mirror of
https://github.com/Fishwaldo/go-yocto.git
synced 2025-03-15 11:21:39 +00:00
Create Recipe Templates works
This commit is contained in:
parent
df721d773c
commit
31c8aab494
14 changed files with 651 additions and 56 deletions
|
@ -1,10 +1,11 @@
|
|||
package backends
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/Fishwaldo/go-yocto/backends/kde"
|
||||
"github.com/Fishwaldo/go-yocto/source"
|
||||
"github.com/Fishwaldo/go-yocto/utils"
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
@ -13,7 +14,8 @@ type Backend interface {
|
|||
Init() error
|
||||
LoadCache() error
|
||||
LoadSource() error
|
||||
SearchSource(keyword string) (source []source.RecipeSource, err error)
|
||||
SearchSource(keyword string) (source []source.RecipeSource, err error)
|
||||
GetRecipe(identifier string) (*source.RecipeSource, error)
|
||||
Ready() bool
|
||||
}
|
||||
|
||||
|
@ -77,4 +79,19 @@ func SearchSource(be string, keyword string) (sources []source.RecipeSource, err
|
|||
}
|
||||
}
|
||||
return sources, nil
|
||||
}
|
||||
|
||||
func GetRecipe(be string, identifier string) (source *source.RecipeSource, err error) {
|
||||
utils.Logger.Trace("Getting Recipe", utils.Logger.Args("backend", be, "identifier", identifier))
|
||||
if be, ok := Backends[be]; ok {
|
||||
if source, err := be.GetRecipe(identifier); err != nil {
|
||||
utils.Logger.Error("Failed to Get Recipe", utils.Logger.Args("backend", be.GetName(), "identifier", identifier, "error", err))
|
||||
return nil, errors.New("Failed to Get Recipe")
|
||||
} else {
|
||||
return source, nil
|
||||
}
|
||||
} else {
|
||||
utils.Logger.Error("Backend not found", utils.Logger.Args("backend", be))
|
||||
}
|
||||
return nil, errors.New("Backend not found")
|
||||
}
|
|
@ -1,15 +1,20 @@
|
|||
package kde
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
// "fmt"
|
||||
|
||||
"github.com/Fishwaldo/go-yocto/parsers"
|
||||
"github.com/Fishwaldo/go-yocto/repo"
|
||||
"github.com/Fishwaldo/go-yocto/source"
|
||||
|
@ -21,24 +26,14 @@ import (
|
|||
"github.com/spf13/viper"
|
||||
"github.com/xanzy/go-gitlab"
|
||||
"gopkg.in/yaml.v3"
|
||||
// "github.com/davecgh/go-spew/spew"
|
||||
)
|
||||
|
||||
|
||||
type Deps struct {
|
||||
Dependencies []struct {
|
||||
On []string
|
||||
Require map[string]string
|
||||
} `yaml:"Dependencies"`
|
||||
Options interface{} `yaml:"Options"`
|
||||
Environment interface{} `yaml:"Environment"`
|
||||
}
|
||||
|
||||
type Project struct {
|
||||
source.RecipeSource `yaml:",inline"`
|
||||
ProjectPath string
|
||||
Repoactive bool
|
||||
Repopath string
|
||||
Identifier string
|
||||
Hasrepo bool
|
||||
Source string
|
||||
Bugzilla struct {
|
||||
|
@ -47,12 +42,14 @@ type Project struct {
|
|||
DNUlegacyproduct string `yaml:"__do_not_use-legacy-product"`
|
||||
}
|
||||
Topics []string
|
||||
MetaData map[string]map[string]interface{}
|
||||
}
|
||||
|
||||
type KDEBe struct {
|
||||
MetaDataRepo repo.Repo
|
||||
br map[string]map[string]string
|
||||
pr map[string]Project
|
||||
dep map[string][]string
|
||||
ready bool
|
||||
}
|
||||
|
||||
|
@ -103,6 +100,7 @@ func (l *KDEBe) LoadSource() (err error) {
|
|||
}
|
||||
maps.Clear(l.br)
|
||||
maps.Clear(l.pr)
|
||||
maps.Clear(l.dep)
|
||||
err = l.parseMetadata()
|
||||
if (err != nil) {
|
||||
utils.Logger.Error("Failed to parse metadata", utils.Logger.Args("error", err))
|
||||
|
@ -113,16 +111,18 @@ func (l *KDEBe) LoadSource() (err error) {
|
|||
|
||||
|
||||
func (l *KDEBe) parseMetadata() (err error) {
|
||||
l.pr = make(map[string]Project)
|
||||
utils.Logger.Trace("Parsing metadata", utils.Logger.Args("layer", l.GetName()))
|
||||
|
||||
l.pr = make(map[string]Project)
|
||||
l.br = make(map[string]map[string]string)
|
||||
l.dep = make(map[string][]string)
|
||||
|
||||
brfile, err := ioutil.ReadFile(l.getDir() + "/branch-rules.yml")
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to read branch-rules.yaml", utils.Logger.Args("error", err))
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
l.br = make(map[string]map[string]string)
|
||||
|
||||
err = yaml.Unmarshal(brfile, &l.br)
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to unmarshal branch-rules.yaml", utils.Logger.Args("error", err))
|
||||
|
@ -140,6 +140,22 @@ func (l *KDEBe) parseMetadata() (err error) {
|
|||
os.Exit(-1)
|
||||
}
|
||||
|
||||
/* parse dependancy file dependencies/dependency-data-kf5-qt5 */
|
||||
depsfile, err := os.Open(l.getDir() + "/dependencies/dependency-data-kf5-qt5")
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to open dependency file", utils.Logger.Args("error", err))
|
||||
}
|
||||
defer depsfile.Close()
|
||||
scanner := bufio.NewScanner(depsfile)
|
||||
var entry = regexp.MustCompile(`^(.*):.(.*)$`)
|
||||
for scanner.Scan() {
|
||||
if entry.MatchString(scanner.Text()) {
|
||||
match := entry.FindStringSubmatch(scanner.Text())
|
||||
l.dep[match[1]] = append(l.dep[match[1]], match[2])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* now parse the directory */
|
||||
files := findmetdata(l.getDir())
|
||||
p, _ := pterm.DefaultProgressbar.WithTotal(len(files)).WithTitle("Parsing Metadata...").Start()
|
||||
|
@ -161,7 +177,7 @@ func (l *KDEBe) parseMetadata() (err error) {
|
|||
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.BackendID = 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] {
|
||||
|
@ -171,36 +187,11 @@ func (l *KDEBe) parseMetadata() (err error) {
|
|||
break
|
||||
}
|
||||
}
|
||||
|
||||
/* get the .kde-ci.yml for dependencies */
|
||||
gf := &gitlab.GetFileOptions{
|
||||
Ref: gitlab.String(data.MetaData["branch-rules"]["branch"].(string)),
|
||||
}
|
||||
f, res, err := gl.RepositoryFiles.GetFile(data.Repopath, ".kde-ci.yml", gf)
|
||||
if err != nil {
|
||||
if res.StatusCode != 404 {
|
||||
utils.Logger.Error("Failed to get .kde-ci.yml", utils.Logger.Args("error", err))
|
||||
}
|
||||
} else {
|
||||
/* now parse the .kde-ci.yml */
|
||||
var deps Deps
|
||||
content, err := base64.StdEncoding.DecodeString(f.Content)
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to decode .kde-ci.yml", utils.Logger.Args("error", err))
|
||||
} else {
|
||||
ymldeps := yaml.NewDecoder(strings.NewReader(string(content)))
|
||||
ymldeps.KnownFields(false);
|
||||
err = ymldeps.Decode(&deps)
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to unmarshal .kde-ci.yml", utils.Logger.Args("error", err, "project", data.Repopath))
|
||||
} else {
|
||||
data.MetaData["kde-ci"] = make(map[string]interface{})
|
||||
data.MetaData["kde-ci"]["dependencies"] = deps
|
||||
}
|
||||
}
|
||||
}
|
||||
/* now get appstream if it exists */
|
||||
f, res, err = gl.RepositoryFiles.GetFile(data.Repopath, "org.kde." + data.Identifier + ".appdata.xml", gf)
|
||||
f, res, err := gl.RepositoryFiles.GetFile(data.Repopath, "org.kde." + data.Identifier + ".appdata.xml", gf)
|
||||
if err != nil {
|
||||
if res.StatusCode != 404 {
|
||||
utils.Logger.Error("Failed to get appstream", utils.Logger.Args("error", err))
|
||||
|
@ -240,6 +231,17 @@ func (l *KDEBe) parseMetadata() (err error) {
|
|||
utils.Logger.Error("Failed to write metadata", utils.Logger.Args("error", err))
|
||||
os.Exit(-1)
|
||||
}
|
||||
depcache, err := json.Marshal(l.dep)
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to marshal dependancy metadata", utils.Logger.Args("error", err))
|
||||
os.Exit(-1)
|
||||
}
|
||||
err = ioutil.WriteFile(utils.Config.BaseDir + "/" + l.GetName() + "-dep-cache.json", depcache, 0644)
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to write dependancy metadata", utils.Logger.Args("error", err))
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
brcache, err := json.Marshal(l.br)
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to marshal branch metadata", utils.Logger.Args("error", err))
|
||||
|
@ -250,6 +252,10 @@ func (l *KDEBe) parseMetadata() (err error) {
|
|||
utils.Logger.Error("Failed to write branch metadata", utils.Logger.Args("error", err))
|
||||
os.Exit(-1)
|
||||
}
|
||||
if err := RefreshDownloadLocations(); err != nil {
|
||||
utils.Logger.Error("Failed to refresh download locations", utils.Logger.Args("error", err))
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
utils.Logger.Trace("Parsed metadata", utils.Logger.Args("layers", len(l.pr), "branches", len(l.br)));
|
||||
|
||||
|
@ -268,6 +274,15 @@ func (l *KDEBe) LoadCache() (err error) {
|
|||
utils.Logger.Error("Failed to unmarshal cache", utils.Logger.Args("error", err))
|
||||
}
|
||||
}
|
||||
depcache, err := ioutil.ReadFile(utils.Config.BaseDir + "/" + l.GetName() + "-dep-cache.json")
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to read dependancy cache", utils.Logger.Args("error", err))
|
||||
} else {
|
||||
err = json.Unmarshal(depcache, &l.dep)
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to unmarshal dependancy cache", utils.Logger.Args("error", err))
|
||||
}
|
||||
}
|
||||
brcache, err := ioutil.ReadFile(utils.Config.BaseDir + "/" + l.GetName() + "-branch-cache.json")
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to read branch cache", utils.Logger.Args("error", err))
|
||||
|
@ -277,7 +292,9 @@ func (l *KDEBe) LoadCache() (err error) {
|
|||
utils.Logger.Error("Failed to unmarshal branch cache", utils.Logger.Args("error", err))
|
||||
}
|
||||
}
|
||||
|
||||
if err := LoadDownloadLocationsCache(); err != nil {
|
||||
utils.Logger.Error("Failed to load download locations cache", utils.Logger.Args("error", err))
|
||||
}
|
||||
utils.Logger.Trace("KDE Cache Loaded", utils.Logger.Args("layers", len(l.pr), "branches", len(l.br)))
|
||||
return nil
|
||||
}
|
||||
|
@ -312,4 +329,66 @@ func findmetdata(path string) (files []string) {
|
|||
panic(err)
|
||||
}
|
||||
return files
|
||||
}
|
||||
}
|
||||
|
||||
func (l *KDEBe) GetRecipe(identifier string) (*source.RecipeSource, error) {
|
||||
utils.Logger.Trace("Getting KDE Recipe", utils.Logger.Args("recipe", identifier))
|
||||
if recipe, ok := l.pr[identifier]; ok {
|
||||
|
||||
/* get the summary if it exists from appstream */
|
||||
if as, ok := recipe.MetaData["appstream"]; ok {
|
||||
if summary, ok := as["summary"]; ok {
|
||||
recipe.Summary = summary.(string)
|
||||
}
|
||||
} else {
|
||||
result, _ := pterm.DefaultInteractiveTextInput.WithMultiLine(false).Show("Summary")
|
||||
recipe.Summary = strings.TrimSpace(result)
|
||||
}
|
||||
/* get version from Appstream */
|
||||
if as, ok := recipe.MetaData["appstream"]; ok {
|
||||
if version, ok := as["version"]; ok {
|
||||
recipe.Version = version.(string)
|
||||
}
|
||||
} else {
|
||||
result, _ := pterm.DefaultInteractiveTextInput.WithMultiLine(false).Show("Version Number")
|
||||
recipe.Version = strings.TrimSpace(result)
|
||||
}
|
||||
if dlpath, err := GetDownloadPath(recipe.Identifier, recipe.Version); err != nil {
|
||||
utils.Logger.Error("Failed to get download path", utils.Logger.Args("error", err))
|
||||
return nil, err
|
||||
} else {
|
||||
recipe.SrcURI = dlpath
|
||||
}
|
||||
if (len(recipe.SrcURI) > 0) {
|
||||
if sha, err := GetDownloadSHA(recipe.Identifier, recipe.Version); err != nil {
|
||||
utils.Logger.Error("Failed to get download SHA", utils.Logger.Args("error", err))
|
||||
} else {
|
||||
recipe.SrcSHA256 = sha
|
||||
}
|
||||
}
|
||||
licenses, err := GetLicense(recipe)
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to get License", utils.Logger.Args("error", err))
|
||||
} else {
|
||||
recipe.Licenses = licenses
|
||||
}
|
||||
|
||||
inherits, err := GetInherits(recipe, l.dep)
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to get Inherits", utils.Logger.Args("error", err))
|
||||
} else {
|
||||
recipe.Inherits = inherits
|
||||
}
|
||||
|
||||
depends, err := GetDepends(recipe, l.dep)
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to get Inherits", utils.Logger.Args("error", err))
|
||||
} else {
|
||||
recipe.Depends = depends
|
||||
}
|
||||
recipe.Section = path.Dir(recipe.Repopath)
|
||||
|
||||
return &recipe.RecipeSource, nil
|
||||
}
|
||||
return nil, errors.New("Recipe Not Found")
|
||||
}
|
||||
|
|
117
backends/kde/kdedownload.go
Normal file
117
backends/kde/kdedownload.go
Normal file
|
@ -0,0 +1,117 @@
|
|||
package kde
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"regexp"
|
||||
"net/http"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"errors"
|
||||
"strings"
|
||||
"crypto/sha256"
|
||||
"io"
|
||||
"fmt"
|
||||
|
||||
"github.com/Fishwaldo/go-yocto/utils"
|
||||
"github.com/pterm/pterm"
|
||||
)
|
||||
|
||||
type dirListing struct {
|
||||
Directory string
|
||||
}
|
||||
|
||||
var files map[string]map[string]dirListing = make(map[string]map[string]dirListing)
|
||||
|
||||
func LoadDownloadLocationsCache() (error) {
|
||||
utils.Logger.Trace("Loading KDE Download Cache")
|
||||
cache, err := ioutil.ReadFile(utils.Config.BaseDir + "/kdedownload-cache.json")
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to read download cache", utils.Logger.Args("error", err))
|
||||
return RefreshDownloadLocations()
|
||||
} else {
|
||||
err = json.Unmarshal(cache, &files)
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to unmarshal cache", utils.Logger.Args("error", err))
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func RefreshDownloadLocations() (error) {
|
||||
file, err := http.Get("https://download.kde.org/ls-lR")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Body.Close()
|
||||
scanner := bufio.NewScanner(file.Body)
|
||||
var directory = regexp.MustCompile(`^(\./)?(.+):$`)
|
||||
var fn = regexp.MustCompile(`^[^dl].* ((.*)-(.*)\.tar\.(bz2|xz))$`)
|
||||
var curdir string
|
||||
for scanner.Scan() {
|
||||
if directory.MatchString(scanner.Text()) {
|
||||
curdir = strings.TrimPrefix( directory.FindStringSubmatch(scanner.Text())[2], "/srv/archives/ftp/")
|
||||
|
||||
}
|
||||
if fn.MatchString(scanner.Text()) {
|
||||
f := fn.FindStringSubmatch(scanner.Text())
|
||||
if _, ok := files[f[2]]; !ok {
|
||||
files[f[2]] = make(map[string]dirListing)
|
||||
}
|
||||
files[f[2]][f[3]] = dirListing{Directory: curdir + "/" + f[1]}
|
||||
}
|
||||
}
|
||||
cache, err := json.Marshal(files)
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to marshal metadata", utils.Logger.Args("error", err))
|
||||
return err
|
||||
}
|
||||
err = ioutil.WriteFile(utils.Config.BaseDir + "/kdedownload-cache.json", cache, 0644)
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to write metadata", utils.Logger.Args("error", err))
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetDownloadPath(source string, version string) (string, error) {
|
||||
if _, ok := files[source]; !ok {
|
||||
return "", errors.New("Source not found")
|
||||
}
|
||||
if _, ok := files[source][version]; !ok {
|
||||
return "", errors.New("Version not found")
|
||||
}
|
||||
return "https://download.kde.org/" + files[source][version].Directory, nil
|
||||
}
|
||||
|
||||
func GetDownloadSHA(source string, version string) (string, error) {
|
||||
if _, ok := files[source]; !ok {
|
||||
return "", errors.New("Source not found")
|
||||
}
|
||||
if _, ok := files[source][version]; !ok {
|
||||
return "", errors.New("Version not found")
|
||||
}
|
||||
path, err := GetDownloadPath(source, version)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
utils.Logger.Trace("Getting SHA", utils.Logger.Args("path", path))
|
||||
spinnerInfo, _ := pterm.DefaultSpinner.Start("Downloading Source for SHA Calculation")
|
||||
|
||||
file, err := http.Get(path)
|
||||
if err != nil {
|
||||
utils.Logger.Warn("Failed to get SHA", utils.Logger.Args("path", path, "error", err))
|
||||
spinnerInfo.Fail("Failed to Download Source for SHA Calculation")
|
||||
return "", err
|
||||
}
|
||||
defer file.Body.Close()
|
||||
hash := sha256.New()
|
||||
if _, err := io.Copy(hash, file.Body); err != nil {
|
||||
utils.Logger.Warn("Failed to calculate SHA", utils.Logger.Args("path", path, "error", err))
|
||||
spinnerInfo.Fail("Failed to Download Source for SHA Calculation")
|
||||
return "", err
|
||||
}
|
||||
spinnerInfo.Success("Downloaded Source for SHA Calculation")
|
||||
return fmt.Sprintf("%x", hash.Sum(nil)), nil
|
||||
|
||||
}
|
54
backends/kde/kdedpendancies.go
Normal file
54
backends/kde/kdedpendancies.go
Normal file
|
@ -0,0 +1,54 @@
|
|||
package kde
|
||||
|
||||
import (
|
||||
"path"
|
||||
|
||||
"github.com/Fishwaldo/go-yocto/utils"
|
||||
)
|
||||
|
||||
var inheritmap map[string]string = make(map[string]string)
|
||||
var dependmap map[string]string = make(map[string]string)
|
||||
|
||||
func init() {
|
||||
inheritmap = map[string]string {
|
||||
"frameworks/extra-cmake-modules": "cmake_plasma",
|
||||
"frameworks/kauth": "kauth",
|
||||
"frameworks/kcmutils": "kcmutils",
|
||||
"frameworks/kconfig": "kconfig",
|
||||
"frameworks/kcoreaddons": "kcoreaddons",
|
||||
"frameworks/kdoctools": "kdoctools",
|
||||
"frameworks/ki18n" : "ki18n",
|
||||
}
|
||||
dependmap = map[string]string {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
func GetInherits(pr Project, depmap map[string][]string) (inherits []string, err error) {
|
||||
utils.Logger.Trace("Getting Inherits", utils.Logger.Args("project", pr.Name))
|
||||
if _, ok := depmap[pr.ProjectPath]; ok {
|
||||
for _, v := range depmap[pr.ProjectPath] {
|
||||
if i, ok := inheritmap[v]; ok {
|
||||
inherits = append(inherits, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
/* add our default inherit */
|
||||
inherits = append(inherits, "reuse_license_checksums")
|
||||
|
||||
return inherits, nil
|
||||
}
|
||||
|
||||
func GetDepends(pr Project, depmap map[string][]string) (depends []string, err error) {
|
||||
utils.Logger.Trace("Getting Depends", utils.Logger.Args("project", pr.Name))
|
||||
if _, ok := depmap[pr.ProjectPath]; ok {
|
||||
for _, v := range depmap[pr.ProjectPath] {
|
||||
if _, ok := inheritmap[v]; !ok {
|
||||
depends = append(depends, path.Base(v))
|
||||
}
|
||||
}
|
||||
}
|
||||
return depends, nil
|
||||
}
|
33
backends/kde/kdelicenses.go
Normal file
33
backends/kde/kdelicenses.go
Normal file
|
@ -0,0 +1,33 @@
|
|||
package kde
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/Fishwaldo/go-yocto/utils"
|
||||
"github.com/xanzy/go-gitlab"
|
||||
)
|
||||
|
||||
|
||||
|
||||
func GetLicense(pr Project) (license []string, err error) {
|
||||
utils.Logger.Trace("Getting License", utils.Logger.Args("project", pr.Name))
|
||||
gl, err := gitlab.NewClient(utils.Config.KDEConfig.AccessToken, gitlab.WithBaseURL(utils.Config.KDEConfig.KDEGitLabURL+"/api/v4"))
|
||||
|
||||
gf := &gitlab.ListTreeOptions {
|
||||
Path: gitlab.String("LICENSES"),
|
||||
Ref: gitlab.String(pr.MetaData["branch-rules"]["branch"].(string)),
|
||||
}
|
||||
f, res, err := gl.Repositories.ListTree(pr.Repopath, gf)
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to get License", utils.Logger.Args("error", err))
|
||||
return nil, err
|
||||
}
|
||||
if res.StatusCode != 200 {
|
||||
utils.Logger.Error("Failed to get License", utils.Logger.Args("error", res.Status))
|
||||
return nil, err
|
||||
}
|
||||
for _, file := range f {
|
||||
license = append(license, strings.TrimSuffix(file.Name, ".txt"))
|
||||
}
|
||||
return license, nil
|
||||
}
|
39
cmd/recipe.go
Normal file
39
cmd/recipe.go
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
|
||||
|
||||
*/
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/Fishwaldo/go-yocto/utils"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/Fishwaldo/go-yocto/cmd/recipe"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// recipeCmd represents the recipe command
|
||||
var recipeCmd = &cobra.Command{
|
||||
Use: "recipe",
|
||||
Short: "A brief description of your command",
|
||||
Long: `A longer description that spans multiple lines and likely contains examples
|
||||
and usage of using your command. For example:
|
||||
|
||||
Cobra is a CLI library for Go that empowers applications.
|
||||
This application is a tool to generate the needed files
|
||||
to quickly create a Cobra application.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println("recipe called")
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(recipeCmd)
|
||||
recipeCmd.AddCommand(cmdRecipe.CreateCmd)
|
||||
|
||||
cmdRecipe.CreateCmd.Flags().StringP("layer", "l", ".", "Layer Directory to create recipe in")
|
||||
if err := viper.BindPFlag("yocto.layerdirectory", cmdRecipe.CreateCmd.Flags().Lookup("layer")); err != nil {
|
||||
utils.Logger.Error("Failed to Bind Flag", utils.Logger.Args("flag", "layer", "error", err))
|
||||
}
|
||||
}
|
25
cmd/recipe/create.go
Normal file
25
cmd/recipe/create.go
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
|
||||
*/
|
||||
package cmdRecipe
|
||||
|
||||
import (
|
||||
"github.com/Fishwaldo/go-yocto/recipe"
|
||||
"github.com/Fishwaldo/go-yocto/utils"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// createCmd represents the update command
|
||||
var CreateCmd = &cobra.Command{
|
||||
Use: "create",
|
||||
Short: "Create a new recipe",
|
||||
Long: `Create a new recipe`,
|
||||
Args: cobra.ExactArgs(2),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
utils.Logger.Info("Creating Recipe", utils.Logger.Args("backend", args[0], "name", args[1]))
|
||||
recipe.CreateRecipe(args[0], args[1])
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
}
|
|
@ -29,13 +29,7 @@ to quickly create a Cobra application.`,
|
|||
func init() {
|
||||
rootCmd.AddCommand(sourceCmd)
|
||||
sourceCmd.AddCommand(cmdSource.SearchCmd)
|
||||
// Here you will define your flags and configuration settings.
|
||||
|
||||
// Cobra supports Persistent Flags which will work for this command
|
||||
// and all subcommands, e.g.:
|
||||
// sourceCmd.PersistentFlags().String("foo", "", "A help for foo")
|
||||
|
||||
// Cobra supports local flags which will only run when this command
|
||||
// is called directly, e.g.:
|
||||
// sourceCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ var SearchCmd = &cobra.Command{
|
|||
if err == nil {
|
||||
td := pterm.TableData{{"Name", "Description", "Backend", "Url"}}
|
||||
for _, source := range sources {
|
||||
td = append(td, []string{source.Name, source.Description, source.Backend, source.Url})
|
||||
td = append(td, []string{source.Name, source.Description, source.BackendID, source.Url})
|
||||
}
|
||||
pterm.DefaultTable.WithHasHeader().WithData(
|
||||
td,
|
||||
|
|
1
go.mod
1
go.mod
|
@ -4,6 +4,7 @@ go 1.18
|
|||
|
||||
require (
|
||||
github.com/Masterminds/semver/v3 v3.2.1
|
||||
github.com/davecgh/go-spew v1.1.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
|
||||
|
|
204
recipe/recipe.go
Normal file
204
recipe/recipe.go
Normal file
|
@ -0,0 +1,204 @@
|
|||
package recipe
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/Fishwaldo/go-yocto/backends"
|
||||
"github.com/Fishwaldo/go-yocto/source"
|
||||
"github.com/Fishwaldo/go-yocto/utils"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/pterm/pterm"
|
||||
// "github.com/davecgh/go-spew/spew"
|
||||
)
|
||||
|
||||
var (
|
||||
funcs = template.FuncMap{"join": strings.Join}
|
||||
parserecipename = regexp.MustCompile(`^(.*)_(.*)\.bb$`)
|
||||
existingRecipes map[string]*source.RecipeSource = make(map[string]*source.RecipeSource)
|
||||
|
||||
)
|
||||
|
||||
|
||||
func init() {
|
||||
}
|
||||
|
||||
|
||||
func CreateRecipe(be string, name string) (error) {
|
||||
utils.Logger.Trace("Creating Recipe", utils.Logger.Args("backend", be, "name", name))
|
||||
b, ok := backends.Backends[be]
|
||||
if !ok {
|
||||
utils.Logger.Error("Backend not found", utils.Logger.Args("backend", be))
|
||||
return errors.New("backend not found")
|
||||
}
|
||||
if !b.Ready() {
|
||||
utils.Logger.Error("Backend not ready", utils.Logger.Args("backend", be))
|
||||
return errors.New("backend not ready")
|
||||
}
|
||||
|
||||
|
||||
layers := viper.GetStringSlice("yocto.layers")
|
||||
for _, layer := range layers {
|
||||
spinnerInfo, _ := pterm.DefaultSpinner.Start("Scanning Existing Recipe Files in " + layer)
|
||||
scanRecipes(layer, 0);
|
||||
spinnerInfo.Success()
|
||||
}
|
||||
s, err := b.GetRecipe(name)
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to get Recipe", utils.Logger.Args("backend", be, "name", name, "error", err))
|
||||
return err
|
||||
}
|
||||
|
||||
/* if it already exists, bail out */
|
||||
if _, ok := existingRecipes[s.Identifier]; ok {
|
||||
utils.Logger.Warn("Recipe already exists", utils.Logger.Args("recipe", s.Name))
|
||||
return errors.New("recipe already exists")
|
||||
}
|
||||
|
||||
/* check out dependancies */
|
||||
for _, dep := range s.Depends {
|
||||
if _, ok := existingRecipes[dep]; !ok {
|
||||
utils.Logger.Warn("Recipe Dependancy not found", utils.Logger.Args("recipe", s.Name, "dependancy", dep))
|
||||
return errors.New("recipe dependancy not found")
|
||||
}
|
||||
}
|
||||
|
||||
if err := writeRecipeFiles(s); err != nil {
|
||||
utils.Logger.Error("Failed to write Recipe Files", utils.Logger.Args("error", err))
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeRecipeFiles(s *source.RecipeSource) (error) {
|
||||
dir := path.Join(viper.GetString("yocto.layerdirectory"), "recipes-" + s.Section)
|
||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||
if err := os.Mkdir(dir, 0755); err != nil {
|
||||
utils.Logger.Error("Failed to create directory", utils.Logger.Args("error", err, "dir", dir))
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
dir = path.Join(dir, s.Identifier)
|
||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||
if err := os.Mkdir(dir, 0755); err != nil {
|
||||
utils.Logger.Error("Failed to create directory", utils.Logger.Args("error", err))
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
utils.Logger.Info("Publishing to " + dir)
|
||||
|
||||
maintmpl, err := ioutil.ReadFile("templates/recipe-main.tmpl")
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to read main template", utils.Logger.Args("error", err))
|
||||
} else {
|
||||
|
||||
/* create recipe_version.bb file */
|
||||
masterTmpl, err := template.New("master").Funcs(funcs).Parse(string(maintmpl))
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to parse template", utils.Logger.Args("error", err))
|
||||
return err
|
||||
}
|
||||
|
||||
fname := path.Join(dir, fmt.Sprintf("%s_%s.bb", s.Identifier, s.Version))
|
||||
|
||||
if f, err := os.Create(fname); err != nil {
|
||||
utils.Logger.Error("Failed to create file", utils.Logger.Args("error", err))
|
||||
return err
|
||||
} else {
|
||||
if err := masterTmpl.Execute(f, s); err != nil {
|
||||
utils.Logger.Error("Failed to execute template", utils.Logger.Args("error", err))
|
||||
return err
|
||||
} else {
|
||||
utils.Logger.Info("Created " + fname)
|
||||
}
|
||||
f.Close();
|
||||
}
|
||||
|
||||
/* create recipe.inc file */
|
||||
maintmpl, err := ioutil.ReadFile("templates/recipe-include.tmpl")
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to read main template", utils.Logger.Args("error", err))
|
||||
} else {
|
||||
overlayTmpl, err := template.Must(masterTmpl.Clone()).Parse(string(maintmpl))
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to parse template", utils.Logger.Args("error", err))
|
||||
return err
|
||||
}
|
||||
fname = path.Join(dir, fmt.Sprintf("%s.inc", s.Identifier))
|
||||
|
||||
if f, err := os.Create(fname); err != nil {
|
||||
utils.Logger.Error("Failed to create file", utils.Logger.Args("error", err))
|
||||
return err
|
||||
} else {
|
||||
if err := overlayTmpl.Execute(f, s); err != nil {
|
||||
utils.Logger.Error("Failed to execute template", utils.Logger.Args("error", err))
|
||||
return err
|
||||
} else {
|
||||
utils.Logger.Info("Created " + fname)
|
||||
}
|
||||
f.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
func scanRecipes(dir string, level int) (error) {
|
||||
|
||||
fsrecipessections, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
utils.Logger.Error("Failed to read directory", utils.Logger.Args("error", err))
|
||||
return err
|
||||
}
|
||||
|
||||
for _, file := range fsrecipessections {
|
||||
if file.IsDir() {
|
||||
if (level == 0) {
|
||||
ok, _ := filepath.Match("recipes-*", file.Name())
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if err := scanRecipes(path.Join(dir, file.Name()), level + 1); err != nil {
|
||||
utils.Logger.Error("Failed to scan directory", utils.Logger.Args("error", err))
|
||||
continue
|
||||
}
|
||||
} else if file.Type().IsRegular() {
|
||||
if strings.EqualFold(path.Ext(file.Name()), ".bb") {
|
||||
if err := parseRecipeFile(file, path.Join(dir, file.Name())); err != nil {
|
||||
utils.Logger.Error("Failed to parse recipe file", utils.Logger.Args("error", err, "file", path.Join(dir, file.Name())))
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseRecipeFile(file fs.DirEntry, dir string) (error) {
|
||||
if parserecipename.Match([]byte(file.Name())) {
|
||||
match := parserecipename.FindSubmatch([]byte(file.Name()))
|
||||
s := source.RecipeSource{
|
||||
Identifier: string(match[1]),
|
||||
Version: string(match[2]),
|
||||
Section: strings.TrimPrefix(file.Name(), "-"),
|
||||
BackendID: "existing",
|
||||
Location: path.Join(dir, file.Name()),
|
||||
}
|
||||
if _, ok := existingRecipes[s.Identifier]; !ok {
|
||||
existingRecipes[s.Identifier] = &s
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -2,10 +2,18 @@ package source
|
|||
|
||||
type RecipeSource struct {
|
||||
Name string
|
||||
Identifier string
|
||||
Description string
|
||||
Summary string
|
||||
Version string
|
||||
Url string
|
||||
Backend string
|
||||
Section string
|
||||
BackendID string
|
||||
MetaData map[string]map[string]interface{}
|
||||
Inherits []string
|
||||
Depends []string
|
||||
SrcURI string
|
||||
SrcSHA256 string
|
||||
Licenses []string
|
||||
Location string
|
||||
}
|
||||
|
||||
|
|
17
templates/recipe-include.tmpl
Normal file
17
templates/recipe-include.tmpl
Normal file
|
@ -0,0 +1,17 @@
|
|||
# SPDX-FileCopyrightText: 2023 Justin Hammond <justin@dynam.ac>
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
DESCRIPTION = "{{.Description}}"
|
||||
SUMMARY = "{{.Summary}}"
|
||||
HOMEPAGE = "{{.Url}}"
|
||||
LICENSE = "{{block "Licenses" .Licenses}} {{join . " & "}}{{end}}"
|
||||
|
||||
{{block "Inherits" .Inherits}}{{"\n"}}{{range .}}{{println "inherit" .}}{{end}}{{end}}
|
||||
|
||||
DEPENDS = " \
|
||||
{{block "Depends" .Depends }}{{range .}}{{print " " . }} \{{println}}{{end}}{{end}}"
|
||||
|
||||
|
||||
KF5_REUSE_LICENSECHECK_ENABLED="1"
|
||||
|
7
templates/recipe-main.tmpl
Normal file
7
templates/recipe-main.tmpl
Normal file
|
@ -0,0 +1,7 @@
|
|||
# SPDX-FileCopyrightText: none
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
require ${PN}.inc
|
||||
SRC_URI = "{{.SrcURI}}"
|
||||
SRC_URI[sha256sum] = "{{.SrcSHA256}}"
|
||||
|
Loading…
Add table
Reference in a new issue