diff --git a/backends/appstream/appstream.go b/backends/appstream/appstream.go deleted file mode 100644 index e564d9e..0000000 --- a/backends/appstream/appstream.go +++ /dev/null @@ -1,80 +0,0 @@ -package appstream - -import ( - "github.com/Fishwaldo/go-yocto/source" - "github.com/Fishwaldo/go-yocto/utils" -) - -type AsSummary struct { - Lang string `xml:"lang,attr"` - Summary string `xml:",chardata"` -} - -type AsDescription struct { - Lang string `xml:"lang,attr"` - Description string `xml:",chardata"` -} - -type AsReleases struct { - Version string `xml:"version,attr"` - Date string `xml:"date,attr"` -} - -type AppStream struct { - Component xml.Name `xml:"component"` - Name string `xml:"name"` - Summary []AsSummary `xml:"summary"` - Description []AsDescription `xml:"description>p"` - Releases []AsReleases `xml:"releases>release"` -} - -type ASProject struct { - Backend string - BackendID string - Project AppStream -} - - - -type AppStreamBE struct { - ready bool - projects map[string]ASProject -} - -func NewBackend() *AppStreamBE { - return &AppStreamBE{} -} - -func (k *AppStreamBE) GetName() string { - return "AppStream" -} - -func (k *AppStreamBE) Init() error { - utils.Logger.Trace("Initializing AppStream Backend") - k.ready = true - return nil -} - -func (k *AppStreamBE) LoadCache() error { - utils.Logger.Trace("Loading AppStream Cache") - return nil -} - -func (k *AppStreamBE) LoadSource() error { - utils.Logger.Trace("Loading AppStream Source") - return nil -} - -func (k *AppStreamBE) RefreshSource() error { - utils.Logger.Trace("Refreshing AppStream Source") - return nil -} - -func (k *AppStreamBE) SearchSource(keyword string) (source []source.RecipeSource, err error) { - utils.Logger.Trace("Searching AppStream Source", utils.Logger.Args("keyword", keyword)) - return nil, nil -} - -func (k *AppStreamBE) Ready() bool { - return k.ready -} diff --git a/backends/backends.go b/backends/backends.go index d9a7315..69a4771 100644 --- a/backends/backends.go +++ b/backends/backends.go @@ -2,7 +2,6 @@ package backends import ( "github.com/Fishwaldo/go-yocto/backends/kde" - "github.com/Fishwaldo/go-yocto/backends/appstream" "github.com/Fishwaldo/go-yocto/source" "github.com/Fishwaldo/go-yocto/utils" @@ -23,7 +22,6 @@ var Backends map[string]Backend func init() { Backends = make(map[string]Backend) Backends["kde"] = kde.NewBackend() - Backends["appstream"] = appstream.NewBackend() } func Init() (err error) { diff --git a/backends/kde/kde.go b/backends/kde/kde.go index 614515a..e50ccdd 100644 --- a/backends/kde/kde.go +++ b/backends/kde/kde.go @@ -3,16 +3,17 @@ package kde import ( "encoding/base64" "encoding/json" - "encoding/xml" + "io/ioutil" + "net/url" "os" "path/filepath" "strings" - "net/url" + "github.com/Fishwaldo/go-yocto/parsers" "github.com/Fishwaldo/go-yocto/repo" - "github.com/Fishwaldo/go-yocto/utils" "github.com/Fishwaldo/go-yocto/source" + "github.com/Fishwaldo/go-yocto/utils" "golang.org/x/exp/maps" @@ -46,11 +47,6 @@ type Project struct { DNUlegacyproduct string `yaml:"__do_not_use-legacy-product"` } Topics []string - MetaData struct { - Branch string - Dependencies Deps - AppStream AppStream - } } type KDEBe struct { @@ -162,21 +158,23 @@ func (l *KDEBe) parseMetadata() (err error) { utils.Logger.Error("Failed to decode metadata file", utils.Logger.Args("file", files[i], "error", err)) continue } - data.MetaData.Branch = utils.Config.KDEConfig.DefaultBranch + data.MetaData = make(map[string]map[string]interface{}) + data.MetaData["branch-rules"] = make(map[string]interface{}) + data.MetaData["branch-rules"]["branch"] = utils.Config.KDEConfig.DefaultBranch data.RecipeSource.Backend = l.GetName() data.RecipeSource.Url, _ = url.JoinPath(utils.Config.KDEConfig.KDEGitLabURL, data.Repopath) /* find out which branch this is in... */ for project, branch := range l.br[utils.Config.KDEConfig.Release] { ok, _ := filepath.Match(project, data.Repopath) if ok { - data.MetaData.Branch = branch + data.MetaData["branch-rules"]["branch"] = branch break } } /* get the .kde-ci.yml for dependencies */ gf := &gitlab.GetFileOptions{ - Ref: gitlab.String(data.MetaData.Branch), + Ref: gitlab.String(data.MetaData["branch-rules"]["branch"].(string)), } f, res, err := gl.RepositoryFiles.GetFile(data.Repopath, ".kde-ci.yml", gf) if err != nil { @@ -196,7 +194,8 @@ func (l *KDEBe) parseMetadata() (err error) { if err != nil { utils.Logger.Error("Failed to unmarshal .kde-ci.yml", utils.Logger.Args("error", err, "project", data.Repopath)) } else { - data.MetaData.Dependencies = deps + data.MetaData["kde-ci"] = make(map[string]interface{}) + data.MetaData["kde-ci"]["dependencies"] = deps } } } @@ -207,18 +206,19 @@ func (l *KDEBe) parseMetadata() (err error) { utils.Logger.Error("Failed to get appstream", utils.Logger.Args("error", err)) } } else { - /* now parse the appstream */ + /* appstream */ content, err := base64.StdEncoding.DecodeString(f.Content) if err != nil { utils.Logger.Error("Failed to decode appstream", utils.Logger.Args("error", err)) } else { - var as AppStream - err = xml.Unmarshal(content, &as) - if err != nil { - utils.Logger.Error("Failed to unmarshal appstream", utils.Logger.Args("error", err, "project", data.Repopath)) + if as, err := parsers.GetParser("appstream"); err != nil { + utils.Logger.Error("Failed to get appstream parser", utils.Logger.Args("error", err)) } else { - data.MetaData.AppStream = as + if data.MetaData["appstream"], err = as.Parse(strings.NewReader(string(content))); err != nil { + utils.Logger.Error("Failed to parse appstream", utils.Logger.Args("error", err)) + } } + } } diff --git a/cmd/root.go b/cmd/root.go index d647936..a8afd63 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -7,6 +7,7 @@ import ( "os" "github.com/Fishwaldo/go-yocto/backends" + "github.com/Fishwaldo/go-yocto/parsers" "github.com/Fishwaldo/go-yocto/utils" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -61,6 +62,10 @@ func initConfig() { utils.Logger.Error("Failed to initialize Backends", utils.Logger.Args("error", err)) os.Exit(-1) } + if err := parsers.InitParsers(); err != nil { + utils.Logger.Error("Failed to initialize Parsers", utils.Logger.Args("error", err)) + os.Exit(-1) + } if err := backends.LoadCache(); err != nil { utils.Logger.Error("Failed to Load Cache", utils.Logger.Args("error", err)) os.Exit(-1) diff --git a/go.mod b/go.mod index 78cc8a4..71eb7db 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/Fishwaldo/go-yocto go 1.18 require ( + github.com/Masterminds/semver/v3 v3.2.1 github.com/go-git/go-git/v5 v5.6.1 github.com/pterm/pterm v0.12.60 github.com/spf13/cobra v1.7.0 diff --git a/go.sum b/go.sum index 82584b5..40dcde5 100644 --- a/go.sum +++ b/go.sum @@ -53,6 +53,8 @@ github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzX github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/2oUqKc6bF2c= github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYewEjXsvsVUPbE= github.com/MarvinJWendt/testza v0.5.2 h1:53KDo64C1z/h/d/stCYCPY69bt/OSwjq5KpFNwi+zB4= +github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= +github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA= diff --git a/parsers/appstream/appstream.go b/parsers/appstream/appstream.go new file mode 100644 index 0000000..ecbd9bf --- /dev/null +++ b/parsers/appstream/appstream.go @@ -0,0 +1,110 @@ +package appstream + +import ( + "encoding/xml" + "io" + "sort" + "strings" + + // "github.com/Fishwaldo/go-yocto/source" + "github.com/Fishwaldo/go-yocto/utils" + "github.com/Masterminds/semver/v3" +) + +type AsSummary struct { + Lang string `xml:"lang,attr"` + Summary string `xml:",chardata"` +} + +type AsDescription struct { + Lang string `xml:"lang,attr"` + Description string `xml:",chardata"` +} + +type AsReleases struct { + Version string `xml:"version,attr"` + Date string `xml:"date,attr"` +} + +type AppStream struct { + Component xml.Name `xml:"component"` + Name string `xml:"name"` + Summary []AsSummary `xml:"summary"` + Description []AsDescription `xml:"description>p"` + Releases []AsReleases `xml:"releases>release"` +} + +type ASProject struct { + Backend string + BackendID string + Project AppStream +} + +type AppStreamParser struct { + ready bool +} + +func NewParser() *AppStreamParser { + return &AppStreamParser{} +} + +func (k *AppStreamParser) GetName() string { + return "AppStream" +} + +func (k *AppStreamParser) Init() error { + utils.Logger.Trace("Initializing AppStream Parser") + k.ready = true + return nil +} + +func (k *AppStreamParser) Ready() bool { + return k.ready +} + +func (k *AppStreamParser) Parse(data io.Reader) (metadata map[string]interface{}, err error) { + /* now parse the appstream */ + var as AppStream + var raw []byte + raw, err = io.ReadAll(data) + metadata = make(map[string]interface{}) + if err != nil { + utils.Logger.Error("Failed to read appstream", utils.Logger.Args("error", err)) + } else { + err = xml.Unmarshal(raw, &as) + if err != nil { + utils.Logger.Error("Failed to unmarshal appstream", utils.Logger.Args("error", err)) + } else { + for _, v := range as.Summary { + if v.Lang == "" { + metadata["summary"] = strings.TrimSpace(v.Summary) + break; + } + } + for _, v := range as.Description { + if v.Lang == "" { + metadata["description"] = strings.TrimSpace(v.Description) + break; + } + } + var releases []*semver.Version + for _, v := range as.Releases { + ver, err := semver.NewVersion(v.Version) + if err != nil { + utils.Logger.Error("Failed to parse version", utils.Logger.Args("version", v.Version, "error", err)) + continue + } + if ver.Prerelease() != "" { + utils.Logger.Trace("Skipping Prerelease", utils.Logger.Args("version", v.Version)) + continue + } + releases = append(releases, ver) + } + if len(releases) > 0 { + sort.Sort(semver.Collection(releases)) + metadata["version"] = releases[len(releases)-1].Original() + } + } + } + return metadata, nil +} \ No newline at end of file diff --git a/parsers/parsers.go b/parsers/parsers.go new file mode 100644 index 0000000..a59cea9 --- /dev/null +++ b/parsers/parsers.go @@ -0,0 +1,43 @@ +package parsers + +import ( + "errors" + "io" + "strings" + + "github.com/Fishwaldo/go-yocto/parsers/appstream" + "github.com/Fishwaldo/go-yocto/utils" +) + + + +type Parsers interface { + GetName() string + Init() error + Parse(data io.Reader) (metadata map[string]interface{}, err error) +} + +var parsers map[string]Parsers + +func init() { + parsers = make(map[string]Parsers, 0) + as := appstream.NewParser() + parsers[strings.ToLower(as.GetName())] = as +} + +func InitParsers() (err error) { + utils.Logger.Trace("Initializing Parsers") + for _, p := range parsers { + p.Init() + } + return nil +} + +func GetParser(name string) (p Parsers, err error) { + p, ok := parsers[strings.ToLower(name)] + if !ok { + utils.Logger.Error("Parser Not Found", utils.Logger.Args("name", name)) + return nil, errors.New("Parser Not Found") + } + return p, nil +} \ No newline at end of file diff --git a/source/source.go b/source/source.go index 8bbd21a..667f51b 100644 --- a/source/source.go +++ b/source/source.go @@ -6,4 +6,6 @@ type RecipeSource struct { Url string Backend string BackendID string + MetaData map[string]map[string]interface{} } +