summaryrefslogtreecommitdiffstats
path: root/modules/packages/chef/metadata.go
diff options
context:
space:
mode:
Diffstat (limited to 'modules/packages/chef/metadata.go')
-rw-r--r--modules/packages/chef/metadata.go134
1 files changed, 134 insertions, 0 deletions
diff --git a/modules/packages/chef/metadata.go b/modules/packages/chef/metadata.go
new file mode 100644
index 0000000..a1c9187
--- /dev/null
+++ b/modules/packages/chef/metadata.go
@@ -0,0 +1,134 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package chef
+
+import (
+ "archive/tar"
+ "compress/gzip"
+ "io"
+ "regexp"
+ "strings"
+
+ "code.gitea.io/gitea/modules/json"
+ "code.gitea.io/gitea/modules/util"
+ "code.gitea.io/gitea/modules/validation"
+)
+
+const (
+ KeyBits = 4096
+ SettingPublicPem = "chef.public_pem"
+)
+
+var (
+ ErrMissingMetadataFile = util.NewInvalidArgumentErrorf("metadata.json file is missing")
+ ErrInvalidName = util.NewInvalidArgumentErrorf("package name is invalid")
+ ErrInvalidVersion = util.NewInvalidArgumentErrorf("package version is invalid")
+
+ namePattern = regexp.MustCompile(`\A\S+\z`)
+ versionPattern = regexp.MustCompile(`\A\d+\.\d+(?:\.\d+)?\z`)
+)
+
+// Package represents a Chef package
+type Package struct {
+ Name string
+ Version string
+ Metadata *Metadata
+}
+
+// Metadata represents the metadata of a Chef package
+type Metadata struct {
+ Description string `json:"description,omitempty"`
+ LongDescription string `json:"long_description,omitempty"`
+ Author string `json:"author,omitempty"`
+ License string `json:"license,omitempty"`
+ RepositoryURL string `json:"repository_url,omitempty"`
+ Dependencies map[string]string `json:"dependencies,omitempty"`
+}
+
+type chefMetadata struct {
+ Name string `json:"name"`
+ Description string `json:"description"`
+ LongDescription string `json:"long_description"`
+ Maintainer string `json:"maintainer"`
+ MaintainerEmail string `json:"maintainer_email"`
+ License string `json:"license"`
+ Platforms map[string]string `json:"platforms"`
+ Dependencies map[string]string `json:"dependencies"`
+ Providing map[string]string `json:"providing"`
+ Recipes map[string]string `json:"recipes"`
+ Version string `json:"version"`
+ SourceURL string `json:"source_url"`
+ IssuesURL string `json:"issues_url"`
+ Privacy bool `json:"privacy"`
+ ChefVersions [][]string `json:"chef_versions"`
+ Gems [][]string `json:"gems"`
+ EagerLoadLibraries bool `json:"eager_load_libraries"`
+}
+
+// ParsePackage parses the Chef package file
+func ParsePackage(r io.Reader) (*Package, error) {
+ gzr, err := gzip.NewReader(r)
+ if err != nil {
+ return nil, err
+ }
+ defer gzr.Close()
+
+ tr := tar.NewReader(gzr)
+ for {
+ hd, err := tr.Next()
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ if hd.Typeflag != tar.TypeReg {
+ continue
+ }
+
+ if strings.Count(hd.Name, "/") != 1 {
+ continue
+ }
+
+ if hd.FileInfo().Name() == "metadata.json" {
+ return ParseChefMetadata(tr)
+ }
+ }
+
+ return nil, ErrMissingMetadataFile
+}
+
+// ParseChefMetadata parses a metadata.json file to retrieve the metadata of a Chef package
+func ParseChefMetadata(r io.Reader) (*Package, error) {
+ var cm chefMetadata
+ if err := json.NewDecoder(r).Decode(&cm); err != nil {
+ return nil, err
+ }
+
+ if !namePattern.MatchString(cm.Name) {
+ return nil, ErrInvalidName
+ }
+
+ if !versionPattern.MatchString(cm.Version) {
+ return nil, ErrInvalidVersion
+ }
+
+ if !validation.IsValidURL(cm.SourceURL) {
+ cm.SourceURL = ""
+ }
+
+ return &Package{
+ Name: cm.Name,
+ Version: cm.Version,
+ Metadata: &Metadata{
+ Description: cm.Description,
+ LongDescription: cm.LongDescription,
+ Author: cm.Maintainer,
+ License: cm.License,
+ RepositoryURL: cm.SourceURL,
+ Dependencies: cm.Dependencies,
+ },
+ }, nil
+}