get.porter.sh/porter@v1.3.0/pkg/pkgmgmt/search.go (about) 1 package pkgmgmt 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io" 7 "net/http" 8 "sort" 9 "strings" 10 ) 11 12 // Searcher can locate a mixin or plugin from the community feeds. 13 type Searcher struct { 14 List PackageList 15 } 16 17 // NewSearcher creates a new Searcher from a package distribution list. 18 func NewSearcher(list PackageList) Searcher { 19 return Searcher{ 20 List: list, 21 } 22 } 23 24 // Search searches for packages matching the optional provided name, 25 // returning the full list if none is provided 26 func (s *Searcher) Search(name, pkgType string) (PackageList, error) { 27 if name == "" { 28 sort.Sort(s.List) 29 return s.List, nil 30 } 31 32 results := PackageList{} 33 query := strings.ToLower(name) 34 for _, p := range s.List { 35 if strings.Contains(p.Name, query) { 36 results = append(results, p) 37 } 38 } 39 40 if results.Len() == 0 { 41 return PackageList{}, fmt.Errorf("no %ss found for %s", pkgType, name) 42 } 43 44 sort.Sort(results) 45 return results, nil 46 } 47 48 // GetPackageListings returns the listings for packages via the provided URL 49 func GetPackageListings(url string) (PackageList, error) { 50 resp, err := http.Get(url) 51 if err != nil { 52 return PackageList{}, fmt.Errorf("unable to fetch package list via %s: %w", url, err) 53 } 54 if resp.StatusCode != http.StatusOK { 55 return PackageList{}, fmt.Errorf("unable to fetch package list via %s: %s", url, http.StatusText(resp.StatusCode)) 56 } 57 58 defer resp.Body.Close() 59 data, err := io.ReadAll(resp.Body) 60 if err != nil { 61 return PackageList{}, fmt.Errorf("unable to read package list via %s: %w", url, err) 62 } 63 64 list := PackageList{} 65 err = json.Unmarshal(data, &list) 66 if err != nil { 67 return PackageList{}, fmt.Errorf("unable to unmarshal package list: %w", err) 68 } 69 70 return list, nil 71 }