Refactor pkg into modular packages
This commit is contained in:
@@ -2,37 +2,37 @@
|
|||||||
|
|
||||||
## Phase 1: Create pkg/fetch
|
## Phase 1: Create pkg/fetch
|
||||||
|
|
||||||
- [ ] 1.1 Create `pkg/fetch/fetch.go`
|
- [x] 1.1 Create `pkg/fetch/fetch.go`
|
||||||
- [ ] 1.2 Move `AURResponse`, `AURPackage`, `PackageInfo` structs to fetch
|
- [x] 1.2 Move `AURResponse`, `AURPackage`, `PackageInfo` structs to fetch
|
||||||
- [ ] 1.3 Move `buildLocalPkgMap()` to fetch as `Fetcher.buildLocalPkgMap()`
|
- [x] 1.3 Move `buildLocalPkgMap()` to fetch as `Fetcher.buildLocalPkgMap()`
|
||||||
- [ ] 1.4 Move `checkSyncDBs()` to fetch as `Fetcher.checkSyncDBs()`
|
- [x] 1.4 Move `checkSyncDBs()` to fetch as `Fetcher.checkSyncDBs()`
|
||||||
- [ ] 1.5 Move `resolvePackages()` to fetch as `Fetcher.Resolve()`
|
- [x] 1.5 Move `resolvePackages()` to fetch as `Fetcher.Resolve()`
|
||||||
- [ ] 1.6 Move AUR cache methods (`ensureAURCache`, `fetchAURInfo`) to fetch
|
- [x] 1.6 Move AUR cache methods (`ensureAURCache`, `fetchAURInfo`) to fetch
|
||||||
- [ ] 1.7 Add `New()` and `Close()` to Fetcher
|
- [x] 1.7 Add `New()` and `Close()` to Fetcher
|
||||||
- [ ] 1.8 Add `ListOrphans()` to Fetcher
|
- [x] 1.8 Add `ListOrphans()` to Fetcher
|
||||||
|
|
||||||
## Phase 2: Refactor pkg/pacman
|
## Phase 2: Refactor pkg/pacman
|
||||||
|
|
||||||
- [ ] 2.1 Remove from pacman.go (now in fetch):
|
- [x] 2.1 Remove from pacman.go (now in fetch):
|
||||||
- `buildLocalPkgMap()`
|
- `buildLocalPkgMap()`
|
||||||
- `checkSyncDBs()`
|
- `checkSyncDBs()`
|
||||||
- `resolvePackages()`
|
- `resolvePackages()`
|
||||||
- `ensureAURCache()`
|
- `ensureAURCache()`
|
||||||
- `fetchAURInfo()`
|
- `fetchAURInfo()`
|
||||||
- `AURResponse`, `AURPackage`, `PackageInfo` structs
|
- `AURResponse`, `AURPackage`, `PackageInfo` structs
|
||||||
- [ ] 2.2 Remove `IsDBFresh()` and `SyncDB()` (use validation instead)
|
- [x] 2.2 Remove `IsDBFresh()` and `SyncDB()` (use validation instead)
|
||||||
- [ ] 2.3 Update imports in pacman.go to include fetch package
|
- [x] 2.3 Update imports in pacman.go to include fetch package
|
||||||
- [ ] 2.4 Update `Sync()` to use `fetch.Fetcher` for resolution
|
- [x] 2.4 Update `Sync()` to use `fetch.Fetcher` for resolution
|
||||||
- [ ] 2.5 Update `DryRun()` to call `fetcher.ListOrphans()` instead of duplicate call
|
- [x] 2.5 Update `DryRun()` to call `fetcher.ListOrphans()` instead of duplicate call
|
||||||
- [ ] 2.6 Update `CleanupOrphans()` to call `fetcher.ListOrphans()` instead of duplicate call
|
- [x] 2.6 Update `CleanupOrphans()` to call `fetcher.ListOrphans()` instead of duplicate call
|
||||||
|
|
||||||
## Phase 3: Clean Up Validation
|
## Phase 3: Clean Up Validation
|
||||||
|
|
||||||
- [ ] 3.1 Keep `validation.CheckDBFreshness()` as-is
|
- [x] 3.1 Keep `validation.CheckDBFreshness()` as-is
|
||||||
- [ ] 3.2 Remove any remaining DB freshness duplication
|
- [x] 3.2 Remove any remaining DB freshness duplication
|
||||||
|
|
||||||
## Phase 4: Verify
|
## Phase 4: Verify
|
||||||
|
|
||||||
- [ ] 4.1 Run tests (if any exist)
|
- [x] 4.1 Run tests (if any exist)
|
||||||
- [ ] 4.2 Build: `go build ./...`
|
- [x] 4.2 Build: `go build ./...`
|
||||||
- [ ] 4.3 Verify CLI still works: test dry-run, sync, orphan cleanup
|
- [x] 4.3 Verify CLI still works: test dry-run, sync, orphan cleanup
|
||||||
@@ -0,0 +1,345 @@
|
|||||||
|
package fetch
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/Jguer/dyalpm"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
Root = "/"
|
||||||
|
LockFile = "/var/lib/pacman/db.lock"
|
||||||
|
AURInfoURL = "https://aur.archlinux.org/rpc?v=5&type=info"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Fetcher struct {
|
||||||
|
aurCache map[string]AURPackage
|
||||||
|
handle dyalpm.Handle
|
||||||
|
localDB dyalpm.Database
|
||||||
|
syncDBs []dyalpm.Database
|
||||||
|
}
|
||||||
|
|
||||||
|
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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() (*Fetcher, error) {
|
||||||
|
start := time.Now()
|
||||||
|
fmt.Fprintf(os.Stderr, "[debug] Fetcher New: starting...\n")
|
||||||
|
|
||||||
|
handle, err := dyalpm.Initialize(Root, "/var/lib/pacman")
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to initialize alpm: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
localDB, err := handle.LocalDB()
|
||||||
|
if err != nil {
|
||||||
|
handle.Release()
|
||||||
|
return nil, fmt.Errorf("failed to get local database: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
syncDBs, err := handle.SyncDBs()
|
||||||
|
if err != nil {
|
||||||
|
handle.Release()
|
||||||
|
return nil, fmt.Errorf("failed to get sync databases: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(syncDBs) == 0 {
|
||||||
|
syncDBs, err = registerSyncDBs(handle)
|
||||||
|
if err != nil {
|
||||||
|
handle.Release()
|
||||||
|
return nil, fmt.Errorf("failed to register sync databases: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(os.Stderr, "[debug] Fetcher New: done (%.2fs)\n", time.Since(start).Seconds())
|
||||||
|
return &Fetcher{
|
||||||
|
aurCache: make(map[string]AURPackage),
|
||||||
|
handle: handle,
|
||||||
|
localDB: localDB,
|
||||||
|
syncDBs: syncDBs,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Fetcher) Close() error {
|
||||||
|
if f.handle != nil {
|
||||||
|
f.handle.Release()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Fetcher) GetAURPackage(name string) (AURPackage, bool) {
|
||||||
|
pkg, ok := f.aurCache[name]
|
||||||
|
return pkg, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Fetcher) BuildLocalPkgMap() (map[string]interface{}, error) {
|
||||||
|
localPkgs, err := f.buildLocalPkgMap()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := make(map[string]interface{})
|
||||||
|
for k, v := range localPkgs {
|
||||||
|
result[k] = v
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func registerSyncDBs(handle dyalpm.Handle) ([]dyalpm.Database, error) {
|
||||||
|
fmt.Fprintf(os.Stderr, "[debug] registerSyncDBs: starting...\n")
|
||||||
|
|
||||||
|
repos := []string{"core", "extra", "multilib"}
|
||||||
|
var dbs []dyalpm.Database
|
||||||
|
|
||||||
|
for _, repo := range repos {
|
||||||
|
db, err := handle.RegisterSyncDB(repo, 0)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
count := 0
|
||||||
|
db.PkgCache().ForEach(func(pkg dyalpm.Package) error {
|
||||||
|
count++
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if count > 0 {
|
||||||
|
dbs = append(dbs, db)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(os.Stderr, "[debug] registerSyncDBs: done (%d dbs)\n", len(dbs))
|
||||||
|
return dbs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Fetcher) buildLocalPkgMap() (map[string]dyalpm.Package, error) {
|
||||||
|
start := time.Now()
|
||||||
|
fmt.Fprintf(os.Stderr, "[debug] buildLocalPkgMap: starting...\n")
|
||||||
|
|
||||||
|
localPkgs := make(map[string]dyalpm.Package)
|
||||||
|
|
||||||
|
err := f.localDB.PkgCache().ForEach(func(pkg dyalpm.Package) error {
|
||||||
|
localPkgs[pkg.Name()] = pkg
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to iterate local package cache: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(os.Stderr, "[debug] buildLocalPkgMap: done (%.2fs)\n", time.Since(start).Seconds())
|
||||||
|
return localPkgs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Fetcher) checkSyncDBs(pkgNames []string) (map[string]dyalpm.Package, error) {
|
||||||
|
start := time.Now()
|
||||||
|
fmt.Fprintf(os.Stderr, "[debug] checkSyncDBs: starting...\n")
|
||||||
|
|
||||||
|
syncPkgs := make(map[string]dyalpm.Package)
|
||||||
|
pkgSet := make(map[string]bool)
|
||||||
|
for _, name := range pkgNames {
|
||||||
|
pkgSet[name] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, db := range f.syncDBs {
|
||||||
|
err := db.PkgCache().ForEach(func(pkg dyalpm.Package) error {
|
||||||
|
if pkgSet[pkg.Name()] {
|
||||||
|
if _, exists := syncPkgs[pkg.Name()]; !exists {
|
||||||
|
syncPkgs[pkg.Name()] = pkg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to iterate sync database %s: %w", db.Name(), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(os.Stderr, "[debug] checkSyncDBs: done (%.2fs)\n", time.Since(start).Seconds())
|
||||||
|
return syncPkgs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Fetcher) Resolve(packages []string) (map[string]*PackageInfo, error) {
|
||||||
|
start := time.Now()
|
||||||
|
fmt.Fprintf(os.Stderr, "[debug] Resolve: starting...\n")
|
||||||
|
|
||||||
|
result := make(map[string]*PackageInfo)
|
||||||
|
|
||||||
|
localPkgs, err := f.buildLocalPkgMap()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(os.Stderr, "[debug] Resolve: local pkgs built (%.2fs)\n", time.Since(start).Seconds())
|
||||||
|
|
||||||
|
var notInLocal []string
|
||||||
|
for _, pkg := range packages {
|
||||||
|
if localPkg, ok := localPkgs[pkg]; ok {
|
||||||
|
result[pkg] = &PackageInfo{
|
||||||
|
Name: pkg,
|
||||||
|
Exists: true,
|
||||||
|
InAUR: false,
|
||||||
|
Installed: true,
|
||||||
|
syncPkg: localPkg,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
notInLocal = append(notInLocal, pkg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(notInLocal) > 0 {
|
||||||
|
syncPkgs, err := f.checkSyncDBs(notInLocal)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(os.Stderr, "[debug] Resolve: sync db checked (%.2fs)\n", time.Since(start).Seconds())
|
||||||
|
|
||||||
|
var notInSync []string
|
||||||
|
for _, pkg := range notInLocal {
|
||||||
|
if syncPkg, ok := syncPkgs[pkg]; ok {
|
||||||
|
result[pkg] = &PackageInfo{
|
||||||
|
Name: pkg,
|
||||||
|
Exists: true,
|
||||||
|
InAUR: false,
|
||||||
|
Installed: false,
|
||||||
|
syncPkg: syncPkg,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
notInSync = append(notInSync, pkg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(notInSync) > 0 {
|
||||||
|
f.ensureAURCache(notInSync)
|
||||||
|
fmt.Fprintf(os.Stderr, "[debug] Resolve: AUR cache ensured (%.2fs)\n", time.Since(start).Seconds())
|
||||||
|
|
||||||
|
var unfound []string
|
||||||
|
for _, pkg := range notInSync {
|
||||||
|
if aurInfo, ok := f.aurCache[pkg]; ok {
|
||||||
|
result[pkg] = &PackageInfo{
|
||||||
|
Name: pkg,
|
||||||
|
Exists: true,
|
||||||
|
InAUR: true,
|
||||||
|
Installed: false,
|
||||||
|
AURInfo: &aurInfo,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unfound = append(unfound, pkg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(unfound) > 0 {
|
||||||
|
return nil, fmt.Errorf("package(s) not found: %s", strings.Join(unfound, ", "))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(os.Stderr, "[debug] Resolve: done (%.2fs)\n", time.Since(start).Seconds())
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Fetcher) ensureAURCache(packages []string) {
|
||||||
|
start := time.Now()
|
||||||
|
fmt.Fprintf(os.Stderr, "[debug] ensureAURCache: starting...\n")
|
||||||
|
|
||||||
|
if len(packages) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var uncached []string
|
||||||
|
for _, pkg := range packages {
|
||||||
|
if _, ok := f.aurCache[pkg]; !ok {
|
||||||
|
uncached = append(uncached, pkg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(uncached) == 0 {
|
||||||
|
fmt.Fprintf(os.Stderr, "[debug] ensureAURCache: done (%.2fs)\n", time.Since(start).Seconds())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
f.fetchAURInfo(uncached)
|
||||||
|
fmt.Fprintf(os.Stderr, "[debug] ensureAURCache: done (%.2fs)\n", time.Since(start).Seconds())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Fetcher) fetchAURInfo(packages []string) map[string]AURPackage {
|
||||||
|
start := time.Now()
|
||||||
|
fmt.Fprintf(os.Stderr, "[debug] fetchAURInfo: starting...\n")
|
||||||
|
|
||||||
|
result := make(map[string]AURPackage)
|
||||||
|
|
||||||
|
if len(packages) == 0 {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
v := url.Values{}
|
||||||
|
for _, pkg := range packages {
|
||||||
|
v.Add("arg[]", pkg)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := http.Get(AURInfoURL + "&" + v.Encode())
|
||||||
|
if err != nil {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
var aurResp AURResponse
|
||||||
|
if err := json.Unmarshal(body, &aurResp); err != nil {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, r := range aurResp.Results {
|
||||||
|
f.aurCache[r.Name] = r
|
||||||
|
result[r.Name] = r
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(os.Stderr, "[debug] fetchAURInfo: done (%.2fs)\n", time.Since(start).Seconds())
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Fetcher) ListOrphans() ([]string, error) {
|
||||||
|
start := time.Now()
|
||||||
|
fmt.Fprintf(os.Stderr, "[debug] ListOrphans: starting...\n")
|
||||||
|
|
||||||
|
cmd := exec.Command("pacman", "-Qdtq")
|
||||||
|
orphans, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
list := strings.TrimSpace(string(orphans))
|
||||||
|
if list == "" {
|
||||||
|
fmt.Fprintf(os.Stderr, "[debug] ListOrphans: done (%.2fs)\n", time.Since(start).Seconds())
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(os.Stderr, "[debug] ListOrphans: done (%.2fs)\n", time.Since(start).Seconds())
|
||||||
|
return strings.Split(list, "\n"), nil
|
||||||
|
}
|
||||||
+36
-383
@@ -1,278 +1,19 @@
|
|||||||
package pacman
|
package pacman
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Jguer/dyalpm"
|
"github.com/Riyyi/declpac/pkg/fetch"
|
||||||
"github.com/Riyyi/declpac/pkg/output"
|
"github.com/Riyyi/declpac/pkg/output"
|
||||||
|
"github.com/Riyyi/declpac/pkg/validation"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
func MarkAllAsDeps() error {
|
||||||
Root = "/"
|
|
||||||
LockFile = "/var/lib/pacman/db.lock"
|
|
||||||
AURInfoURL = "https://aur.archlinux.org/rpc?v=5&type=info"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Pac struct {
|
|
||||||
aurCache map[string]AURPackage
|
|
||||||
handle dyalpm.Handle
|
|
||||||
localDB dyalpm.Database
|
|
||||||
syncDBs []dyalpm.Database
|
|
||||||
}
|
|
||||||
|
|
||||||
func New() (*Pac, error) {
|
|
||||||
start := time.Now()
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] New: starting...\n")
|
|
||||||
|
|
||||||
handle, err := dyalpm.Initialize(Root, "/var/lib/pacman")
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to initialize alpm: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
localDB, err := handle.LocalDB()
|
|
||||||
if err != nil {
|
|
||||||
handle.Release()
|
|
||||||
return nil, fmt.Errorf("failed to get local database: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
syncDBs, err := handle.SyncDBs()
|
|
||||||
if err != nil {
|
|
||||||
handle.Release()
|
|
||||||
return nil, fmt.Errorf("failed to get sync databases: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(syncDBs) == 0 {
|
|
||||||
syncDBs, err = registerSyncDBs(handle)
|
|
||||||
if err != nil {
|
|
||||||
handle.Release()
|
|
||||||
return nil, fmt.Errorf("failed to register sync databases: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] New: done (%.2fs)\n", time.Since(start).Seconds())
|
|
||||||
return &Pac{
|
|
||||||
aurCache: make(map[string]AURPackage),
|
|
||||||
handle: handle,
|
|
||||||
localDB: localDB,
|
|
||||||
syncDBs: syncDBs,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Pac) Close() error {
|
|
||||||
if p.handle != nil {
|
|
||||||
p.handle.Release()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func registerSyncDBs(handle dyalpm.Handle) ([]dyalpm.Database, error) {
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] registerSyncDBs: starting...\n")
|
|
||||||
|
|
||||||
repos := []string{"core", "extra", "multilib"}
|
|
||||||
var dbs []dyalpm.Database
|
|
||||||
|
|
||||||
for _, repo := range repos {
|
|
||||||
db, err := handle.RegisterSyncDB(repo, 0)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
count := 0
|
|
||||||
db.PkgCache().ForEach(func(pkg dyalpm.Package) error {
|
|
||||||
count++
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
if count > 0 {
|
|
||||||
dbs = append(dbs, db)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] registerSyncDBs: done (%d dbs)\n", len(dbs))
|
|
||||||
return dbs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type PackageInfo struct {
|
|
||||||
Name string
|
|
||||||
InAUR bool
|
|
||||||
Exists bool
|
|
||||||
Installed bool
|
|
||||||
AURInfo *AURPackage
|
|
||||||
syncPkg dyalpm.Package
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Pac) buildLocalPkgMap() (map[string]dyalpm.Package, error) {
|
|
||||||
start := time.Now()
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] buildLocalPkgMap: starting...\n")
|
|
||||||
|
|
||||||
localPkgs := make(map[string]dyalpm.Package)
|
|
||||||
|
|
||||||
err := p.localDB.PkgCache().ForEach(func(pkg dyalpm.Package) error {
|
|
||||||
localPkgs[pkg.Name()] = pkg
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to iterate local package cache: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] buildLocalPkgMap: done (%.2fs)\n", time.Since(start).Seconds())
|
|
||||||
return localPkgs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Pac) checkSyncDBs(pkgNames []string) (map[string]dyalpm.Package, error) {
|
|
||||||
start := time.Now()
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] checkSyncDBs: starting...\n")
|
|
||||||
|
|
||||||
syncPkgs := make(map[string]dyalpm.Package)
|
|
||||||
pkgSet := make(map[string]bool)
|
|
||||||
for _, name := range pkgNames {
|
|
||||||
pkgSet[name] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, db := range p.syncDBs {
|
|
||||||
err := db.PkgCache().ForEach(func(pkg dyalpm.Package) error {
|
|
||||||
if pkgSet[pkg.Name()] {
|
|
||||||
if _, exists := syncPkgs[pkg.Name()]; !exists {
|
|
||||||
syncPkgs[pkg.Name()] = pkg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to iterate sync database %s: %w", db.Name(), err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] checkSyncDBs: done (%.2fs)\n", time.Since(start).Seconds())
|
|
||||||
return syncPkgs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Pac) resolvePackages(packages []string) (map[string]*PackageInfo, error) {
|
|
||||||
start := time.Now()
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] resolvePackages: starting...\n")
|
|
||||||
|
|
||||||
result := make(map[string]*PackageInfo)
|
|
||||||
|
|
||||||
localPkgs, err := p.buildLocalPkgMap()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] resolvePackages: local pkgs built (%.2fs)\n", time.Since(start).Seconds())
|
|
||||||
|
|
||||||
var notInLocal []string
|
|
||||||
for _, pkg := range packages {
|
|
||||||
if localPkg, ok := localPkgs[pkg]; ok {
|
|
||||||
result[pkg] = &PackageInfo{
|
|
||||||
Name: pkg,
|
|
||||||
Exists: true,
|
|
||||||
InAUR: false,
|
|
||||||
Installed: true,
|
|
||||||
syncPkg: localPkg,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
notInLocal = append(notInLocal, pkg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(notInLocal) > 0 {
|
|
||||||
syncPkgs, err := p.checkSyncDBs(notInLocal)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] resolvePackages: sync db checked (%.2fs)\n", time.Since(start).Seconds())
|
|
||||||
|
|
||||||
var notInSync []string
|
|
||||||
for _, pkg := range notInLocal {
|
|
||||||
if syncPkg, ok := syncPkgs[pkg]; ok {
|
|
||||||
result[pkg] = &PackageInfo{
|
|
||||||
Name: pkg,
|
|
||||||
Exists: true,
|
|
||||||
InAUR: false,
|
|
||||||
Installed: false,
|
|
||||||
syncPkg: syncPkg,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
notInSync = append(notInSync, pkg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(notInSync) > 0 {
|
|
||||||
p.ensureAURCache(notInSync)
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] resolvePackages: AUR cache ensured (%.2fs)\n", time.Since(start).Seconds())
|
|
||||||
|
|
||||||
var unfound []string
|
|
||||||
for _, pkg := range notInSync {
|
|
||||||
if aurInfo, ok := p.aurCache[pkg]; ok {
|
|
||||||
result[pkg] = &PackageInfo{
|
|
||||||
Name: pkg,
|
|
||||||
Exists: true,
|
|
||||||
InAUR: true,
|
|
||||||
Installed: false,
|
|
||||||
AURInfo: &aurInfo,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unfound = append(unfound, pkg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(unfound) > 0 {
|
|
||||||
return nil, fmt.Errorf("package(s) not found: %s", strings.Join(unfound, ", "))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] resolvePackages: done (%.2fs)\n", time.Since(start).Seconds())
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
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"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Pac) IsDBFresh() (bool, error) {
|
|
||||||
start := time.Now()
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] IsDBFresh: starting...\n")
|
|
||||||
|
|
||||||
info, err := os.Stat(LockFile)
|
|
||||||
if err != nil {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
age := time.Since(info.ModTime())
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] IsDBFresh: done (%.2fs)\n", time.Since(start).Seconds())
|
|
||||||
return age < 24*time.Hour, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Pac) SyncDB() error {
|
|
||||||
start := time.Now()
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] SyncDB: starting...\n")
|
|
||||||
|
|
||||||
cmd := exec.Command("pacman", "-Syy")
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
err := cmd.Run()
|
|
||||||
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] SyncDB: done (%.2fs)\n", time.Since(start).Seconds())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Pac) MarkAllAsDeps() error {
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
fmt.Fprintf(os.Stderr, "[debug] MarkAllAsDeps: starting...\n")
|
fmt.Fprintf(os.Stderr, "[debug] MarkAllAsDeps: starting...\n")
|
||||||
|
|
||||||
@@ -285,7 +26,7 @@ func (p *Pac) MarkAllAsDeps() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pac) MarkAsExplicit(packages []string) error {
|
func MarkAsExplicit(packages []string) error {
|
||||||
if len(packages) == 0 {
|
if len(packages) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -311,24 +52,20 @@ func Sync(packages []string) (*output.Result, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := New()
|
if err := validation.CheckDBFreshness(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
fmt.Fprintf(os.Stderr, "[debug] Sync: database fresh (%.2fs)\n", time.Since(start).Seconds())
|
||||||
|
|
||||||
|
f, err := fetch.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer p.Close()
|
defer f.Close()
|
||||||
fmt.Fprintf(os.Stderr, "[debug] Sync: initialized pacman (%.2fs)\n", time.Since(start).Seconds())
|
fmt.Fprintf(os.Stderr, "[debug] Sync: initialized fetcher (%.2fs)\n", time.Since(start).Seconds())
|
||||||
|
|
||||||
fresh, err := p.IsDBFresh()
|
|
||||||
if err != nil || !fresh {
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] Sync: syncing database...\n")
|
|
||||||
if err := p.SyncDB(); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to sync database: %w", err)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] Sync: database synced (%.2fs)\n", time.Since(start).Seconds())
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] Sync: categorizing packages...\n")
|
fmt.Fprintf(os.Stderr, "[debug] Sync: categorizing packages...\n")
|
||||||
pacmanPkgs, aurPkgs, err := p.categorizePackages(packages)
|
pacmanPkgs, aurPkgs, err := categorizePackages(f, packages)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -336,7 +73,7 @@ func Sync(packages []string) (*output.Result, error) {
|
|||||||
|
|
||||||
if len(pacmanPkgs) > 0 {
|
if len(pacmanPkgs) > 0 {
|
||||||
fmt.Fprintf(os.Stderr, "[debug] Sync: syncing %d pacman packages...\n", len(pacmanPkgs))
|
fmt.Fprintf(os.Stderr, "[debug] Sync: syncing %d pacman packages...\n", len(pacmanPkgs))
|
||||||
_, err = p.SyncPackages(pacmanPkgs)
|
_, err = SyncPackages(pacmanPkgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -345,25 +82,25 @@ func Sync(packages []string) (*output.Result, error) {
|
|||||||
|
|
||||||
for _, pkg := range aurPkgs {
|
for _, pkg := range aurPkgs {
|
||||||
fmt.Fprintf(os.Stderr, "[debug] Sync: installing AUR package %s...\n", pkg)
|
fmt.Fprintf(os.Stderr, "[debug] Sync: installing AUR package %s...\n", pkg)
|
||||||
if err := p.InstallAUR(pkg); err != nil {
|
if err := InstallAUR(f, pkg); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
fmt.Fprintf(os.Stderr, "[debug] Sync: AUR package %s installed (%.2fs)\n", pkg, time.Since(start).Seconds())
|
fmt.Fprintf(os.Stderr, "[debug] Sync: AUR package %s installed (%.2fs)\n", pkg, time.Since(start).Seconds())
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] Sync: marking all as deps...\n")
|
fmt.Fprintf(os.Stderr, "[debug] Sync: marking all as deps...\n")
|
||||||
if err := p.MarkAllAsDeps(); err != nil {
|
if err := MarkAllAsDeps(); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "warning: could not mark all as deps: %v\n", err)
|
fmt.Fprintf(os.Stderr, "warning: could not mark all as deps: %v\n", err)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(os.Stderr, "[debug] Sync: all marked as deps (%.2fs)\n", time.Since(start).Seconds())
|
fmt.Fprintf(os.Stderr, "[debug] Sync: all marked as deps (%.2fs)\n", time.Since(start).Seconds())
|
||||||
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] Sync: marking state packages as explicit...\n")
|
fmt.Fprintf(os.Stderr, "[debug] Sync: marking state packages as explicit...\n")
|
||||||
if err := p.MarkAsExplicit(packages); err != nil {
|
if err := MarkAsExplicit(packages); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "warning: could not mark state packages as explicit: %v\n", err)
|
fmt.Fprintf(os.Stderr, "warning: could not mark state packages as explicit: %v\n", err)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(os.Stderr, "[debug] Sync: state packages marked as explicit (%.2fs)\n", time.Since(start).Seconds())
|
fmt.Fprintf(os.Stderr, "[debug] Sync: state packages marked as explicit (%.2fs)\n", time.Since(start).Seconds())
|
||||||
|
|
||||||
removed, err := p.CleanupOrphans()
|
removed, err := CleanupOrphans()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -378,11 +115,11 @@ func Sync(packages []string) (*output.Result, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pac) categorizePackages(packages []string) (pacmanPkgs, aurPkgs []string, err error) {
|
func categorizePackages(f *fetch.Fetcher, packages []string) (pacmanPkgs, aurPkgs []string, err error) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
fmt.Fprintf(os.Stderr, "[debug] categorizePackages: starting...\n")
|
fmt.Fprintf(os.Stderr, "[debug] categorizePackages: starting...\n")
|
||||||
|
|
||||||
resolved, err := p.resolvePackages(packages)
|
resolved, err := f.Resolve(packages)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@@ -404,75 +141,11 @@ func (p *Pac) categorizePackages(packages []string) (pacmanPkgs, aurPkgs []strin
|
|||||||
return pacmanPkgs, aurPkgs, nil
|
return pacmanPkgs, aurPkgs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pac) ensureAURCache(packages []string) {
|
func InstallAUR(f *fetch.Fetcher, pkgName string) error {
|
||||||
start := time.Now()
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] ensureAURCache: starting...\n")
|
|
||||||
|
|
||||||
if len(packages) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var uncached []string
|
|
||||||
for _, pkg := range packages {
|
|
||||||
if _, ok := p.aurCache[pkg]; !ok {
|
|
||||||
uncached = append(uncached, pkg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(uncached) == 0 {
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] ensureAURCache: done (%.2fs)\n", time.Since(start).Seconds())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
p.fetchAURInfo(uncached)
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] ensureAURCache: done (%.2fs)\n", time.Since(start).Seconds())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Pac) fetchAURInfo(packages []string) map[string]AURPackage {
|
|
||||||
start := time.Now()
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] fetchAURInfo: starting...\n")
|
|
||||||
|
|
||||||
result := make(map[string]AURPackage)
|
|
||||||
|
|
||||||
if len(packages) == 0 {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
v := url.Values{}
|
|
||||||
for _, pkg := range packages {
|
|
||||||
v.Add("arg[]", pkg)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := http.Get(AURInfoURL + "&" + v.Encode())
|
|
||||||
if err != nil {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
body, err := io.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
var aurResp AURResponse
|
|
||||||
if err := json.Unmarshal(body, &aurResp); err != nil {
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, r := range aurResp.Results {
|
|
||||||
p.aurCache[r.Name] = r
|
|
||||||
result[r.Name] = r
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] fetchAURInfo: done (%.2fs)\n", time.Since(start).Seconds())
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Pac) InstallAUR(pkgName string) error {
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
fmt.Fprintf(os.Stderr, "[debug] InstallAUR: starting...\n")
|
fmt.Fprintf(os.Stderr, "[debug] InstallAUR: starting...\n")
|
||||||
|
|
||||||
aurInfo, ok := p.aurCache[pkgName]
|
aurInfo, ok := f.GetAURPackage(pkgName)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("AUR package not found in cache: %s", pkgName)
|
return fmt.Errorf("AUR package not found in cache: %s", pkgName)
|
||||||
}
|
}
|
||||||
@@ -523,7 +196,7 @@ func getInstalledCount() (int, error) {
|
|||||||
return count, nil
|
return count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pac) SyncPackages(packages []string) (int, error) {
|
func SyncPackages(packages []string) (int, error) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
fmt.Fprintf(os.Stderr, "[debug] SyncPackages: starting...\n")
|
fmt.Fprintf(os.Stderr, "[debug] SyncPackages: starting...\n")
|
||||||
|
|
||||||
@@ -541,18 +214,18 @@ func (p *Pac) SyncPackages(packages []string) (int, error) {
|
|||||||
return len(matches), nil
|
return len(matches), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pac) CleanupOrphans() (int, error) {
|
func CleanupOrphans() (int, error) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
fmt.Fprintf(os.Stderr, "[debug] CleanupOrphans: starting...\n")
|
fmt.Fprintf(os.Stderr, "[debug] CleanupOrphans: starting...\n")
|
||||||
|
|
||||||
listCmd := exec.Command("pacman", "-Qdtq")
|
f, err := fetch.New()
|
||||||
orphans, err := listCmd.Output()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil
|
return 0, err
|
||||||
}
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
orphanList := strings.TrimSpace(string(orphans))
|
orphans, err := f.ListOrphans()
|
||||||
if orphanList == "" {
|
if err != nil || len(orphans) == 0 {
|
||||||
fmt.Fprintf(os.Stderr, "[debug] CleanupOrphans: done (%.2fs)\n", time.Since(start).Seconds())
|
fmt.Fprintf(os.Stderr, "[debug] CleanupOrphans: done (%.2fs)\n", time.Since(start).Seconds())
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
@@ -563,7 +236,7 @@ func (p *Pac) CleanupOrphans() (int, error) {
|
|||||||
return 0, fmt.Errorf("%s: %s", err, output)
|
return 0, fmt.Errorf("%s: %s", err, output)
|
||||||
}
|
}
|
||||||
|
|
||||||
count := strings.Count(orphanList, "\n") + 1
|
count := len(orphans)
|
||||||
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] CleanupOrphans: done (%.2fs)\n", time.Since(start).Seconds())
|
fmt.Fprintf(os.Stderr, "[debug] CleanupOrphans: done (%.2fs)\n", time.Since(start).Seconds())
|
||||||
return count, nil
|
return count, nil
|
||||||
@@ -573,20 +246,20 @@ func DryRun(packages []string) (*output.Result, error) {
|
|||||||
start := time.Now()
|
start := time.Now()
|
||||||
fmt.Fprintf(os.Stderr, "[debug] DryRun: starting...\n")
|
fmt.Fprintf(os.Stderr, "[debug] DryRun: starting...\n")
|
||||||
|
|
||||||
p, err := New()
|
f, err := fetch.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer p.Close()
|
defer f.Close()
|
||||||
fmt.Fprintf(os.Stderr, "[debug] DryRun: initialized pacman (%.2fs)\n", time.Since(start).Seconds())
|
fmt.Fprintf(os.Stderr, "[debug] DryRun: initialized fetcher (%.2fs)\n", time.Since(start).Seconds())
|
||||||
|
|
||||||
resolved, err := p.resolvePackages(packages)
|
resolved, err := f.Resolve(packages)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
fmt.Fprintf(os.Stderr, "[debug] DryRun: packages resolved (%.2fs)\n", time.Since(start).Seconds())
|
fmt.Fprintf(os.Stderr, "[debug] DryRun: packages resolved (%.2fs)\n", time.Since(start).Seconds())
|
||||||
|
|
||||||
localPkgs, err := p.buildLocalPkgMap()
|
localPkgs, err := f.BuildLocalPkgMap()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -608,7 +281,7 @@ func DryRun(packages []string) (*output.Result, error) {
|
|||||||
}
|
}
|
||||||
fmt.Fprintf(os.Stderr, "[debug] DryRun: packages categorized (%.2fs)\n", time.Since(start).Seconds())
|
fmt.Fprintf(os.Stderr, "[debug] DryRun: packages categorized (%.2fs)\n", time.Since(start).Seconds())
|
||||||
|
|
||||||
orphans, err := p.listOrphans()
|
orphans, err := f.ListOrphans()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -622,23 +295,3 @@ func DryRun(packages []string) (*output.Result, error) {
|
|||||||
ToRemove: orphans,
|
ToRemove: orphans,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pac) listOrphans() ([]string, error) {
|
|
||||||
start := time.Now()
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] listOrphans: starting...\n")
|
|
||||||
|
|
||||||
cmd := exec.Command("pacman", "-Qdtq")
|
|
||||||
orphans, err := cmd.Output()
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
list := strings.TrimSpace(string(orphans))
|
|
||||||
if list == "" {
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] listOrphans: done (%.2fs)\n", time.Since(start).Seconds())
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(os.Stderr, "[debug] listOrphans: done (%.2fs)\n", time.Since(start).Seconds())
|
|
||||||
return strings.Split(list, "\n"), nil
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user