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  }