2021-10-16 10:07:39 +02:00
|
|
|
package query
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2021-11-01 16:41:07 +01:00
|
|
|
"io"
|
2021-10-16 10:07:39 +02:00
|
|
|
"sort"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/Jguer/aur"
|
2021-11-07 00:15:50 +01:00
|
|
|
"github.com/Jguer/go-alpm/v2"
|
2023-02-20 13:14:16 +01:00
|
|
|
"github.com/hashicorp/go-multierror"
|
2021-10-16 10:07:39 +02:00
|
|
|
"github.com/leonelquinteros/gotext"
|
|
|
|
|
|
|
|
"github.com/Jguer/yay/v11/pkg/db"
|
|
|
|
"github.com/Jguer/yay/v11/pkg/intrange"
|
|
|
|
"github.com/Jguer/yay/v11/pkg/settings/parser"
|
|
|
|
"github.com/Jguer/yay/v11/pkg/stringset"
|
|
|
|
"github.com/Jguer/yay/v11/pkg/text"
|
2022-11-16 00:25:17 +01:00
|
|
|
|
2023-02-20 12:20:48 +01:00
|
|
|
"github.com/Jguer/aur/rpc"
|
2021-10-16 10:07:39 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
type SearchVerbosity int
|
|
|
|
|
|
|
|
// Verbosity settings for search.
|
|
|
|
const (
|
|
|
|
NumberMenu SearchVerbosity = iota
|
|
|
|
Detailed
|
|
|
|
Minimal
|
|
|
|
)
|
|
|
|
|
|
|
|
type SourceQueryBuilder struct {
|
|
|
|
repoQuery
|
|
|
|
aurQuery
|
2022-11-13 23:53:37 +01:00
|
|
|
|
2021-11-01 16:41:07 +01:00
|
|
|
sortBy string
|
|
|
|
searchBy string
|
2022-03-07 00:48:15 +01:00
|
|
|
targetMode parser.TargetMode
|
2022-12-29 19:42:43 +01:00
|
|
|
useAURCache bool
|
2022-03-07 00:48:15 +01:00
|
|
|
bottomUp bool
|
2021-11-01 16:41:07 +01:00
|
|
|
singleLineResults bool
|
2022-11-13 14:29:00 +01:00
|
|
|
|
2023-02-20 12:20:48 +01:00
|
|
|
aurClient rpc.ClientInterface
|
|
|
|
aurCache aur.QueryClient
|
2021-10-16 10:07:39 +02:00
|
|
|
}
|
|
|
|
|
2021-11-01 16:41:07 +01:00
|
|
|
func NewSourceQueryBuilder(
|
2023-02-20 12:20:48 +01:00
|
|
|
aurClient rpc.ClientInterface,
|
|
|
|
aurCache aur.QueryClient,
|
2021-11-01 16:41:07 +01:00
|
|
|
sortBy string,
|
|
|
|
targetMode parser.TargetMode,
|
|
|
|
searchBy string,
|
2021-11-07 00:15:50 +01:00
|
|
|
bottomUp,
|
2021-11-01 16:41:07 +01:00
|
|
|
singleLineResults bool,
|
2022-11-13 23:53:37 +01:00
|
|
|
useAURCache bool,
|
2021-11-01 16:41:07 +01:00
|
|
|
) *SourceQueryBuilder {
|
2021-10-16 10:07:39 +02:00
|
|
|
return &SourceQueryBuilder{
|
2022-11-13 14:29:00 +01:00
|
|
|
aurClient: aurClient,
|
|
|
|
aurCache: aurCache,
|
2021-11-07 00:15:50 +01:00
|
|
|
repoQuery: []alpm.IPackage{},
|
|
|
|
aurQuery: []aur.Pkg{},
|
|
|
|
bottomUp: bottomUp,
|
2021-11-01 16:41:07 +01:00
|
|
|
sortBy: sortBy,
|
|
|
|
targetMode: targetMode,
|
|
|
|
searchBy: searchBy,
|
|
|
|
singleLineResults: singleLineResults,
|
2022-11-13 23:53:37 +01:00
|
|
|
useAURCache: useAURCache,
|
2021-10-16 10:07:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-13 14:29:00 +01:00
|
|
|
func (s *SourceQueryBuilder) Execute(ctx context.Context,
|
|
|
|
dbExecutor db.Executor,
|
|
|
|
pkgS []string,
|
|
|
|
) {
|
2021-10-16 10:07:39 +02:00
|
|
|
var aurErr error
|
|
|
|
|
|
|
|
pkgS = RemoveInvalidTargets(pkgS, s.targetMode)
|
|
|
|
|
|
|
|
if s.targetMode.AtLeastAUR() {
|
2022-11-13 23:53:37 +01:00
|
|
|
s.aurQuery, aurErr = queryAUR(ctx, s.aurClient, s.aurCache, pkgS, s.searchBy, s.useAURCache)
|
2022-03-07 00:48:15 +01:00
|
|
|
s.aurQuery = filterAURResults(pkgS, s.aurQuery)
|
|
|
|
|
|
|
|
sort.Sort(aurSortable{aurQuery: s.aurQuery, sortBy: s.sortBy, bottomUp: s.bottomUp})
|
2021-10-16 10:07:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if s.targetMode.AtLeastRepo() {
|
2022-03-07 00:48:15 +01:00
|
|
|
s.repoQuery = repoQuery(dbExecutor.SyncPackages(pkgS...))
|
|
|
|
|
|
|
|
if s.bottomUp {
|
|
|
|
s.Reverse()
|
|
|
|
}
|
2021-10-16 10:07:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if aurErr != nil && len(s.repoQuery) != 0 {
|
|
|
|
text.Errorln(ErrAURSearch{inner: aurErr})
|
|
|
|
text.Warnln(gotext.Get("Showing repo packages only"))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-01 16:41:07 +01:00
|
|
|
func (s *SourceQueryBuilder) Results(w io.Writer, dbExecutor db.Executor, verboseSearch SearchVerbosity) error {
|
2021-11-07 00:15:50 +01:00
|
|
|
if s.aurQuery == nil || s.repoQuery == nil {
|
2021-10-16 10:07:39 +02:00
|
|
|
return ErrNoQuery{}
|
|
|
|
}
|
|
|
|
|
2021-11-07 00:15:50 +01:00
|
|
|
if s.bottomUp {
|
|
|
|
if s.targetMode.AtLeastAUR() {
|
|
|
|
s.aurQuery.printSearch(w, len(s.repoQuery)+1, dbExecutor, verboseSearch, s.bottomUp, s.singleLineResults)
|
2021-10-16 10:07:39 +02:00
|
|
|
}
|
|
|
|
|
2021-11-07 00:15:50 +01:00
|
|
|
if s.targetMode.AtLeastRepo() {
|
|
|
|
s.repoQuery.printSearch(w, dbExecutor, verboseSearch, s.bottomUp, s.singleLineResults)
|
2021-10-16 10:07:39 +02:00
|
|
|
}
|
2021-11-07 00:15:50 +01:00
|
|
|
} else {
|
|
|
|
if s.targetMode.AtLeastRepo() {
|
|
|
|
s.repoQuery.printSearch(w, dbExecutor, verboseSearch, s.bottomUp, s.singleLineResults)
|
2021-10-16 10:07:39 +02:00
|
|
|
}
|
|
|
|
|
2021-11-07 00:15:50 +01:00
|
|
|
if s.targetMode.AtLeastAUR() {
|
|
|
|
s.aurQuery.printSearch(w, len(s.repoQuery)+1, dbExecutor, verboseSearch, s.bottomUp, s.singleLineResults)
|
2021-10-16 10:07:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-11-03 00:03:35 +01:00
|
|
|
func (s *SourceQueryBuilder) Len() int {
|
|
|
|
return len(s.repoQuery) + len(s.aurQuery)
|
|
|
|
}
|
|
|
|
|
2021-10-16 10:07:39 +02:00
|
|
|
func (s *SourceQueryBuilder) GetTargets(include, exclude intrange.IntRanges,
|
2022-03-07 00:48:15 +01:00
|
|
|
otherExclude stringset.StringSet,
|
|
|
|
) ([]string, error) {
|
2021-10-16 10:07:39 +02:00
|
|
|
isInclude := len(exclude) == 0 && len(otherExclude) == 0
|
|
|
|
|
|
|
|
var targets []string
|
|
|
|
|
|
|
|
for i, pkg := range s.repoQuery {
|
|
|
|
var target int
|
|
|
|
|
2021-11-07 00:15:50 +01:00
|
|
|
if s.bottomUp {
|
2021-10-16 10:07:39 +02:00
|
|
|
target = len(s.repoQuery) - i
|
2021-11-07 00:15:50 +01:00
|
|
|
} else {
|
|
|
|
target = i + 1
|
2021-10-16 10:07:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (isInclude && include.Get(target)) || (!isInclude && !exclude.Get(target)) {
|
|
|
|
targets = append(targets, pkg.DB().Name()+"/"+pkg.Name())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := range s.aurQuery {
|
|
|
|
var target int
|
|
|
|
|
2021-11-07 00:15:50 +01:00
|
|
|
if s.bottomUp {
|
2021-10-16 10:07:39 +02:00
|
|
|
target = len(s.aurQuery) - i + len(s.repoQuery)
|
2021-11-07 00:15:50 +01:00
|
|
|
} else {
|
|
|
|
target = i + 1 + len(s.repoQuery)
|
2021-10-16 10:07:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (isInclude && include.Get(target)) || (!isInclude && !exclude.Get(target)) {
|
|
|
|
targets = append(targets, "aur/"+s.aurQuery[i].Name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return targets, nil
|
|
|
|
}
|
|
|
|
|
2022-03-07 00:48:15 +01:00
|
|
|
// filter AUR results to remove strings that don't contain all of the search terms.
|
|
|
|
func filterAURResults(pkgS []string, results []aur.Pkg) []aur.Pkg {
|
|
|
|
aurPkgs := make([]aur.Pkg, 0, len(results))
|
|
|
|
|
|
|
|
matchesSearchTerms := func(pkg *aur.Pkg, terms []string) bool {
|
|
|
|
for _, pkgN := range terms {
|
|
|
|
name := strings.ToLower(pkg.Name)
|
|
|
|
desc := strings.ToLower(pkg.Description)
|
|
|
|
targ := strings.ToLower(pkgN)
|
|
|
|
|
|
|
|
if !(strings.Contains(name, targ) || strings.Contains(desc, targ)) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
2021-10-16 10:07:39 +02:00
|
|
|
|
2022-03-07 00:48:15 +01:00
|
|
|
for i := range results {
|
|
|
|
if matchesSearchTerms(&results[i], pkgS) {
|
|
|
|
aurPkgs = append(aurPkgs, results[i])
|
|
|
|
}
|
2021-10-16 10:07:39 +02:00
|
|
|
}
|
|
|
|
|
2022-03-07 00:48:15 +01:00
|
|
|
return aurPkgs
|
2021-10-16 10:07:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// queryAUR searches AUR and narrows based on subarguments.
|
2022-11-13 17:47:19 +01:00
|
|
|
func queryAUR(ctx context.Context,
|
2023-02-20 13:14:16 +01:00
|
|
|
rpcClient rpc.ClientInterface, aurClient aur.QueryClient,
|
2022-11-13 23:53:37 +01:00
|
|
|
pkgS []string, searchBy string, newEngine bool,
|
2022-11-13 17:47:19 +01:00
|
|
|
) ([]aur.Pkg, error) {
|
2021-10-16 10:07:39 +02:00
|
|
|
var (
|
2022-03-07 00:48:15 +01:00
|
|
|
err error
|
|
|
|
by = getSearchBy(searchBy)
|
2021-10-16 10:07:39 +02:00
|
|
|
)
|
|
|
|
|
2023-02-20 13:14:16 +01:00
|
|
|
queryClient := aurClient
|
|
|
|
if !newEngine {
|
|
|
|
queryClient = rpcClient
|
|
|
|
}
|
2022-11-15 15:44:50 +01:00
|
|
|
|
2023-02-20 13:14:16 +01:00
|
|
|
for _, word := range pkgS {
|
|
|
|
r, errM := queryClient.Get(ctx, &aur.Query{
|
|
|
|
Needles: []string{word},
|
|
|
|
By: by,
|
|
|
|
Contains: true,
|
|
|
|
})
|
|
|
|
if errM == nil {
|
|
|
|
return r, nil
|
2022-11-13 23:53:37 +01:00
|
|
|
}
|
|
|
|
|
2023-02-20 13:14:16 +01:00
|
|
|
err = multierror.Append(err, errM)
|
2021-10-16 10:07:39 +02:00
|
|
|
}
|
|
|
|
|
2022-03-07 00:48:15 +01:00
|
|
|
return nil, err
|
2021-10-16 10:07:39 +02:00
|
|
|
}
|