get.porter.sh/porter@v1.3.0/pkg/pkgmgmt/feed/load.go (about) 1 package feed 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "net/url" 8 "path" 9 10 "get.porter.sh/porter/pkg/tracing" 11 "github.com/mmcdole/gofeed/atom" 12 "go.opentelemetry.io/otel/attribute" 13 ) 14 15 func (feed *MixinFeed) Load(ctx context.Context, file string) error { 16 _, span := tracing.StartSpan(ctx) 17 defer span.EndSpan() 18 19 contents, err := feed.FileSystem.ReadFile(file) 20 if err != nil { 21 return span.Error(fmt.Errorf("error reading mixin feed at %s: %w", file, err)) 22 } 23 24 p := atom.Parser{} 25 atomFeed, err := p.Parse(bytes.NewReader(contents)) 26 if err != nil { 27 return span.Error(fmt.Errorf("error parsing the mixin feed as an atom xml file: %w", err), 28 attribute.String("contents", string(contents))) 29 } 30 31 feed.Updated = atomFeed.UpdatedParsed 32 33 for _, category := range atomFeed.Categories { 34 feed.Mixins = append(feed.Mixins, category.Term) 35 } 36 37 for _, entry := range atomFeed.Entries { 38 fileset := &MixinFileset{} 39 40 if len(entry.Categories) == 0 { 41 span.Debugf("skipping invalid entry %s, missing category (mixin name)", entry.ID) 42 continue 43 } 44 fileset.Mixin = entry.Categories[0].Term 45 if fileset.Mixin == "" { 46 span.Debugf("skipping invalid entry %s, empty category (mixin name)", entry.ID) 47 continue 48 } 49 50 fileset.Version = entry.Content.Value 51 if fileset.Version == "" { 52 span.Debugf("skipping invalid entry %s, empty content (version)", entry.ID) 53 continue 54 } 55 56 fileset.Files = make([]*MixinFile, 0, len(entry.Links)) 57 for _, link := range entry.Links { 58 if link.Rel == "download" { 59 if entry.UpdatedParsed == nil { 60 span.Debugf("skipping invalid entry %s, invalid updated %q could not be parsed as RFC3339", entry.ID, entry.Updated) 61 continue 62 } 63 64 parsedUrl, err := url.Parse(link.Href) 65 if err != nil || link.Href == "" { 66 span.Debugf("skipping invalid entry %s, invalid link.href %q", entry.ID, link.Href) 67 continue 68 } 69 70 file := &MixinFile{ 71 URL: parsedUrl, 72 Updated: *entry.UpdatedParsed, 73 File: path.Base(parsedUrl.Path), 74 } 75 fileset.Files = append(fileset.Files, file) 76 } 77 } 78 versions, ok := feed.Index[fileset.Mixin] 79 if !ok { 80 versions = map[string]*MixinFileset{} 81 feed.Index[fileset.Mixin] = versions 82 } 83 84 indexedFileset, ok := versions[fileset.Version] 85 if !ok || fileset.GetLastUpdated().After(indexedFileset.GetLastUpdated()) { 86 versions[fileset.Version] = fileset 87 } 88 } 89 90 return nil 91 }