install.go 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "os/exec"
  6. "io/ioutil"
  7. "strings"
  8. alpm "github.com/jguer/go-alpm"
  9. rpc "github.com/mikkeloscar/aur"
  10. gopkg "github.com/mikkeloscar/gopkgbuild"
  11. )
  12. // Install handles package installs
  13. func install(parser *arguments) error {
  14. aurs, repos, missing, err := packageSlices(parser.targets.toSlice())
  15. srcinfos := make(map[string]*gopkg.PKGBUILD)
  16. if err != nil {
  17. return err
  18. }
  19. if len(missing) > 0 {
  20. fmt.Println(missing)
  21. fmt.Println("Could not find all Targets")
  22. }
  23. arguments := parser.copy()
  24. arguments.delArg("u", "sysupgrade")
  25. arguments.delArg("y", "refresh")
  26. arguments.op = "S"
  27. arguments.targets = make(stringSet)
  28. arguments.addTarget(repos...)
  29. if len(repos) != 0 {
  30. err := passToPacman(arguments)
  31. if err != nil {
  32. fmt.Println("Error installing repo packages.")
  33. }
  34. }
  35. if len(aurs) != 0 {
  36. //todo make pretty
  37. fmt.Println(greenFg(arrow), greenFg("Resolving Dependencies"))
  38. dt, err := getDepTree(aurs)
  39. if err != nil {
  40. return err
  41. }
  42. if len(dt.Missing) > 0 {
  43. fmt.Println(dt.Missing)
  44. return fmt.Errorf("Could not find all Deps")
  45. }
  46. dc, err := getDepCatagories(aurs, dt)
  47. if err != nil {
  48. return err
  49. }
  50. for _, pkg := range dc.AurMake {
  51. if pkg.Maintainer == "" {
  52. fmt.Println(boldRedFgBlackBg(arrow+" Warning:"),
  53. blackBg(pkg.Name+"-"+pkg.Version+" is orphaned"))
  54. }
  55. }
  56. for _, pkg := range dc.Aur {
  57. if pkg.Maintainer == "" {
  58. fmt.Println(boldRedFgBlackBg(arrow+" Warning:"),
  59. blackBg(pkg.Name+"-"+pkg.Version+" is orphaned"))
  60. }
  61. }
  62. printDownloadsFromRepo("Repo", dc.Repo)
  63. printDownloadsFromRepo("Repo Make", dc.RepoMake)
  64. printDownloadsFromAur("AUR", dc.Aur)
  65. printDownloadsFromAur("AUR Make", dc.AurMake)
  66. askCleanBuilds(dc.AurMake)
  67. askCleanBuilds(dc.Aur)
  68. fmt.Println()
  69. if !continueTask("Proceed with install?", "nN") {
  70. return fmt.Errorf("Aborting due to user")
  71. }
  72. if len(dc.RepoMake) + len(dc.Repo) > 0 {
  73. arguments := parser.copy()
  74. arguments.delArg("u", "sysupgrade")
  75. arguments.delArg("y", "refresh")
  76. arguments.op = "S"
  77. arguments.targets = make(stringSet)
  78. arguments.addArg("needed", "asdeps")
  79. for _, pkg := range dc.Repo {
  80. arguments.addTarget(pkg.Name())
  81. }
  82. for _, pkg := range dc.RepoMake {
  83. arguments.addTarget(pkg.Name())
  84. }
  85. oldConfirm := config.NoConfirm
  86. config.NoConfirm = true
  87. passToPacman(arguments)
  88. config.NoConfirm = oldConfirm
  89. if err != nil {
  90. return err
  91. }
  92. }
  93. // if !continueTask("Proceed with download?", "nN") {
  94. // return fmt.Errorf("Aborting due to user")
  95. // }
  96. if _, ok := arguments.options["gendb"]; !ok {
  97. err = checkForConflicts(dc.Aur, dc.AurMake, dc.Repo, dc.RepoMake)
  98. if err != nil {
  99. return err
  100. }
  101. }
  102. err = dowloadPkgBuilds(dc.AurMake)
  103. if err != nil {
  104. return err
  105. }
  106. err = dowloadPkgBuilds(dc.Aur)
  107. if err != nil {
  108. return err
  109. }
  110. err = askEditPkgBuilds(dc.AurMake)
  111. if err != nil {
  112. return err
  113. }
  114. err = askEditPkgBuilds(dc.Aur)
  115. if err != nil {
  116. return err
  117. }
  118. if _, ok := arguments.options["gendb"]; ok {
  119. fmt.Println("GenDB finished. No packages were installed")
  120. return nil
  121. }
  122. // if !continueTask("Proceed with install?", "nN") {
  123. // return fmt.Errorf("Aborting due to user")
  124. // }
  125. err = downloadPkgBuildsSources(dc.AurMake)
  126. if err != nil {
  127. return err
  128. }
  129. err = downloadPkgBuildsSources(dc.Aur)
  130. if err != nil {
  131. return err
  132. }
  133. err = parsesrcinfos(dc.AurMake, srcinfos)
  134. if err != nil {
  135. return err
  136. }
  137. err = parsesrcinfos(dc.Aur, srcinfos)
  138. if err != nil {
  139. return err
  140. }
  141. err = buildInstallPkgBuilds(dc.AurMake, srcinfos, parser.targets, parser)
  142. if err != nil {
  143. return err
  144. }
  145. err = buildInstallPkgBuilds(dc.Aur, srcinfos, parser.targets, parser)
  146. if err != nil {
  147. return err
  148. }
  149. if len(dc.RepoMake)+len(dc.AurMake) > 0 {
  150. if continueTask("Remove make dependencies?", "yY") {
  151. return nil
  152. }
  153. removeArguments := makeArguments()
  154. removeArguments.addArg("R", "u")
  155. for _, pkg := range dc.RepoMake {
  156. removeArguments.addTarget(pkg.Name())
  157. }
  158. for _, pkg := range dc.AurMake {
  159. removeArguments.addTarget(pkg.Name)
  160. }
  161. oldValue := config.NoConfirm
  162. config.NoConfirm = true
  163. passToPacman(removeArguments)
  164. config.NoConfirm = oldValue
  165. }
  166. return nil
  167. }
  168. return nil
  169. }
  170. func askCleanBuilds(pkgs []*rpc.Pkg) {
  171. for _, pkg := range pkgs {
  172. dir := config.BuildDir + pkg.PackageBase + "/"
  173. if _, err := os.Stat(dir); !os.IsNotExist(err) {
  174. if !continueTask(pkg.Name+" Directory exists. Clean Build?", "yY") {
  175. _ = os.RemoveAll(config.BuildDir + pkg.PackageBase)
  176. }
  177. }
  178. }
  179. }
  180. func checkForConflicts(aur []*rpc.Pkg, aurMake []*rpc.Pkg, repo []*alpm.Package,
  181. repoMake []*alpm.Package) error {
  182. localDb, err := alpmHandle.LocalDb()
  183. if err != nil {
  184. return err
  185. }
  186. var toRemove []string
  187. for _, pkg := range aur {
  188. for _, cpkg := range pkg.Conflicts {
  189. if _, err := localDb.PkgByName(cpkg); err == nil {
  190. toRemove = append(toRemove, cpkg)
  191. }
  192. }
  193. }
  194. for _, pkg := range aurMake {
  195. for _, cpkg := range pkg.Conflicts {
  196. if _, err := localDb.PkgByName(cpkg); err == nil {
  197. toRemove = append(toRemove, cpkg)
  198. }
  199. }
  200. }
  201. for _, pkg := range repo {
  202. pkg.Conflicts().ForEach(func(conf alpm.Depend) error {
  203. if _, err := localDb.PkgByName(conf.Name); err == nil {
  204. toRemove = append(toRemove, conf.Name)
  205. }
  206. return nil
  207. })
  208. }
  209. for _, pkg := range repoMake {
  210. pkg.Conflicts().ForEach(func(conf alpm.Depend) error {
  211. if _, err := localDb.PkgByName(conf.Name); err == nil {
  212. toRemove = append(toRemove, conf.Name)
  213. }
  214. return nil
  215. })
  216. }
  217. if len(toRemove) != 0 {
  218. fmt.Println(
  219. redFg("The following packages conflict with packages to install:"))
  220. for _, pkg := range toRemove {
  221. fmt.Println(yellowFg(pkg))
  222. }
  223. if !continueTask("Remove conflicting package(s)?", "nN") {
  224. return fmt.Errorf("Aborting due to user")
  225. }
  226. removeArguments := makeArguments()
  227. removeArguments.addArg("R", "d", "d")
  228. for _, pkg := range toRemove {
  229. removeArguments.addTarget(pkg)
  230. }
  231. oldValue := config.NoConfirm
  232. config.NoConfirm = true
  233. passToPacman(removeArguments)
  234. config.NoConfirm = oldValue
  235. }
  236. return nil
  237. }
  238. func askEditPkgBuilds(pkgs []*rpc.Pkg) (error) {
  239. for _, pkg := range pkgs {
  240. dir := config.BuildDir + pkg.PackageBase + "/"
  241. if !continueTask(pkg.Name+" Edit PKGBUILD?", "yY") {
  242. editcmd := exec.Command(editor(), dir+"PKGBUILD")
  243. editcmd.Stdin, editcmd.Stdout, editcmd.Stderr = os.Stdin, os.Stdout, os.Stderr
  244. editcmd.Run()
  245. }
  246. }
  247. return nil
  248. }
  249. func parsesrcinfos(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD) (error) {
  250. for _, pkg := range pkgs {
  251. dir := config.BuildDir + pkg.PackageBase + "/"
  252. cmd := exec.Command(config.MakepkgBin, "--printsrcinfo")
  253. cmd.Stderr = os.Stderr
  254. cmd.Dir = dir
  255. srcinfo, err := cmd.Output()
  256. if err != nil {
  257. return err
  258. }
  259. pkgbuild, err := gopkg.ParseSRCINFOContent(srcinfo)
  260. if err == nil {
  261. srcinfos[pkg.PackageBase] = pkgbuild
  262. for _, pkgsource := range pkgbuild.Source {
  263. owner, repo := parseSource(pkgsource)
  264. if owner != "" && repo != "" {
  265. err = branchInfo(pkg.Name, owner, repo)
  266. if err != nil {
  267. return err
  268. }
  269. }
  270. }
  271. }
  272. }
  273. return nil
  274. }
  275. func dowloadPkgBuilds(pkgs []*rpc.Pkg) (err error) {
  276. for _, pkg := range pkgs {
  277. //todo make pretty
  278. fmt.Println("Downloading:", pkg.Name+"-"+pkg.Version)
  279. err = downloadAndUnpack(baseURL+pkg.URLPath, config.BuildDir, false)
  280. if err != nil {
  281. return
  282. }
  283. }
  284. return
  285. }
  286. func downloadPkgBuildsSources(pkgs []*rpc.Pkg) (err error) {
  287. for _, pkg := range pkgs {
  288. dir := config.BuildDir + pkg.PackageBase + "/"
  289. err = passToMakepkg(dir, "--nobuild", "--nocheck", "--noprepare", "--nodeps")
  290. if err != nil {
  291. return
  292. }
  293. }
  294. return
  295. }
  296. func buildInstallPkgBuilds(pkgs []*rpc.Pkg, srcinfos map[string]*gopkg.PKGBUILD, targets stringSet, parser *arguments) (error) {
  297. //for n := len(pkgs) -1 ; n > 0; n-- {
  298. for n := 0; n < len(pkgs); n++ {
  299. pkg := pkgs[n]
  300. dir := config.BuildDir + pkg.PackageBase + "/"
  301. srcinfo := srcinfos[pkg.PackageBase]
  302. version := srcinfo.CompleteVersion()
  303. file, err := completeFileName(dir, pkg.Name + "-" + version.String())
  304. if file != "" {
  305. fmt.Println(boldRedFgBlackBg(arrow+" Warning:"),
  306. blackBg(pkg.Name+"-"+pkg.Version+ " Already made -- skipping build"))
  307. } else {
  308. err = passToMakepkg(dir, "-Cscf", "--noconfirm")
  309. if err != nil {
  310. return err
  311. }
  312. file, err = completeFileName(dir, pkg.Name + "-" + version.String())
  313. if err != nil {
  314. return err
  315. }
  316. if file == "" {
  317. return fmt.Errorf("Could not find built package")
  318. }
  319. }
  320. arguments := parser.copy()
  321. arguments.targets = make(stringSet)
  322. arguments.op = "U"
  323. arguments.delArg("confirm")
  324. arguments.delArg("c", "clean")
  325. arguments.delArg("q", "quiet")
  326. arguments.delArg("q", "quiet")
  327. arguments.delArg("y", "refresh")
  328. arguments.delArg("u", "sysupgrade")
  329. arguments.delArg("w", "downloadonly")
  330. oldConfirm := config.NoConfirm
  331. config.NoConfirm = true
  332. if targets.get(pkg.Name) {
  333. arguments.addArg("asdeps")
  334. }
  335. arguments.addTarget(file)
  336. err = passToPacman(arguments)
  337. config.NoConfirm = oldConfirm
  338. if err !=nil {
  339. return err
  340. }
  341. }
  342. return nil
  343. }
  344. func completeFileName(dir, name string) (string, error) {
  345. files, err := ioutil.ReadDir(dir)
  346. if err != nil {
  347. return "", err
  348. }
  349. for _, file := range files {
  350. if file.IsDir() {
  351. continue
  352. }
  353. if strings.HasPrefix(file.Name(), name) {
  354. return dir + file.Name(), nil
  355. }
  356. }
  357. return "", nil
  358. }