metadata_aur.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. package metadata
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "log"
  6. "github.com/Jguer/aur"
  7. "github.com/itchyny/gojq"
  8. "github.com/ohler55/ojg/oj"
  9. "github.com/tidwall/gjson"
  10. )
  11. type AURCache struct {
  12. cache []byte
  13. provideCache map[string][]*aur.Pkg
  14. unmarshalledCache []interface{}
  15. cacheHits int
  16. gojqCode *gojq.Code
  17. }
  18. func NewAURCache(cachePath string) (*AURCache, error) {
  19. aurCache, err := MakeOrReadCache(cachePath)
  20. if err != nil {
  21. return nil, err
  22. }
  23. inputStruct, err := oj.Parse(aurCache)
  24. return &AURCache{
  25. cache: aurCache,
  26. provideCache: make(map[string][]*aur.Pkg, 300),
  27. unmarshalledCache: inputStruct.([]interface{}),
  28. gojqCode: makeGoJQ(),
  29. }, nil
  30. }
  31. func (a *AURCache) DebugInfo() {
  32. fmt.Println("Byte Cache", len(a.cache))
  33. fmt.Println("Entries Cached", len(a.provideCache))
  34. fmt.Println("Cache Hits", a.cacheHits)
  35. }
  36. func (a *AURCache) SetProvideCache(needle string, pkgs []*aur.Pkg) {
  37. a.provideCache[needle] = pkgs
  38. }
  39. // Get returns a list of packages that provide the given search term
  40. func (a *AURCache) FindPackage(needle string) ([]*aur.Pkg, error) {
  41. if pkgs, ok := a.provideCache[needle]; ok {
  42. a.cacheHits++
  43. return pkgs, nil
  44. }
  45. final, error := a.gojqGet(needle)
  46. if error != nil {
  47. return nil, error
  48. }
  49. a.provideCache[needle] = final
  50. return final, nil
  51. }
  52. func (a *AURCache) gjsonGet(depName string) ([]*aur.Pkg, error) {
  53. dedupMap := make(map[string]bool)
  54. queryProvides := fmt.Sprintf("#(Provides.#(==\"%s\"))#", depName)
  55. queryNames := fmt.Sprintf("#(Name==\"%s\")#", depName)
  56. queryBases := fmt.Sprintf("#(PackageBase==\"%s\")#", depName)
  57. results := gjson.GetManyBytes(a.cache, queryProvides, queryNames, queryBases)
  58. aggregated := append(append(results[0].Array(), results[1].Array()...), results[2].Array()...)
  59. final := make([]*aur.Pkg, 0, len(aggregated))
  60. for i := range aggregated {
  61. jsonString := aggregated[i].Raw
  62. key := jsonString[:15]
  63. if _, ok := dedupMap[key]; !ok {
  64. pkg := &aur.Pkg{}
  65. json.Unmarshal([]byte(jsonString), pkg)
  66. final = append(final, pkg)
  67. dedupMap[key] = true
  68. }
  69. }
  70. return final, nil
  71. }
  72. func (a *AURCache) gojqGet(searchTerm string) ([]*aur.Pkg, error) {
  73. final := make([]*aur.Pkg, 0, 1)
  74. iter := a.gojqCode.Run(a.unmarshalledCache, searchTerm) // or query.RunWithContext
  75. for {
  76. v, ok := iter.Next()
  77. if !ok {
  78. break
  79. }
  80. if err, ok := v.(error); ok {
  81. return nil, err
  82. }
  83. pkg := &aur.Pkg{}
  84. bValue, err := gojq.Marshal(v)
  85. if err != nil {
  86. log.Fatalln(err)
  87. }
  88. json.Unmarshal(bValue, pkg)
  89. final = append(final, pkg)
  90. }
  91. return final, nil
  92. }
  93. func makeGoJQ() *gojq.Code {
  94. // pattern := ".[] | select((.PackageBase == $x) or (.Name == $x) or (.Provides[]? == ($x)))"
  95. pattern := ".[] | select((.Name == $x) or (.Provides[]? == ($x)))"
  96. query, err := gojq.Parse(pattern)
  97. if err != nil {
  98. log.Fatalln(err)
  99. }
  100. compiled, err := gojq.Compile(query, gojq.WithVariables([]string{"$x"}))
  101. if err != nil {
  102. log.Fatalln(err)
  103. }
  104. return compiled
  105. }