2017-04-29 17:12:12 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2021-05-13 05:27:24 +00:00
|
|
|
"context"
|
2017-04-29 17:12:12 +00:00
|
|
|
"fmt"
|
2022-02-06 09:53:34 +00:00
|
|
|
"io/fs"
|
|
|
|
"path/filepath"
|
2017-04-29 17:12:12 +00:00
|
|
|
|
2021-05-13 05:27:24 +00:00
|
|
|
aur "github.com/Jguer/aur"
|
2020-10-01 11:38:03 +00:00
|
|
|
alpm "github.com/Jguer/go-alpm/v2"
|
2023-07-23 17:29:01 +00:00
|
|
|
mapset "github.com/deckarep/golang-set/v2"
|
2020-05-02 14:17:20 +00:00
|
|
|
|
2023-03-07 21:04:06 +00:00
|
|
|
"github.com/Jguer/yay/v12/pkg/db"
|
|
|
|
"github.com/Jguer/yay/v12/pkg/query"
|
2023-08-06 19:39:41 +00:00
|
|
|
"github.com/Jguer/yay/v12/pkg/runtime"
|
2023-03-07 21:04:06 +00:00
|
|
|
"github.com/Jguer/yay/v12/pkg/settings"
|
|
|
|
"github.com/Jguer/yay/v12/pkg/settings/parser"
|
|
|
|
"github.com/Jguer/yay/v12/pkg/text"
|
2017-04-29 17:12:12 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// SyncSearch presents a query to the local repos and to the AUR.
|
2022-11-13 13:29:00 +00:00
|
|
|
func syncSearch(ctx context.Context, pkgS []string,
|
2022-03-06 23:48:15 +00:00
|
|
|
dbExecutor db.Executor, queryBuilder query.Builder, verbose bool,
|
|
|
|
) error {
|
2022-11-13 13:29:00 +00:00
|
|
|
queryBuilder.Execute(ctx, dbExecutor, pkgS)
|
2017-04-29 17:12:12 +00:00
|
|
|
|
2021-10-16 08:07:39 +00:00
|
|
|
searchMode := query.Minimal
|
|
|
|
if verbose {
|
|
|
|
searchMode = query.Detailed
|
2018-04-03 05:49:41 +00:00
|
|
|
}
|
|
|
|
|
2023-04-02 00:23:02 +00:00
|
|
|
return queryBuilder.Results(dbExecutor, searchMode)
|
2017-04-29 17:12:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// SyncInfo serves as a pacman -Si for repo packages and AUR packages.
|
2023-08-06 19:39:41 +00:00
|
|
|
func syncInfo(ctx context.Context, run *runtime.Runtime,
|
2023-03-05 21:58:18 +00:00
|
|
|
cmdArgs *parser.Arguments, pkgS []string, dbExecutor db.Executor,
|
|
|
|
) error {
|
2021-08-11 18:13:28 +00:00
|
|
|
var (
|
2022-12-29 18:42:43 +00:00
|
|
|
info []aur.Pkg
|
2021-08-11 18:13:28 +00:00
|
|
|
err error
|
|
|
|
missing = false
|
|
|
|
)
|
|
|
|
|
2023-08-06 19:39:41 +00:00
|
|
|
pkgS = query.RemoveInvalidTargets(run.Logger, pkgS, run.Cfg.Mode)
|
|
|
|
aurS, repoS := packageSlices(pkgS, run.Cfg, dbExecutor)
|
2017-04-29 17:12:12 +00:00
|
|
|
|
2018-02-18 23:46:25 +00:00
|
|
|
if len(aurS) != 0 {
|
2019-02-04 16:56:02 +00:00
|
|
|
noDB := make([]string, 0, len(aurS))
|
2018-03-13 21:36:42 +00:00
|
|
|
|
|
|
|
for _, pkg := range aurS {
|
2020-07-10 00:36:45 +00:00
|
|
|
_, name := text.SplitDBFromName(pkg)
|
2019-02-04 16:56:02 +00:00
|
|
|
noDB = append(noDB, name)
|
2018-03-13 21:36:42 +00:00
|
|
|
}
|
|
|
|
|
2023-08-06 19:39:41 +00:00
|
|
|
info, err = run.AURClient.Get(ctx, &aur.Query{
|
2023-04-11 21:15:21 +00:00
|
|
|
Needles: noDB,
|
2023-05-01 12:52:43 +00:00
|
|
|
By: aur.Name,
|
2023-04-11 21:15:21 +00:00
|
|
|
})
|
2018-02-18 23:46:25 +00:00
|
|
|
if err != nil {
|
2018-06-01 03:20:49 +00:00
|
|
|
missing = true
|
2021-08-11 18:13:28 +00:00
|
|
|
|
2023-08-06 19:39:41 +00:00
|
|
|
run.Logger.Errorln(err)
|
2018-02-18 23:46:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-06 13:50:54 +00:00
|
|
|
if len(repoS) != 0 {
|
2020-07-05 00:45:23 +00:00
|
|
|
arguments := cmdArgs.Copy()
|
|
|
|
arguments.ClearTargets()
|
|
|
|
arguments.AddTarget(repoS...)
|
2021-08-11 18:13:28 +00:00
|
|
|
|
2023-08-06 19:39:41 +00:00
|
|
|
err = run.CmdBuilder.Show(run.CmdBuilder.BuildPacmanCmd(ctx,
|
|
|
|
arguments, run.Cfg.Mode, settings.NoConfirm))
|
2018-01-06 13:50:54 +00:00
|
|
|
if err != nil {
|
2020-05-02 14:17:20 +00:00
|
|
|
return err
|
2018-01-06 13:50:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-01 03:20:49 +00:00
|
|
|
if len(aurS) != len(info) {
|
|
|
|
missing = true
|
|
|
|
}
|
|
|
|
|
2018-05-28 12:43:02 +00:00
|
|
|
if len(info) != 0 {
|
2022-12-29 18:42:43 +00:00
|
|
|
for i := range info {
|
2023-08-06 19:39:41 +00:00
|
|
|
printInfo(run.Logger, run.Cfg, &info[i], cmdArgs.ExistsDouble("i"))
|
2017-07-05 21:30:42 +00:00
|
|
|
}
|
2017-04-29 17:12:12 +00:00
|
|
|
}
|
2018-01-20 22:37:10 +00:00
|
|
|
|
2018-06-01 03:20:49 +00:00
|
|
|
if missing {
|
|
|
|
err = fmt.Errorf("")
|
2018-05-28 12:43:02 +00:00
|
|
|
}
|
|
|
|
|
2020-05-02 14:17:20 +00:00
|
|
|
return err
|
2017-04-29 17:12:12 +00:00
|
|
|
}
|
|
|
|
|
2021-08-11 18:13:28 +00:00
|
|
|
// PackageSlices separates an input slice into aur and repo slices.
|
2023-03-05 21:58:18 +00:00
|
|
|
func packageSlices(toCheck []string, config *settings.Configuration, dbExecutor db.Executor) (aurNames, repoNames []string) {
|
2018-01-17 21:48:23 +00:00
|
|
|
for _, _pkg := range toCheck {
|
2020-07-31 22:01:01 +00:00
|
|
|
dbName, name := text.SplitDBFromName(_pkg)
|
2017-08-02 17:24:03 +00:00
|
|
|
|
2023-03-13 08:48:39 +00:00
|
|
|
if dbName == "aur" || config.Mode == parser.ModeAUR {
|
2021-05-13 05:27:24 +00:00
|
|
|
aurNames = append(aurNames, _pkg)
|
2018-03-13 21:36:42 +00:00
|
|
|
continue
|
2023-03-13 08:48:39 +00:00
|
|
|
} else if dbName != "" || config.Mode == parser.ModeRepo {
|
2021-05-13 05:27:24 +00:00
|
|
|
repoNames = append(repoNames, _pkg)
|
2018-03-13 21:36:42 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2020-12-15 00:29:05 +00:00
|
|
|
if dbExecutor.SyncSatisfierExists(name) ||
|
|
|
|
len(dbExecutor.PackagesFromGroup(name)) != 0 {
|
2021-05-13 05:27:24 +00:00
|
|
|
repoNames = append(repoNames, _pkg)
|
2018-01-17 21:48:23 +00:00
|
|
|
} else {
|
2021-05-13 05:27:24 +00:00
|
|
|
aurNames = append(aurNames, _pkg)
|
2017-08-02 17:24:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-13 05:27:24 +00:00
|
|
|
return aurNames, repoNames
|
2017-08-02 17:24:03 +00:00
|
|
|
}
|
|
|
|
|
2023-07-23 17:29:01 +00:00
|
|
|
// MapSetMap is a Map of Sets.
|
|
|
|
type mapSetMap[T comparable] map[T]mapset.Set[T]
|
|
|
|
|
|
|
|
// Add adds a new value to the Map.
|
|
|
|
// If n is already in the map, then v is appended to the StringSet under that key.
|
|
|
|
// Otherwise a new Set is created containing v.
|
|
|
|
func (mss mapSetMap[T]) Add(n, v T) {
|
|
|
|
if _, ok := mss[n]; !ok {
|
|
|
|
mss[n] = mapset.NewSet[T]()
|
|
|
|
}
|
|
|
|
|
|
|
|
mss[n].Add(v)
|
|
|
|
}
|
|
|
|
|
2017-08-02 17:24:03 +00:00
|
|
|
// HangingPackages returns a list of packages installed as deps
|
|
|
|
// and unneeded by the system
|
2021-08-11 18:13:28 +00:00
|
|
|
// removeOptional decides whether optional dependencies are counted or not.
|
2020-08-16 21:41:38 +00:00
|
|
|
func hangingPackages(removeOptional bool, dbExecutor db.Executor) (hanging []string) {
|
2018-03-23 23:45:46 +00:00
|
|
|
// safePackages represents every package in the system in one of 3 states
|
|
|
|
// State = 0 - Remove package from the system
|
|
|
|
// State = 1 - Keep package in the system; need to iterate over dependencies
|
|
|
|
// State = 2 - Keep package and have iterated over dependencies
|
|
|
|
safePackages := make(map[string]uint8)
|
|
|
|
// provides stores a mapping from the provides name back to the original package name
|
2023-07-23 17:29:01 +00:00
|
|
|
provides := make(mapSetMap[string])
|
2018-03-23 23:45:46 +00:00
|
|
|
|
2020-08-07 16:55:19 +00:00
|
|
|
packages := dbExecutor.LocalPackages()
|
2018-03-23 23:45:46 +00:00
|
|
|
// Mark explicit dependencies and enumerate the provides list
|
2020-08-07 16:55:19 +00:00
|
|
|
for _, pkg := range packages {
|
2018-03-23 23:45:46 +00:00
|
|
|
if pkg.Reason() == alpm.PkgReasonExplicit {
|
|
|
|
safePackages[pkg.Name()] = 1
|
|
|
|
} else {
|
|
|
|
safePackages[pkg.Name()] = 0
|
|
|
|
}
|
|
|
|
|
2020-08-07 16:55:19 +00:00
|
|
|
for _, dep := range dbExecutor.PackageProvides(pkg) {
|
2018-05-07 22:01:39 +00:00
|
|
|
provides.Add(dep.Name, pkg.Name())
|
2020-08-07 16:55:19 +00:00
|
|
|
}
|
2018-03-23 23:45:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
iterateAgain := true
|
2017-08-02 17:24:03 +00:00
|
|
|
|
2020-08-07 16:55:19 +00:00
|
|
|
for iterateAgain {
|
|
|
|
iterateAgain = false
|
2021-08-11 18:13:28 +00:00
|
|
|
|
2020-08-07 16:55:19 +00:00
|
|
|
for _, pkg := range packages {
|
|
|
|
if state := safePackages[pkg.Name()]; state == 0 || state == 2 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
safePackages[pkg.Name()] = 2
|
|
|
|
deps := dbExecutor.PackageDepends(pkg)
|
2021-08-11 18:13:28 +00:00
|
|
|
|
2020-08-07 16:55:19 +00:00
|
|
|
if !removeOptional {
|
|
|
|
deps = append(deps, dbExecutor.PackageOptionalDepends(pkg)...)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update state for dependencies
|
|
|
|
for _, dep := range deps {
|
|
|
|
// Don't assume a dependency is installed
|
|
|
|
state, ok := safePackages[dep.Name]
|
|
|
|
if !ok {
|
|
|
|
// Check if dep is a provides rather than actual package name
|
|
|
|
if pset, ok2 := provides[dep.Name]; ok2 {
|
2023-07-23 17:29:01 +00:00
|
|
|
for p := range pset.Iter() {
|
2020-08-07 16:55:19 +00:00
|
|
|
if safePackages[p] == 0 {
|
|
|
|
iterateAgain = true
|
|
|
|
safePackages[p] = 1
|
|
|
|
}
|
2018-03-24 12:37:31 +00:00
|
|
|
}
|
|
|
|
}
|
2021-08-11 18:13:28 +00:00
|
|
|
|
2020-08-07 16:55:19 +00:00
|
|
|
continue
|
2018-03-23 23:45:46 +00:00
|
|
|
}
|
|
|
|
|
2020-08-07 16:55:19 +00:00
|
|
|
if state == 0 {
|
|
|
|
iterateAgain = true
|
|
|
|
safePackages[dep.Name] = 1
|
|
|
|
}
|
2018-03-23 23:45:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Build list of packages to be removed
|
2020-08-07 16:55:19 +00:00
|
|
|
for _, pkg := range packages {
|
2018-03-23 23:45:46 +00:00
|
|
|
if safePackages[pkg.Name()] == 0 {
|
|
|
|
hanging = append(hanging, pkg.Name())
|
|
|
|
}
|
2020-08-07 16:55:19 +00:00
|
|
|
}
|
2018-03-23 23:45:46 +00:00
|
|
|
|
2020-08-07 16:55:19 +00:00
|
|
|
return hanging
|
2017-08-02 17:24:03 +00:00
|
|
|
}
|
|
|
|
|
2022-02-06 09:53:34 +00:00
|
|
|
func getFolderSize(path string) (size int64) {
|
|
|
|
_ = filepath.WalkDir(path, func(p string, entry fs.DirEntry, err error) error {
|
|
|
|
info, _ := entry.Info()
|
|
|
|
size += info.Size()
|
|
|
|
return nil
|
|
|
|
})
|
2021-08-11 18:13:28 +00:00
|
|
|
|
2022-02-06 09:53:34 +00:00
|
|
|
return size
|
|
|
|
}
|
2020-08-04 20:00:07 +00:00
|
|
|
|
2022-02-06 09:53:34 +00:00
|
|
|
// Statistics returns statistics about packages installed in system.
|
2023-08-06 19:39:41 +00:00
|
|
|
func statistics(run *runtime.Runtime, dbExecutor db.Executor) (res struct {
|
2022-02-06 09:53:34 +00:00
|
|
|
Totaln int
|
|
|
|
Expln int
|
|
|
|
TotalSize int64
|
|
|
|
pacmanCaches map[string]int64
|
|
|
|
yayCache int64
|
2022-03-06 23:48:15 +00:00
|
|
|
},
|
|
|
|
) {
|
2022-02-06 09:53:34 +00:00
|
|
|
for _, pkg := range dbExecutor.LocalPackages() {
|
|
|
|
res.TotalSize += pkg.ISize()
|
|
|
|
res.Totaln++
|
2021-08-11 18:13:28 +00:00
|
|
|
|
2020-08-04 20:00:07 +00:00
|
|
|
if pkg.Reason() == alpm.PkgReasonExplicit {
|
2022-02-06 09:53:34 +00:00
|
|
|
res.Expln++
|
2017-08-02 17:24:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-06 09:53:34 +00:00
|
|
|
res.pacmanCaches = make(map[string]int64)
|
2023-08-06 19:39:41 +00:00
|
|
|
for _, path := range run.PacmanConf.CacheDir {
|
2022-02-06 09:53:34 +00:00
|
|
|
res.pacmanCaches[path] = getFolderSize(path)
|
2017-08-02 17:24:03 +00:00
|
|
|
}
|
|
|
|
|
2023-08-06 19:39:41 +00:00
|
|
|
res.yayCache = getFolderSize(run.Cfg.BuildDir)
|
2022-02-06 09:53:34 +00:00
|
|
|
|
|
|
|
return
|
2017-08-02 17:24:03 +00:00
|
|
|
}
|