From 9fd6917bc013bfcbee021bde69cbe889a4b3d808 Mon Sep 17 00:00:00 2001 From: jguer Date: Sat, 1 Aug 2020 00:01:01 +0200 Subject: [PATCH] fix(alpm): transfer handle initialization to executor --- callbacks.go | 9 --- cmd.go | 12 +-- install.go | 4 + main.go | 3 +- pkg/db/alpm.go | 197 ++++++++++++++++++++++++++++++++++++++++++--- pkg/db/executor.go | 3 + print.go | 27 +++---- query.go | 56 +++++-------- 8 files changed, 233 insertions(+), 78 deletions(-) diff --git a/callbacks.go b/callbacks.go index c9a0915d..0099c6ca 100644 --- a/callbacks.go +++ b/callbacks.go @@ -92,12 +92,3 @@ func questionCallback(question alpm.QuestionAny) { break } } - -func logCallback(level alpm.LogLevel, str string) { - switch level { - case alpm.LogWarning: - text.Warn(str) - case alpm.LogError: - text.Error(str) - } -} diff --git a/cmd.go b/cmd.go index de00d87a..e83c491e 100644 --- a/cmd.go +++ b/cmd.go @@ -277,7 +277,7 @@ func handleSync(cmdArgs *settings.Arguments, alpmHandle *alpm.Handle) error { } else { config.SearchMode = detailed } - return syncSearch(targets, alpmHandle) + return syncSearch(targets) } if cmdArgs.ExistsArg("p", "print", "print-format") { return show(passToPacman(cmdArgs)) @@ -331,7 +331,7 @@ func displayNumberMenu(pkgS []string, alpmHandle *alpm.Handle, cmdArgs *settings lenaq = len(aq) } if config.Runtime.Mode == settings.ModeRepo || config.Runtime.Mode == settings.ModeAny { - pq, repoErr = queryRepo(pkgS, alpmHandle) + pq = queryRepo(pkgS, config.Runtime.DBExecutor) lenpq = len(pq) if repoErr != nil { return repoErr @@ -345,17 +345,17 @@ func displayNumberMenu(pkgS []string, alpmHandle *alpm.Handle, cmdArgs *settings switch config.SortMode { case settings.TopDown: if config.Runtime.Mode == settings.ModeRepo || config.Runtime.Mode == settings.ModeAny { - pq.printSearch(alpmHandle) + pq.printSearch(config.Runtime.DBExecutor) } if config.Runtime.Mode == settings.ModeAUR || config.Runtime.Mode == settings.ModeAny { - aq.printSearch(lenpq+1, alpmHandle) + aq.printSearch(lenpq+1, config.Runtime.DBExecutor) } case settings.BottomUp: if config.Runtime.Mode == settings.ModeAUR || config.Runtime.Mode == settings.ModeAny { - aq.printSearch(lenpq+1, alpmHandle) + aq.printSearch(lenpq+1, config.Runtime.DBExecutor) } if config.Runtime.Mode == settings.ModeRepo || config.Runtime.Mode == settings.ModeAny { - pq.printSearch(alpmHandle) + pq.printSearch(config.Runtime.DBExecutor) } default: return fmt.Errorf(gotext.Get("invalid sort mode. Fix with yay -Y --bottomup --save")) diff --git a/install.go b/install.go index 68c20e43..510aa8dd 100644 --- a/install.go +++ b/install.go @@ -94,6 +94,10 @@ func install(cmdArgs *settings.Arguments, alpmHandle *alpm.Handle, ignoreProvide return err } config.Runtime.AlpmHandle = alpmHandle + err = config.Runtime.DBExecutor.RefreshHandle() + if err != nil { + return err + } localNames, remoteNames, err := query.GetPackageNamesBySource(alpmHandle) if err != nil { diff --git a/main.go b/main.go index 5cbc6f0c..6464a080 100644 --- a/main.go +++ b/main.go @@ -145,7 +145,6 @@ func initAlpmHandle(pacmanConf *pacmanconf.Config, oldAlpmHandle *alpm.Handle) ( } alpmHandle.SetQuestionCallback(questionCallback) - alpmHandle.SetLogCallback(logCallback) return alpmHandle, nil } @@ -194,7 +193,7 @@ func main() { exitOnError(initVCS(runtime.VCSPath)) config.Runtime.AlpmHandle, config.Runtime.PacmanConf, err = initAlpm(cmdArgs, config.PacmanConf) exitOnError(err) - config.Runtime.DBExecutor, err = db.NewExecutor(config.Runtime.AlpmHandle) + config.Runtime.DBExecutor, err = db.NewAlpmExecutor(config.Runtime.AlpmHandle, runtime.PacmanConf, questionCallback) exitOnError(err) exitOnError(handleCmd(cmdArgs, config.Runtime.AlpmHandle)) os.Exit(cleanup(config.Runtime.AlpmHandle)) diff --git a/pkg/db/alpm.go b/pkg/db/alpm.go index 76cc8c60..72826043 100644 --- a/pkg/db/alpm.go +++ b/pkg/db/alpm.go @@ -1,16 +1,26 @@ package db import ( + "errors" + alpm "github.com/Jguer/go-alpm" + "github.com/Morganamilo/go-pacmanconf" + "github.com/leonelquinteros/gotext" + + "github.com/Jguer/yay/v10/pkg/text" ) type AlpmExecutor struct { - Handle *alpm.Handle - LocalDB *alpm.DB - SyncDB alpm.DBList + handle *alpm.Handle + localDB *alpm.DB + syncDB alpm.DBList + conf *pacmanconf.Config + questionCallback func(question alpm.QuestionAny) } -func NewExecutor(handle *alpm.Handle) (*AlpmExecutor, error) { +func NewAlpmExecutor(handle *alpm.Handle, + pacamnConf *pacmanconf.Config, + questionCallback func(question alpm.QuestionAny)) (*AlpmExecutor, error) { localDB, err := handle.LocalDB() if err != nil { return nil, err @@ -20,18 +30,154 @@ func NewExecutor(handle *alpm.Handle) (*AlpmExecutor, error) { return nil, err } - return &AlpmExecutor{Handle: handle, LocalDB: localDB, SyncDB: syncDB}, nil + return &AlpmExecutor{handle: handle, localDB: localDB, syncDB: syncDB, conf: pacamnConf, questionCallback: questionCallback}, nil +} + +func toUsage(usages []string) alpm.Usage { + if len(usages) == 0 { + return alpm.UsageAll + } + + var ret alpm.Usage + for _, usage := range usages { + switch usage { + case "Sync": + ret |= alpm.UsageSync + case "Search": + ret |= alpm.UsageSearch + case "Install": + ret |= alpm.UsageInstall + case "Upgrade": + ret |= alpm.UsageUpgrade + case "All": + ret |= alpm.UsageAll + } + } + + return ret +} + +func configureAlpm(pacmanConf *pacmanconf.Config, alpmHandle *alpm.Handle) error { + // TODO: set SigLevel + // sigLevel := alpm.SigPackage | alpm.SigPackageOptional | alpm.SigDatabase | alpm.SigDatabaseOptional + // localFileSigLevel := alpm.SigUseDefault + // remoteFileSigLevel := alpm.SigUseDefault + + for _, repo := range pacmanConf.Repos { + // TODO: set SigLevel + db, err := alpmHandle.RegisterSyncDB(repo.Name, 0) + if err != nil { + return err + } + + db.SetServers(repo.Servers) + db.SetUsage(toUsage(repo.Usage)) + } + + if err := alpmHandle.SetCacheDirs(pacmanConf.CacheDir); err != nil { + return err + } + + // add hook directories 1-by-1 to avoid overwriting the system directory + for _, dir := range pacmanConf.HookDir { + if err := alpmHandle.AddHookDir(dir); err != nil { + return err + } + } + + if err := alpmHandle.SetGPGDir(pacmanConf.GPGDir); err != nil { + return err + } + + if err := alpmHandle.SetLogFile(pacmanConf.LogFile); err != nil { + return err + } + + if err := alpmHandle.SetIgnorePkgs(pacmanConf.IgnorePkg); err != nil { + return err + } + + if err := alpmHandle.SetIgnoreGroups(pacmanConf.IgnoreGroup); err != nil { + return err + } + + if err := alpmHandle.SetArch(pacmanConf.Architecture); err != nil { + return err + } + + if err := alpmHandle.SetNoUpgrades(pacmanConf.NoUpgrade); err != nil { + return err + } + + if err := alpmHandle.SetNoExtracts(pacmanConf.NoExtract); err != nil { + return err + } + + /*if err := alpmHandle.SetDefaultSigLevel(sigLevel); err != nil { + return err + } + + if err := alpmHandle.SetLocalFileSigLevel(localFileSigLevel); err != nil { + return err + } + + if err := alpmHandle.SetRemoteFileSigLevel(remoteFileSigLevel); err != nil { + return err + }*/ + + if err := alpmHandle.SetUseSyslog(pacmanConf.UseSyslog); err != nil { + return err + } + + return alpmHandle.SetCheckSpace(pacmanConf.CheckSpace) +} + +func logCallback(level alpm.LogLevel, str string) { + switch level { + case alpm.LogWarning: + text.Warn(str) + case alpm.LogError: + text.Error(str) + } +} + +func (ae *AlpmExecutor) RefreshHandle() error { + if ae.handle != nil { + if errRelease := ae.handle.Release(); errRelease != nil { + return errRelease + } + } + + alpmHandle, err := alpm.Initialize(ae.conf.RootDir, ae.conf.DBPath) + if err != nil { + return errors.New(gotext.Get("unable to CreateHandle: %s", err)) + } + + if errConf := configureAlpm(ae.conf, alpmHandle); errConf != nil { + return errConf + } + + alpmHandle.SetQuestionCallback(ae.questionCallback) + alpmHandle.SetLogCallback(logCallback) + ae.handle = alpmHandle + ae.syncDB, err = alpmHandle.SyncDBs() + if err != nil { + return err + } + + ae.localDB, err = alpmHandle.LocalDB() + return err } func (ae *AlpmExecutor) LocalSatisfierExists(pkgName string) bool { - if _, err := ae.LocalDB.PkgCache().FindSatisfier(pkgName); err != nil { + if _, err := ae.localDB.PkgCache().FindSatisfier(pkgName); err != nil { return false } return true } func (ae *AlpmExecutor) IsCorrectVersionInstalled(pkgName, versionRequired string) bool { - alpmPackage := ae.LocalDB.Pkg(pkgName) + alpmPackage := ae.localDB.Pkg(pkgName) if alpmPackage == nil { return false } @@ -40,7 +186,7 @@ func (ae *AlpmExecutor) IsCorrectVersionInstalled(pkgName, versionRequired strin } func (ae *AlpmExecutor) SyncSatisfier(pkgName string) RepoPackage { - foundPkg, err := ae.SyncDB.FindSatisfier(pkgName) + foundPkg, err := ae.syncDB.FindSatisfier(pkgName) if err != nil { return nil } @@ -49,7 +195,7 @@ func (ae *AlpmExecutor) SyncSatisfier(pkgName string) RepoPackage { func (ae *AlpmExecutor) PackagesFromGroup(groupName string) []RepoPackage { groupPackages := []RepoPackage{} - _ = ae.SyncDB.FindGroupPkgs(groupName).ForEach(func(pkg alpm.Package) error { + _ = ae.syncDB.FindGroupPkgs(groupName).ForEach(func(pkg alpm.Package) error { groupPackages = append(groupPackages, &pkg) return nil }) @@ -58,15 +204,39 @@ func (ae *AlpmExecutor) PackagesFromGroup(groupName string) []RepoPackage { func (ae *AlpmExecutor) LocalPackages() []RepoPackage { localPackages := []RepoPackage{} - _ = ae.LocalDB.PkgCache().ForEach(func(pkg alpm.Package) error { + _ = ae.localDB.PkgCache().ForEach(func(pkg alpm.Package) error { localPackages = append(localPackages, RepoPackage(&pkg)) return nil }) return localPackages } +// SyncPackages searches SyncDB for packages or returns all packages if no search param is given +func (ae *AlpmExecutor) SyncPackages(pkgNames ...string) []RepoPackage { + repoPackages := []RepoPackage{} + _ = ae.syncDB.ForEach(func(db alpm.DB) error { + if len(pkgNames) == 0 { + _ = db.PkgCache().ForEach(func(pkg alpm.Package) error { + repoPackages = append(repoPackages, RepoPackage(&pkg)) + return nil + }) + } else { + _ = db.Search(pkgNames).ForEach(func(pkg alpm.Package) error { + repoPackages = append(repoPackages, RepoPackage(&pkg)) + return nil + }) + } + return nil + }) + return repoPackages +} + +func (ae *AlpmExecutor) LocalPackage(pkgName string) RepoPackage { + return ae.localDB.Pkg(pkgName) +} + func (ae *AlpmExecutor) PackageFromDB(pkgName, dbName string) RepoPackage { - singleDB, err := ae.Handle.SyncDBByName(dbName) + singleDB, err := ae.handle.SyncDBByName(dbName) if err != nil { return nil } @@ -91,3 +261,8 @@ func (ae *AlpmExecutor) PackageConflicts(pkg RepoPackage) []alpm.Depend { alpmPackage := pkg.(*alpm.Package) return alpmPackage.Conflicts().Slice() } + +func (ae *AlpmExecutor) PackageGroups(pkg RepoPackage) []string { + alpmPackage := pkg.(*alpm.Package) + return alpmPackage.Groups().Slice() +} diff --git a/pkg/db/executor.go b/pkg/db/executor.go index 2a43f7fb..0272e797 100644 --- a/pkg/db/executor.go +++ b/pkg/db/executor.go @@ -7,4 +7,7 @@ type RepoPackage interface { Name() string Version() string DB() *alpm.DB + ISize() int64 + Size() int64 + Description() string } diff --git a/print.go b/print.go index 89f8b035..7a46dd09 100644 --- a/print.go +++ b/print.go @@ -11,6 +11,7 @@ import ( "github.com/Jguer/go-alpm" + "github.com/Jguer/yay/v10/pkg/db" "github.com/Jguer/yay/v10/pkg/intrange" "github.com/Jguer/yay/v10/pkg/query" "github.com/Jguer/yay/v10/pkg/settings" @@ -19,9 +20,7 @@ import ( ) // PrintSearch handles printing search results in a given format -func (q aurQuery) printSearch(start int, alpmHandle *alpm.Handle) { - localDB, _ := alpmHandle.LocalDB() - +func (q aurQuery) printSearch(start int, dbExecutor *db.AlpmExecutor) { for i := range q { var toprint string if config.SearchMode == numberMenu { @@ -51,7 +50,7 @@ func (q aurQuery) printSearch(start int, alpmHandle *alpm.Handle) { toprint += bold(red(gotext.Get("(Out-of-date: %s)", text.FormatTime(q[i].OutOfDate)))) + " " } - if pkg := localDB.Pkg(q[i].Name); pkg != nil { + if pkg := dbExecutor.LocalPackage(q[i].Name); pkg != nil { if pkg.Version() != q[i].Version { toprint += bold(green(gotext.Get("(Installed: %s)", pkg.Version()))) } else { @@ -64,7 +63,7 @@ func (q aurQuery) printSearch(start int, alpmHandle *alpm.Handle) { } // PrintSearch receives a RepoSearch type and outputs pretty text. -func (s repoQuery) printSearch(alpmHandle *alpm.Handle) { +func (s repoQuery) printSearch(dbExecutor *db.AlpmExecutor) { for i, res := range s { var toprint string if config.SearchMode == numberMenu { @@ -86,18 +85,16 @@ func (s repoQuery) printSearch(alpmHandle *alpm.Handle) { bold(" ("+text.Human(res.Size())+ " "+text.Human(res.ISize())+") ") - if len(res.Groups().Slice()) != 0 { - toprint += fmt.Sprint(res.Groups().Slice(), " ") + packageGroups := dbExecutor.PackageGroups(res) + if len(packageGroups) != 0 { + toprint += fmt.Sprint(packageGroups, " ") } - localDB, err := alpmHandle.LocalDB() - if err == nil { - if pkg := localDB.Pkg(res.Name()); pkg != nil { - if pkg.Version() != res.Version() { - toprint += bold(green(gotext.Get("(Installed: %s)", pkg.Version()))) - } else { - toprint += bold(green(gotext.Get("(Installed)"))) - } + if pkg := dbExecutor.LocalPackage(res.Name()); pkg != nil { + if pkg.Version() != res.Version() { + toprint += bold(green(gotext.Get("(Installed: %s)", pkg.Version()))) + } else { + toprint += bold(green(gotext.Get("(Installed)"))) } } diff --git a/query.go b/query.go index 124789dd..7a6b2956 100644 --- a/query.go +++ b/query.go @@ -11,6 +11,7 @@ import ( "github.com/leonelquinteros/gotext" rpc "github.com/mikkeloscar/aur" + "github.com/Jguer/yay/v10/pkg/db" "github.com/Jguer/yay/v10/pkg/query" "github.com/Jguer/yay/v10/pkg/settings" "github.com/Jguer/yay/v10/pkg/stringset" @@ -21,7 +22,13 @@ import ( type aurQuery []rpc.Pkg // Query holds the results of a repository search. -type repoQuery []alpm.Package +type repoQuery []db.RepoPackage + +func (s repoQuery) Reverse() { + for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { + s[i], s[j] = s[j], s[i] + } +} func (q aurQuery) Len() int { return len(q) @@ -140,10 +147,9 @@ func narrowSearch(pkgS []string, sortS bool) (aurQuery, error) { } // SyncSearch presents a query to the local repos and to the AUR. -func syncSearch(pkgS []string, alpmHandle *alpm.Handle) (err error) { +func syncSearch(pkgS []string) (err error) { pkgS = query.RemoveInvalidTargets(pkgS, config.Runtime.Mode) var aurErr error - var repoErr error var aq aurQuery var pq repoQuery @@ -151,26 +157,23 @@ func syncSearch(pkgS []string, alpmHandle *alpm.Handle) (err error) { aq, aurErr = narrowSearch(pkgS, true) } if config.Runtime.Mode == settings.ModeRepo || config.Runtime.Mode == settings.ModeAny { - pq, repoErr = queryRepo(pkgS, alpmHandle) - if repoErr != nil { - return err - } + pq = queryRepo(pkgS, config.Runtime.DBExecutor) } switch config.SortMode { case settings.TopDown: if config.Runtime.Mode == settings.ModeRepo || config.Runtime.Mode == settings.ModeAny { - pq.printSearch(alpmHandle) + pq.printSearch(config.Runtime.DBExecutor) } if config.Runtime.Mode == settings.ModeAUR || config.Runtime.Mode == settings.ModeAny { - aq.printSearch(1, alpmHandle) + aq.printSearch(1, config.Runtime.DBExecutor) } case settings.BottomUp: if config.Runtime.Mode == settings.ModeAUR || config.Runtime.Mode == settings.ModeAny { - aq.printSearch(1, alpmHandle) + aq.printSearch(1, config.Runtime.DBExecutor) } if config.Runtime.Mode == settings.ModeRepo || config.Runtime.Mode == settings.ModeAny { - pq.printSearch(alpmHandle) + pq.printSearch(config.Runtime.DBExecutor) } default: return errors.New(gotext.Get("invalid sort mode. Fix with yay -Y --bottomup --save")) @@ -239,30 +242,13 @@ func syncInfo(cmdArgs *settings.Arguments, pkgS []string, alpmHandle *alpm.Handl } // Search handles repo searches. Creates a RepoSearch struct. -func queryRepo(pkgInputN []string, alpmHandle *alpm.Handle) (s repoQuery, err error) { - dbList, err := alpmHandle.SyncDBs() - if err != nil { - return - } - - _ = dbList.ForEach(func(db alpm.DB) error { - if len(pkgInputN) == 0 { - pkgs := db.PkgCache() - s = append(s, pkgs.Slice()...) - } else { - pkgs := db.Search(pkgInputN) - s = append(s, pkgs.Slice()...) - } - return nil - }) +func queryRepo(pkgInputN []string, dbExecutor *db.AlpmExecutor) repoQuery { + s := repoQuery(dbExecutor.SyncPackages(pkgInputN...)) if config.SortMode == settings.BottomUp { - for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { - s[i], s[j] = s[j], s[i] - } + s.Reverse() } - - return + return s } // PackageSlices separates an input slice into aur and repo slices @@ -273,13 +259,13 @@ func packageSlices(toCheck []string, alpmHandle *alpm.Handle) (aur, repo []strin } for _, _pkg := range toCheck { - db, name := text.SplitDBFromName(_pkg) + dbName, name := text.SplitDBFromName(_pkg) found := false - if db == "aur" || config.Runtime.Mode == settings.ModeAUR { + if dbName == "aur" || config.Runtime.Mode == settings.ModeAUR { aur = append(aur, _pkg) continue - } else if db != "" || config.Runtime.Mode == settings.ModeRepo { + } else if dbName != "" || config.Runtime.Mode == settings.ModeRepo { repo = append(repo, _pkg) continue }