2017-04-29 17:12:12 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2020-05-04 07:24:32 +00:00
|
|
|
"errors"
|
2017-04-29 17:12:12 +00:00
|
|
|
"fmt"
|
2018-11-14 12:14:41 +00:00
|
|
|
"os"
|
2017-08-02 17:24:03 +00:00
|
|
|
"sort"
|
|
|
|
"strings"
|
2017-04-29 17:12:12 +00:00
|
|
|
|
2019-04-23 15:53:20 +00:00
|
|
|
alpm "github.com/Jguer/go-alpm"
|
2020-05-04 07:24:32 +00:00
|
|
|
"github.com/leonelquinteros/gotext"
|
2020-05-02 14:17:20 +00:00
|
|
|
rpc "github.com/mikkeloscar/aur"
|
|
|
|
|
2020-07-10 00:36:45 +00:00
|
|
|
"github.com/Jguer/yay/v10/pkg/query"
|
2020-07-05 00:01:08 +00:00
|
|
|
"github.com/Jguer/yay/v10/pkg/settings"
|
2020-06-13 17:29:50 +00:00
|
|
|
"github.com/Jguer/yay/v10/pkg/stringset"
|
|
|
|
"github.com/Jguer/yay/v10/pkg/text"
|
2017-04-29 17:12:12 +00:00
|
|
|
)
|
|
|
|
|
2017-08-02 17:24:03 +00:00
|
|
|
// Query is a collection of Results
|
|
|
|
type aurQuery []rpc.Pkg
|
2017-05-02 15:46:14 +00:00
|
|
|
|
2017-08-02 17:24:03 +00:00
|
|
|
// Query holds the results of a repository search.
|
|
|
|
type repoQuery []alpm.Package
|
|
|
|
|
|
|
|
func (q aurQuery) Len() int {
|
|
|
|
return len(q)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (q aurQuery) Less(i, j int) bool {
|
2018-04-04 20:26:07 +00:00
|
|
|
var result bool
|
|
|
|
|
|
|
|
switch config.SortBy {
|
|
|
|
case "votes":
|
|
|
|
result = q[i].NumVotes > q[j].NumVotes
|
|
|
|
case "popularity":
|
|
|
|
result = q[i].Popularity > q[j].Popularity
|
|
|
|
case "name":
|
2020-07-10 00:36:45 +00:00
|
|
|
result = text.LessRunes([]rune(q[i].Name), []rune(q[j].Name))
|
2018-04-04 20:26:07 +00:00
|
|
|
case "base":
|
2020-07-10 00:36:45 +00:00
|
|
|
result = text.LessRunes([]rune(q[i].PackageBase), []rune(q[j].PackageBase))
|
2018-04-04 20:26:07 +00:00
|
|
|
case "submitted":
|
|
|
|
result = q[i].FirstSubmitted < q[j].FirstSubmitted
|
|
|
|
case "modified":
|
|
|
|
result = q[i].LastModified < q[j].LastModified
|
|
|
|
case "id":
|
|
|
|
result = q[i].ID < q[j].ID
|
|
|
|
case "baseid":
|
|
|
|
result = q[i].PackageBaseID < q[j].PackageBaseID
|
|
|
|
}
|
|
|
|
|
2020-07-05 00:01:08 +00:00
|
|
|
if config.SortMode == settings.BottomUp {
|
2018-04-04 20:26:07 +00:00
|
|
|
return !result
|
2017-08-02 17:24:03 +00:00
|
|
|
}
|
2018-04-04 20:26:07 +00:00
|
|
|
|
|
|
|
return result
|
2017-08-02 17:24:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (q aurQuery) Swap(i, j int) {
|
|
|
|
q[i], q[j] = q[j], q[i]
|
|
|
|
}
|
|
|
|
|
2019-10-10 16:40:38 +00:00
|
|
|
func getSearchBy(value string) rpc.By {
|
|
|
|
switch value {
|
|
|
|
case "name":
|
|
|
|
return rpc.Name
|
|
|
|
case "maintainer":
|
|
|
|
return rpc.Maintainer
|
|
|
|
case "depends":
|
|
|
|
return rpc.Depends
|
|
|
|
case "makedepends":
|
|
|
|
return rpc.MakeDepends
|
|
|
|
case "optdepends":
|
|
|
|
return rpc.OptDepends
|
|
|
|
case "checkdepends":
|
|
|
|
return rpc.CheckDepends
|
|
|
|
default:
|
|
|
|
return rpc.NameDesc
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-02 17:24:03 +00:00
|
|
|
// NarrowSearch searches AUR and narrows based on subarguments
|
|
|
|
func narrowSearch(pkgS []string, sortS bool) (aurQuery, error) {
|
2018-04-02 14:27:07 +00:00
|
|
|
var r []rpc.Pkg
|
|
|
|
var err error
|
|
|
|
var usedIndex int
|
|
|
|
|
2019-10-10 16:40:38 +00:00
|
|
|
by := getSearchBy(config.SearchBy)
|
|
|
|
|
2017-08-02 17:24:03 +00:00
|
|
|
if len(pkgS) == 0 {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2018-04-02 14:27:07 +00:00
|
|
|
for i, word := range pkgS {
|
2019-10-10 16:40:38 +00:00
|
|
|
r, err = rpc.SearchBy(word, by)
|
2018-04-02 14:27:07 +00:00
|
|
|
if err == nil {
|
|
|
|
usedIndex = i
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-02 17:24:03 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(pkgS) == 1 {
|
|
|
|
if sortS {
|
2017-08-04 09:26:53 +00:00
|
|
|
sort.Sort(aurQuery(r))
|
2017-08-02 17:24:03 +00:00
|
|
|
}
|
|
|
|
return r, err
|
|
|
|
}
|
|
|
|
|
|
|
|
var aq aurQuery
|
|
|
|
var n int
|
|
|
|
|
2020-05-02 14:17:20 +00:00
|
|
|
for i := range r {
|
2017-08-02 17:24:03 +00:00
|
|
|
match := true
|
2020-06-15 03:58:22 +00:00
|
|
|
for j, pkgN := range pkgS {
|
|
|
|
if usedIndex == j {
|
2018-04-02 14:27:07 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2020-06-15 06:50:06 +00:00
|
|
|
if !(strings.Contains(r[i].Name, pkgN) || strings.Contains(strings.ToLower(r[i].Description), pkgN)) {
|
2017-08-02 17:24:03 +00:00
|
|
|
match = false
|
|
|
|
break
|
|
|
|
}
|
2017-05-02 15:46:14 +00:00
|
|
|
}
|
|
|
|
|
2017-08-02 17:24:03 +00:00
|
|
|
if match {
|
|
|
|
n++
|
2020-05-02 14:17:20 +00:00
|
|
|
aq = append(aq, r[i])
|
2017-05-02 15:46:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-02 17:24:03 +00:00
|
|
|
if sortS {
|
|
|
|
sort.Sort(aq)
|
|
|
|
}
|
|
|
|
|
|
|
|
return aq, err
|
2017-05-02 15:46:14 +00:00
|
|
|
}
|
|
|
|
|
2017-04-29 17:12:12 +00:00
|
|
|
// SyncSearch presents a query to the local repos and to the AUR.
|
2020-07-05 14:58:35 +00:00
|
|
|
func syncSearch(pkgS []string, alpmHandle *alpm.Handle) (err error) {
|
2020-07-10 00:36:45 +00:00
|
|
|
pkgS = query.RemoveInvalidTargets(pkgS, config.Runtime.Mode)
|
2018-06-04 19:36:10 +00:00
|
|
|
var aurErr error
|
|
|
|
var repoErr error
|
|
|
|
var aq aurQuery
|
|
|
|
var pq repoQuery
|
|
|
|
|
2020-07-05 00:45:23 +00:00
|
|
|
if config.Runtime.Mode == settings.ModeAUR || config.Runtime.Mode == settings.ModeAny {
|
2018-06-04 19:36:10 +00:00
|
|
|
aq, aurErr = narrowSearch(pkgS, true)
|
|
|
|
}
|
2020-07-05 00:45:23 +00:00
|
|
|
if config.Runtime.Mode == settings.ModeRepo || config.Runtime.Mode == settings.ModeAny {
|
2020-07-05 14:58:35 +00:00
|
|
|
pq, repoErr = queryRepo(pkgS, alpmHandle)
|
2018-06-04 19:36:10 +00:00
|
|
|
if repoErr != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-04-29 17:12:12 +00:00
|
|
|
}
|
|
|
|
|
2019-04-04 08:22:33 +00:00
|
|
|
switch config.SortMode {
|
2020-07-05 00:01:08 +00:00
|
|
|
case settings.TopDown:
|
2020-07-05 00:45:23 +00:00
|
|
|
if config.Runtime.Mode == settings.ModeRepo || config.Runtime.Mode == settings.ModeAny {
|
2020-07-05 14:58:35 +00:00
|
|
|
pq.printSearch(alpmHandle)
|
2018-06-04 19:36:10 +00:00
|
|
|
}
|
2020-07-05 00:45:23 +00:00
|
|
|
if config.Runtime.Mode == settings.ModeAUR || config.Runtime.Mode == settings.ModeAny {
|
2020-07-05 14:58:35 +00:00
|
|
|
aq.printSearch(1, alpmHandle)
|
2018-06-04 19:36:10 +00:00
|
|
|
}
|
2020-07-05 00:01:08 +00:00
|
|
|
case settings.BottomUp:
|
2020-07-05 00:45:23 +00:00
|
|
|
if config.Runtime.Mode == settings.ModeAUR || config.Runtime.Mode == settings.ModeAny {
|
2020-07-05 14:58:35 +00:00
|
|
|
aq.printSearch(1, alpmHandle)
|
2018-06-04 19:36:10 +00:00
|
|
|
}
|
2020-07-05 00:45:23 +00:00
|
|
|
if config.Runtime.Mode == settings.ModeRepo || config.Runtime.Mode == settings.ModeAny {
|
2020-07-05 14:58:35 +00:00
|
|
|
pq.printSearch(alpmHandle)
|
2019-04-04 08:22:33 +00:00
|
|
|
}
|
|
|
|
default:
|
2020-05-04 07:24:32 +00:00
|
|
|
return errors.New(gotext.Get("invalid sort mode. Fix with yay -Y --bottomup --save"))
|
2017-04-29 17:12:12 +00:00
|
|
|
}
|
|
|
|
|
2018-04-03 05:49:41 +00:00
|
|
|
if aurErr != nil {
|
2020-05-04 07:24:32 +00:00
|
|
|
text.Errorln(gotext.Get("error during AUR search: %s", aurErr))
|
|
|
|
text.Warnln(gotext.Get("Showing repo packages only"))
|
2018-04-03 05:49:41 +00:00
|
|
|
}
|
|
|
|
|
2017-04-29 17:12:12 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// SyncInfo serves as a pacman -Si for repo packages and AUR packages.
|
2020-07-08 01:31:35 +00:00
|
|
|
func syncInfo(cmdArgs *settings.Arguments, pkgS []string, alpmHandle *alpm.Handle) error {
|
2018-03-22 18:11:00 +00:00
|
|
|
var info []*rpc.Pkg
|
2018-06-01 03:20:49 +00:00
|
|
|
missing := false
|
2020-07-10 00:36:45 +00:00
|
|
|
pkgS = query.RemoveInvalidTargets(pkgS, config.Runtime.Mode)
|
2020-07-05 14:58:35 +00:00
|
|
|
aurS, repoS, err := packageSlices(pkgS, alpmHandle)
|
2017-04-29 17:12:12 +00:00
|
|
|
if err != nil {
|
2020-05-02 14:17:20 +00:00
|
|
|
return err
|
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
|
|
|
}
|
|
|
|
|
2020-07-10 00:36:45 +00:00
|
|
|
info, err = query.AURInfoPrint(noDB, config.RequestSplitN)
|
2018-02-18 23:46:25 +00:00
|
|
|
if err != nil {
|
2018-06-01 03:20:49 +00:00
|
|
|
missing = true
|
2018-11-14 12:14:41 +00:00
|
|
|
fmt.Fprintln(os.Stderr, err)
|
2018-02-18 23:46:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-03 02:45:16 +00:00
|
|
|
// Repo always goes first
|
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...)
|
2018-07-19 17:37:28 +00:00
|
|
|
err = show(passToPacman(arguments))
|
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 {
|
2018-02-18 23:46:25 +00:00
|
|
|
for _, pkg := range info {
|
2020-07-08 01:22:01 +00:00
|
|
|
PrintInfo(pkg, 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
|
|
|
}
|
|
|
|
|
2017-08-02 17:24:03 +00:00
|
|
|
// Search handles repo searches. Creates a RepoSearch struct.
|
2020-07-05 14:58:35 +00:00
|
|
|
func queryRepo(pkgInputN []string, alpmHandle *alpm.Handle) (s repoQuery, err error) {
|
2019-02-04 16:56:02 +00:00
|
|
|
dbList, err := alpmHandle.SyncDBs()
|
2017-08-02 17:24:03 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-10-13 11:15:51 +00:00
|
|
|
_ = dbList.ForEach(func(db alpm.DB) error {
|
2018-07-24 21:00:33 +00:00
|
|
|
if len(pkgInputN) == 0 {
|
|
|
|
pkgs := db.PkgCache()
|
|
|
|
s = append(s, pkgs.Slice()...)
|
|
|
|
} else {
|
|
|
|
pkgs := db.Search(pkgInputN)
|
|
|
|
s = append(s, pkgs.Slice()...)
|
2017-08-02 17:24:03 +00:00
|
|
|
}
|
2018-07-24 21:00:33 +00:00
|
|
|
return nil
|
|
|
|
})
|
2017-08-02 17:24:03 +00:00
|
|
|
|
2020-07-05 00:01:08 +00:00
|
|
|
if config.SortMode == settings.BottomUp {
|
2018-07-24 21:00:33 +00:00
|
|
|
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
|
|
|
|
s[i], s[j] = s[j], s[i]
|
2017-08-02 17:24:03 +00:00
|
|
|
}
|
|
|
|
}
|
2018-07-24 21:00:33 +00:00
|
|
|
|
2017-08-02 17:24:03 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// PackageSlices separates an input slice into aur and repo slices
|
2020-07-05 14:58:35 +00:00
|
|
|
func packageSlices(toCheck []string, alpmHandle *alpm.Handle) (aur, repo []string, err error) {
|
2019-02-04 16:56:02 +00:00
|
|
|
dbList, err := alpmHandle.SyncDBs()
|
2017-08-02 17:24:03 +00:00
|
|
|
if err != nil {
|
2020-05-02 14:17:20 +00:00
|
|
|
return nil, nil, err
|
2017-08-02 17:24:03 +00:00
|
|
|
}
|
|
|
|
|
2018-01-17 21:48:23 +00:00
|
|
|
for _, _pkg := range toCheck {
|
2020-07-10 00:36:45 +00:00
|
|
|
db, name := text.SplitDBFromName(_pkg)
|
2018-03-19 00:11:40 +00:00
|
|
|
found := false
|
2017-08-02 17:24:03 +00:00
|
|
|
|
2020-07-05 00:45:23 +00:00
|
|
|
if db == "aur" || config.Runtime.Mode == settings.ModeAUR {
|
2018-03-13 21:36:42 +00:00
|
|
|
aur = append(aur, _pkg)
|
|
|
|
continue
|
2020-07-05 00:45:23 +00:00
|
|
|
} else if db != "" || config.Runtime.Mode == settings.ModeRepo {
|
2018-03-13 21:36:42 +00:00
|
|
|
repo = append(repo, _pkg)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2019-02-04 16:56:02 +00:00
|
|
|
_ = dbList.ForEach(func(db alpm.DB) error {
|
2019-02-14 20:44:39 +00:00
|
|
|
if db.Pkg(name) != nil {
|
2018-03-19 00:11:40 +00:00
|
|
|
found = true
|
|
|
|
return fmt.Errorf("")
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
})
|
2017-08-02 17:24:03 +00:00
|
|
|
|
|
|
|
if !found {
|
2019-02-14 20:44:39 +00:00
|
|
|
found = !dbList.FindGroupPkgs(name).Empty()
|
2018-01-17 21:48:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if found {
|
2018-03-10 19:14:37 +00:00
|
|
|
repo = append(repo, _pkg)
|
2018-01-17 21:48:23 +00:00
|
|
|
} else {
|
2018-03-10 19:14:37 +00:00
|
|
|
aur = append(aur, _pkg)
|
2017-08-02 17:24:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-02 14:17:20 +00:00
|
|
|
return aur, repo, nil
|
2017-08-02 17:24:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// HangingPackages returns a list of packages installed as deps
|
|
|
|
// and unneeded by the system
|
2018-03-23 23:45:46 +00:00
|
|
|
// removeOptional decides whether optional dependencies are counted or not
|
2020-07-05 14:58:35 +00:00
|
|
|
func hangingPackages(removeOptional bool, alpmHandle *alpm.Handle) (hanging []string, err error) {
|
2019-02-04 16:56:02 +00:00
|
|
|
localDB, err := alpmHandle.LocalDB()
|
2017-08-02 17:24:03 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
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
|
2019-10-16 21:25:40 +00:00
|
|
|
provides := make(stringset.MapStringSet)
|
2019-02-04 16:56:02 +00:00
|
|
|
packages := localDB.PkgCache()
|
2018-03-23 23:45:46 +00:00
|
|
|
|
|
|
|
// Mark explicit dependencies and enumerate the provides list
|
|
|
|
setupResources := func(pkg alpm.Package) error {
|
|
|
|
if pkg.Reason() == alpm.PkgReasonExplicit {
|
|
|
|
safePackages[pkg.Name()] = 1
|
|
|
|
} else {
|
|
|
|
safePackages[pkg.Name()] = 0
|
|
|
|
}
|
|
|
|
|
2019-10-13 11:15:51 +00:00
|
|
|
_ = pkg.Provides().ForEach(func(dep alpm.Depend) error {
|
2018-05-07 22:01:39 +00:00
|
|
|
provides.Add(dep.Name, pkg.Name())
|
2018-03-23 23:45:46 +00:00
|
|
|
return nil
|
|
|
|
})
|
|
|
|
return nil
|
|
|
|
}
|
2019-10-13 11:15:51 +00:00
|
|
|
_ = packages.ForEach(setupResources)
|
2018-03-23 23:45:46 +00:00
|
|
|
|
|
|
|
iterateAgain := true
|
|
|
|
processDependencies := func(pkg alpm.Package) error {
|
2018-04-27 00:25:40 +00:00
|
|
|
if state := safePackages[pkg.Name()]; state == 0 || state == 2 {
|
2017-08-02 17:24:03 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-03-23 23:45:46 +00:00
|
|
|
safePackages[pkg.Name()] = 2
|
|
|
|
|
|
|
|
// Update state for dependencies
|
|
|
|
markDependencies := func(dep alpm.Depend) error {
|
|
|
|
// 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
|
2018-03-24 12:37:31 +00:00
|
|
|
if pset, ok2 := provides[dep.Name]; ok2 {
|
|
|
|
for p := range pset {
|
|
|
|
if safePackages[p] == 0 {
|
|
|
|
iterateAgain = true
|
|
|
|
safePackages[p] = 1
|
|
|
|
}
|
|
|
|
}
|
2018-03-23 23:45:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if state == 0 {
|
|
|
|
iterateAgain = true
|
|
|
|
safePackages[dep.Name] = 1
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-10-13 11:15:51 +00:00
|
|
|
_ = pkg.Depends().ForEach(markDependencies)
|
2018-03-23 23:45:46 +00:00
|
|
|
if !removeOptional {
|
2019-10-13 11:15:51 +00:00
|
|
|
_ = pkg.OptionalDepends().ForEach(markDependencies)
|
2017-08-02 17:24:03 +00:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-03-23 23:45:46 +00:00
|
|
|
for iterateAgain {
|
|
|
|
iterateAgain = false
|
2019-10-13 11:15:51 +00:00
|
|
|
_ = packages.ForEach(processDependencies)
|
2018-03-23 23:45:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Build list of packages to be removed
|
2019-10-13 11:15:51 +00:00
|
|
|
_ = packages.ForEach(func(pkg alpm.Package) error {
|
2018-03-23 23:45:46 +00:00
|
|
|
if safePackages[pkg.Name()] == 0 {
|
|
|
|
hanging = append(hanging, pkg.Name())
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
|
2020-05-02 14:17:20 +00:00
|
|
|
return hanging, err
|
2017-08-02 17:24:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Statistics returns statistics about packages installed in system
|
2020-07-05 14:58:35 +00:00
|
|
|
func statistics(alpmHandle *alpm.Handle) (*struct {
|
2017-08-02 17:24:03 +00:00
|
|
|
Totaln int
|
|
|
|
Expln int
|
|
|
|
TotalSize int64
|
2020-05-02 14:17:20 +00:00
|
|
|
}, error) {
|
2017-08-02 17:24:03 +00:00
|
|
|
var tS int64 // TotalSize
|
|
|
|
var nPkg int
|
|
|
|
var ePkg int
|
|
|
|
|
2019-02-04 16:56:02 +00:00
|
|
|
localDB, err := alpmHandle.LocalDB()
|
2017-08-02 17:24:03 +00:00
|
|
|
if err != nil {
|
2020-05-02 14:17:20 +00:00
|
|
|
return nil, err
|
2017-08-02 17:24:03 +00:00
|
|
|
}
|
|
|
|
|
2019-02-04 16:56:02 +00:00
|
|
|
for _, pkg := range localDB.PkgCache().Slice() {
|
2017-08-02 17:24:03 +00:00
|
|
|
tS += pkg.ISize()
|
|
|
|
nPkg++
|
|
|
|
if pkg.Reason() == 0 {
|
|
|
|
ePkg++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-02 14:17:20 +00:00
|
|
|
info := &struct {
|
2017-08-02 17:24:03 +00:00
|
|
|
Totaln int
|
|
|
|
Expln int
|
|
|
|
TotalSize int64
|
|
|
|
}{
|
|
|
|
nPkg, ePkg, tS,
|
|
|
|
}
|
|
|
|
|
2020-05-02 14:17:20 +00:00
|
|
|
return info, err
|
2017-08-02 17:24:03 +00:00
|
|
|
}
|