abs.go 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. package download
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "io"
  7. "net/http"
  8. "regexp"
  9. "github.com/leonelquinteros/gotext"
  10. "github.com/Jguer/yay/v12/pkg/settings/exe"
  11. )
  12. const (
  13. MaxConcurrentFetch = 20
  14. absPackageURL = "https://gitlab.archlinux.org/archlinux/packaging/packages"
  15. )
  16. var (
  17. ErrInvalidRepository = errors.New(gotext.Get("invalid repository"))
  18. ErrABSPackageNotFound = errors.New(gotext.Get("package not found in repos"))
  19. )
  20. type regexReplace struct {
  21. repl string
  22. match *regexp.Regexp
  23. }
  24. // regex replacements for Gitlab URLs
  25. // info: https://gitlab.archlinux.org/archlinux/devtools/-/blob/6ce666a1669235749c17d5c44d8a24dea4a135da/src/lib/api/gitlab.sh#L84
  26. var gitlabRepl = []regexReplace{
  27. {repl: `$1-$2`, match: regexp.MustCompile(`([a-zA-Z0-9]+)\+([a-zA-Z]+)`)},
  28. {repl: `plus`, match: regexp.MustCompile(`\+`)},
  29. {repl: `-`, match: regexp.MustCompile(`[^a-zA-Z0-9_\-.]`)},
  30. {repl: `-`, match: regexp.MustCompile(`[_\-]{2,}`)},
  31. {repl: `unix-tree`, match: regexp.MustCompile(`^tree$`)},
  32. }
  33. // Return format for pkgbuild
  34. // https://gitlab.archlinux.org/archlinux/packaging/packages/0ad/-/raw/main/PKGBUILD
  35. func getPackagePKGBUILDURL(pkgName string) string {
  36. return fmt.Sprintf("%s/%s/-/raw/main/PKGBUILD", absPackageURL, convertPkgNameForURL(pkgName))
  37. }
  38. // Return format for pkgbuild repo
  39. // https://gitlab.archlinux.org/archlinux/packaging/packages/0ad.git
  40. func getPackageRepoURL(pkgName string) string {
  41. return fmt.Sprintf("%s/%s.git", absPackageURL, convertPkgNameForURL(pkgName))
  42. }
  43. // convert pkgName for Gitlab URL path (repo name)
  44. func convertPkgNameForURL(pkgName string) string {
  45. for _, regex := range gitlabRepl {
  46. pkgName = regex.match.ReplaceAllString(pkgName, regex.repl)
  47. }
  48. return pkgName
  49. }
  50. // ABSPKGBUILD retrieves the PKGBUILD file to a dest directory.
  51. func ABSPKGBUILD(httpClient httpRequestDoer, dbName, pkgName string) ([]byte, error) {
  52. packageURL := getPackagePKGBUILDURL(pkgName)
  53. resp, err := httpClient.Get(packageURL)
  54. if err != nil {
  55. return nil, err
  56. }
  57. if resp.StatusCode != http.StatusOK {
  58. return nil, ErrABSPackageNotFound
  59. }
  60. defer resp.Body.Close()
  61. pkgBuild, err := io.ReadAll(resp.Body)
  62. if err != nil {
  63. return nil, err
  64. }
  65. return pkgBuild, nil
  66. }
  67. // ABSPKGBUILDRepo retrieves the PKGBUILD repository to a dest directory.
  68. func ABSPKGBUILDRepo(ctx context.Context, cmdBuilder exe.GitCmdBuilder,
  69. dbName, pkgName, dest string, force bool,
  70. ) (bool, error) {
  71. pkgURL := getPackageRepoURL(pkgName)
  72. return downloadGitRepo(ctx, cmdBuilder, pkgURL,
  73. pkgName, dest, force, "--single-branch")
  74. }