alpm.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. package db
  2. import (
  3. "errors"
  4. alpm "github.com/Jguer/go-alpm"
  5. "github.com/Morganamilo/go-pacmanconf"
  6. "github.com/leonelquinteros/gotext"
  7. "github.com/Jguer/yay/v10/pkg/text"
  8. "github.com/Jguer/yay/v10/pkg/upgrade"
  9. )
  10. type AlpmExecutor struct {
  11. handle *alpm.Handle
  12. localDB *alpm.DB
  13. syncDB alpm.DBList
  14. conf *pacmanconf.Config
  15. questionCallback func(question alpm.QuestionAny)
  16. }
  17. func NewAlpmExecutor(handle *alpm.Handle,
  18. pacamnConf *pacmanconf.Config,
  19. questionCallback func(question alpm.QuestionAny)) (*AlpmExecutor, error) {
  20. localDB, err := handle.LocalDB()
  21. if err != nil {
  22. return nil, err
  23. }
  24. syncDB, err := handle.SyncDBs()
  25. if err != nil {
  26. return nil, err
  27. }
  28. return &AlpmExecutor{handle: handle, localDB: localDB, syncDB: syncDB, conf: pacamnConf, questionCallback: questionCallback}, nil
  29. }
  30. func toUsage(usages []string) alpm.Usage {
  31. if len(usages) == 0 {
  32. return alpm.UsageAll
  33. }
  34. var ret alpm.Usage
  35. for _, usage := range usages {
  36. switch usage {
  37. case "Sync":
  38. ret |= alpm.UsageSync
  39. case "Search":
  40. ret |= alpm.UsageSearch
  41. case "Install":
  42. ret |= alpm.UsageInstall
  43. case "Upgrade":
  44. ret |= alpm.UsageUpgrade
  45. case "All":
  46. ret |= alpm.UsageAll
  47. }
  48. }
  49. return ret
  50. }
  51. func configureAlpm(pacmanConf *pacmanconf.Config, alpmHandle *alpm.Handle) error {
  52. // TODO: set SigLevel
  53. // sigLevel := alpm.SigPackage | alpm.SigPackageOptional | alpm.SigDatabase | alpm.SigDatabaseOptional
  54. // localFileSigLevel := alpm.SigUseDefault
  55. // remoteFileSigLevel := alpm.SigUseDefault
  56. for _, repo := range pacmanConf.Repos {
  57. // TODO: set SigLevel
  58. db, err := alpmHandle.RegisterSyncDB(repo.Name, 0)
  59. if err != nil {
  60. return err
  61. }
  62. db.SetServers(repo.Servers)
  63. db.SetUsage(toUsage(repo.Usage))
  64. }
  65. if err := alpmHandle.SetCacheDirs(pacmanConf.CacheDir); err != nil {
  66. return err
  67. }
  68. // add hook directories 1-by-1 to avoid overwriting the system directory
  69. for _, dir := range pacmanConf.HookDir {
  70. if err := alpmHandle.AddHookDir(dir); err != nil {
  71. return err
  72. }
  73. }
  74. if err := alpmHandle.SetGPGDir(pacmanConf.GPGDir); err != nil {
  75. return err
  76. }
  77. if err := alpmHandle.SetLogFile(pacmanConf.LogFile); err != nil {
  78. return err
  79. }
  80. if err := alpmHandle.SetIgnorePkgs(pacmanConf.IgnorePkg); err != nil {
  81. return err
  82. }
  83. if err := alpmHandle.SetIgnoreGroups(pacmanConf.IgnoreGroup); err != nil {
  84. return err
  85. }
  86. if err := alpmHandle.SetArch(pacmanConf.Architecture); err != nil {
  87. return err
  88. }
  89. if err := alpmHandle.SetNoUpgrades(pacmanConf.NoUpgrade); err != nil {
  90. return err
  91. }
  92. if err := alpmHandle.SetNoExtracts(pacmanConf.NoExtract); err != nil {
  93. return err
  94. }
  95. /*if err := alpmHandle.SetDefaultSigLevel(sigLevel); err != nil {
  96. return err
  97. }
  98. if err := alpmHandle.SetLocalFileSigLevel(localFileSigLevel); err != nil {
  99. return err
  100. }
  101. if err := alpmHandle.SetRemoteFileSigLevel(remoteFileSigLevel); err != nil {
  102. return err
  103. }*/
  104. if err := alpmHandle.SetUseSyslog(pacmanConf.UseSyslog); err != nil {
  105. return err
  106. }
  107. return alpmHandle.SetCheckSpace(pacmanConf.CheckSpace)
  108. }
  109. func logCallback(level alpm.LogLevel, str string) {
  110. switch level {
  111. case alpm.LogWarning:
  112. text.Warn(str)
  113. case alpm.LogError:
  114. text.Error(str)
  115. }
  116. }
  117. func (ae *AlpmExecutor) RefreshHandle() error {
  118. if ae.handle != nil {
  119. if errRelease := ae.handle.Release(); errRelease != nil {
  120. return errRelease
  121. }
  122. }
  123. alpmHandle, err := alpm.Initialize(ae.conf.RootDir, ae.conf.DBPath)
  124. if err != nil {
  125. return errors.New(gotext.Get("unable to CreateHandle: %s", err))
  126. }
  127. if errConf := configureAlpm(ae.conf, alpmHandle); errConf != nil {
  128. return errConf
  129. }
  130. alpmHandle.SetQuestionCallback(ae.questionCallback)
  131. alpmHandle.SetLogCallback(logCallback)
  132. ae.handle = alpmHandle
  133. ae.syncDB, err = alpmHandle.SyncDBs()
  134. if err != nil {
  135. return err
  136. }
  137. ae.localDB, err = alpmHandle.LocalDB()
  138. return err
  139. }
  140. func (ae *AlpmExecutor) LocalSatisfierExists(pkgName string) bool {
  141. if _, err := ae.localDB.PkgCache().FindSatisfier(pkgName); err != nil {
  142. return false
  143. }
  144. return true
  145. }
  146. func (ae *AlpmExecutor) SyncSatisfierExists(pkgName string) bool {
  147. if _, err := ae.syncDB.FindSatisfier(pkgName); err != nil {
  148. return false
  149. }
  150. return true
  151. }
  152. func (ae *AlpmExecutor) IsCorrectVersionInstalled(pkgName, versionRequired string) bool {
  153. alpmPackage := ae.localDB.Pkg(pkgName)
  154. if alpmPackage == nil {
  155. return false
  156. }
  157. return alpmPackage.Version() == versionRequired
  158. }
  159. func (ae *AlpmExecutor) SyncSatisfier(pkgName string) RepoPackage {
  160. foundPkg, err := ae.syncDB.FindSatisfier(pkgName)
  161. if err != nil {
  162. return nil
  163. }
  164. return foundPkg
  165. }
  166. func (ae *AlpmExecutor) PackagesFromGroup(groupName string) []RepoPackage {
  167. groupPackages := []RepoPackage{}
  168. _ = ae.syncDB.FindGroupPkgs(groupName).ForEach(func(pkg alpm.Package) error {
  169. groupPackages = append(groupPackages, &pkg)
  170. return nil
  171. })
  172. return groupPackages
  173. }
  174. func (ae *AlpmExecutor) LocalPackages() []RepoPackage {
  175. localPackages := []RepoPackage{}
  176. _ = ae.localDB.PkgCache().ForEach(func(pkg alpm.Package) error {
  177. localPackages = append(localPackages, RepoPackage(&pkg))
  178. return nil
  179. })
  180. return localPackages
  181. }
  182. // SyncPackages searches SyncDB for packages or returns all packages if no search param is given
  183. func (ae *AlpmExecutor) SyncPackages(pkgNames ...string) []RepoPackage {
  184. repoPackages := []RepoPackage{}
  185. _ = ae.syncDB.ForEach(func(db alpm.DB) error {
  186. if len(pkgNames) == 0 {
  187. _ = db.PkgCache().ForEach(func(pkg alpm.Package) error {
  188. repoPackages = append(repoPackages, RepoPackage(&pkg))
  189. return nil
  190. })
  191. } else {
  192. _ = db.Search(pkgNames).ForEach(func(pkg alpm.Package) error {
  193. repoPackages = append(repoPackages, RepoPackage(&pkg))
  194. return nil
  195. })
  196. }
  197. return nil
  198. })
  199. return repoPackages
  200. }
  201. func (ae *AlpmExecutor) LocalPackage(pkgName string) RepoPackage {
  202. return ae.localDB.Pkg(pkgName)
  203. }
  204. func (ae *AlpmExecutor) PackageFromDB(pkgName, dbName string) RepoPackage {
  205. singleDB, err := ae.handle.SyncDBByName(dbName)
  206. if err != nil {
  207. return nil
  208. }
  209. foundPkg, err := singleDB.PkgCache().FindSatisfier(pkgName)
  210. if err != nil {
  211. return nil
  212. }
  213. return foundPkg
  214. }
  215. func (ae *AlpmExecutor) PackageDepends(pkg RepoPackage) []alpm.Depend {
  216. alpmPackage := pkg.(*alpm.Package)
  217. return alpmPackage.Depends().Slice()
  218. }
  219. func (ae *AlpmExecutor) PackageProvides(pkg RepoPackage) []alpm.Depend {
  220. alpmPackage := pkg.(*alpm.Package)
  221. return alpmPackage.Provides().Slice()
  222. }
  223. func (ae *AlpmExecutor) PackageConflicts(pkg RepoPackage) []alpm.Depend {
  224. alpmPackage := pkg.(*alpm.Package)
  225. return alpmPackage.Conflicts().Slice()
  226. }
  227. func (ae *AlpmExecutor) PackageGroups(pkg RepoPackage) []string {
  228. alpmPackage := pkg.(*alpm.Package)
  229. return alpmPackage.Groups().Slice()
  230. }
  231. // upRepo gathers local packages and checks if they have new versions.
  232. // Output: Upgrade type package list.
  233. func (ae *AlpmExecutor) RepoUpgrades(enableDowngrade bool) (upgrade.UpSlice, error) {
  234. slice := upgrade.UpSlice{}
  235. localDB, err := ae.handle.LocalDB()
  236. if err != nil {
  237. return slice, err
  238. }
  239. err = ae.handle.TransInit(alpm.TransFlagNoLock)
  240. if err != nil {
  241. return slice, err
  242. }
  243. defer func() {
  244. err = ae.handle.TransRelease()
  245. }()
  246. err = ae.handle.SyncSysupgrade(enableDowngrade)
  247. if err != nil {
  248. return slice, err
  249. }
  250. _ = ae.handle.TransGetAdd().ForEach(func(pkg alpm.Package) error {
  251. localVer := "-"
  252. if localPkg := localDB.Pkg(pkg.Name()); localPkg != nil {
  253. localVer = localPkg.Version()
  254. }
  255. slice = append(slice, upgrade.Upgrade{
  256. Name: pkg.Name(),
  257. Repository: pkg.DB().Name(),
  258. LocalVersion: localVer,
  259. RemoteVersion: pkg.Version(),
  260. })
  261. return nil
  262. })
  263. return slice, nil
  264. }
  265. func (ae *AlpmExecutor) AlpmArch() (string, error) {
  266. return ae.handle.Arch()
  267. }
  268. func (ae *AlpmExecutor) BiggestPackages() []RepoPackage {
  269. localPackages := []RepoPackage{}
  270. _ = ae.localDB.PkgCache().SortBySize().ForEach(func(pkg alpm.Package) error {
  271. localPackages = append(localPackages, RepoPackage(&pkg))
  272. return nil
  273. })
  274. return localPackages
  275. }