2019-11-22 20:01:38 +00:00
|
|
|
// Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org>
|
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation; either version 2 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License along
|
|
|
|
// with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
package installer
|
|
|
|
|
|
|
|
import (
|
2020-01-03 23:31:11 +00:00
|
|
|
"fmt"
|
2019-11-22 20:01:38 +00:00
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
2020-01-28 16:46:32 +00:00
|
|
|
"path"
|
2019-11-22 20:01:38 +00:00
|
|
|
"path/filepath"
|
2021-02-28 17:42:54 +00:00
|
|
|
"regexp"
|
2019-11-22 20:01:38 +00:00
|
|
|
"sort"
|
2020-01-03 19:09:29 +00:00
|
|
|
"strconv"
|
2019-11-22 20:01:38 +00:00
|
|
|
"strings"
|
2020-01-03 19:09:29 +00:00
|
|
|
"time"
|
2019-11-22 20:01:38 +00:00
|
|
|
|
2020-11-13 17:25:44 +00:00
|
|
|
"github.com/mudler/luet/pkg/bus"
|
2019-11-22 20:01:38 +00:00
|
|
|
"github.com/mudler/luet/pkg/compiler"
|
2019-12-31 00:21:06 +00:00
|
|
|
"github.com/mudler/luet/pkg/config"
|
2019-11-22 20:01:38 +00:00
|
|
|
"github.com/mudler/luet/pkg/helpers"
|
2020-01-12 22:31:43 +00:00
|
|
|
"github.com/mudler/luet/pkg/installer/client"
|
2020-01-02 17:31:25 +00:00
|
|
|
. "github.com/mudler/luet/pkg/logger"
|
2019-11-22 20:01:38 +00:00
|
|
|
pkg "github.com/mudler/luet/pkg/package"
|
|
|
|
tree "github.com/mudler/luet/pkg/tree"
|
2020-01-12 22:31:43 +00:00
|
|
|
|
|
|
|
"github.com/ghodss/yaml"
|
2019-11-22 20:01:38 +00:00
|
|
|
"github.com/pkg/errors"
|
|
|
|
)
|
|
|
|
|
2020-01-03 23:31:11 +00:00
|
|
|
const (
|
2020-03-23 22:56:29 +00:00
|
|
|
REPOSITORY_METAFILE = "repository.meta.yaml"
|
2020-01-03 23:31:11 +00:00
|
|
|
REPOSITORY_SPECFILE = "repository.yaml"
|
2020-01-04 23:40:28 +00:00
|
|
|
TREE_TARBALL = "tree.tar"
|
2020-03-23 22:56:29 +00:00
|
|
|
|
|
|
|
REPOFILE_TREE_KEY = "tree"
|
|
|
|
REPOFILE_META_KEY = "meta"
|
2021-01-18 16:58:32 +00:00
|
|
|
|
|
|
|
DiskRepositoryType = "disk"
|
|
|
|
HttpRepositoryType = "http"
|
|
|
|
DockerRepositoryType = "docker"
|
2020-01-03 23:31:11 +00:00
|
|
|
)
|
|
|
|
|
2020-03-23 22:56:29 +00:00
|
|
|
type LuetRepositoryFile struct {
|
2020-03-24 17:30:52 +00:00
|
|
|
FileName string `json:"filename"`
|
2020-03-23 22:56:29 +00:00
|
|
|
CompressionType compiler.CompressionImplementation `json:"compressiontype,omitempty"`
|
|
|
|
Checksums compiler.Checksums `json:"checksums,omitempty"`
|
|
|
|
}
|
|
|
|
|
2019-12-31 00:21:06 +00:00
|
|
|
type LuetSystemRepository struct {
|
|
|
|
*config.LuetRepository
|
|
|
|
|
2020-03-23 22:56:29 +00:00
|
|
|
Index compiler.ArtifactIndex `json:"index"`
|
|
|
|
Tree tree.Builder `json:"-"`
|
|
|
|
RepositoryFiles map[string]LuetRepositoryFile `json:"repo_files"`
|
2021-01-18 16:58:32 +00:00
|
|
|
Backend compiler.CompilerBackend `json:"-"`
|
2021-01-19 11:00:51 +00:00
|
|
|
PushImages bool `json:"-"`
|
|
|
|
ForcePush bool `json:"-"`
|
2019-11-22 20:01:38 +00:00
|
|
|
}
|
|
|
|
|
2019-12-31 00:21:06 +00:00
|
|
|
type LuetSystemRepositorySerialized struct {
|
2020-03-23 22:56:29 +00:00
|
|
|
Name string `json:"name"`
|
|
|
|
Description string `json:"description,omitempty"`
|
|
|
|
Urls []string `json:"urls"`
|
|
|
|
Priority int `json:"priority"`
|
|
|
|
Type string `json:"type"`
|
|
|
|
Revision int `json:"revision,omitempty"`
|
|
|
|
LastUpdate string `json:"last_update,omitempty"`
|
|
|
|
TreePath string `json:"treepath"`
|
|
|
|
MetaPath string `json:"metapath"`
|
|
|
|
RepositoryFiles map[string]LuetRepositoryFile `json:"repo_files"`
|
2021-03-11 16:04:26 +00:00
|
|
|
Verify bool `json:"verify"`
|
2020-03-23 22:56:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type LuetSystemRepositoryMetadata struct {
|
|
|
|
Index []*compiler.PackageArtifact `json:"index,omitempty"`
|
2019-11-23 14:42:05 +00:00
|
|
|
}
|
|
|
|
|
2021-02-28 17:42:54 +00:00
|
|
|
type LuetSearchModeType int
|
2020-03-20 22:47:35 +00:00
|
|
|
|
|
|
|
const (
|
2021-02-28 17:42:54 +00:00
|
|
|
SLabel = iota
|
|
|
|
SRegexPkg = iota
|
|
|
|
SRegexLabel = iota
|
|
|
|
FileSearch = iota
|
2020-03-20 22:47:35 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type LuetSearchOpts struct {
|
2021-02-28 17:42:54 +00:00
|
|
|
Mode LuetSearchModeType
|
2020-03-20 22:47:35 +00:00
|
|
|
}
|
|
|
|
|
2020-03-23 22:56:29 +00:00
|
|
|
func NewLuetSystemRepositoryMetadata(file string, removeFile bool) (*LuetSystemRepositoryMetadata, error) {
|
|
|
|
ans := &LuetSystemRepositoryMetadata{}
|
|
|
|
err := ans.ReadFile(file, removeFile)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return ans, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *LuetSystemRepositoryMetadata) WriteFile(path string) error {
|
|
|
|
data, err := yaml.Marshal(m)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
err = ioutil.WriteFile(path, data, os.ModePerm)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *LuetSystemRepositoryMetadata) ReadFile(file string, removeFile bool) error {
|
|
|
|
if file == "" {
|
|
|
|
return errors.New("Invalid path for repository metadata")
|
|
|
|
}
|
|
|
|
|
|
|
|
dat, err := ioutil.ReadFile(file)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if removeFile {
|
|
|
|
defer os.Remove(file)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = yaml.Unmarshal(dat, m)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-05-01 09:07:14 +00:00
|
|
|
func (m *LuetSystemRepositoryMetadata) ToArtifactIndex() (ans compiler.ArtifactIndex) {
|
2020-03-23 22:56:29 +00:00
|
|
|
for _, a := range m.Index {
|
|
|
|
ans = append(ans, a)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewDefaultTreeRepositoryFile() LuetRepositoryFile {
|
|
|
|
return LuetRepositoryFile{
|
2020-03-24 17:30:52 +00:00
|
|
|
FileName: TREE_TARBALL,
|
2020-03-23 22:56:29 +00:00
|
|
|
CompressionType: compiler.GZip,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewDefaultMetaRepositoryFile() LuetRepositoryFile {
|
|
|
|
return LuetRepositoryFile{
|
2020-03-24 17:30:52 +00:00
|
|
|
FileName: REPOSITORY_METAFILE + ".tar",
|
2020-03-23 22:56:29 +00:00
|
|
|
CompressionType: compiler.None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-22 10:59:56 +00:00
|
|
|
// SetFileName sets the name of the repository file.
|
|
|
|
// Each repository can ship arbitrary file that will be downloaded by the client
|
|
|
|
// in case of need, this set the filename that the client will pull
|
2020-03-24 17:30:52 +00:00
|
|
|
func (f *LuetRepositoryFile) SetFileName(n string) {
|
|
|
|
f.FileName = n
|
2020-03-23 22:56:29 +00:00
|
|
|
}
|
2020-04-18 15:33:34 +00:00
|
|
|
|
2021-01-22 10:59:56 +00:00
|
|
|
// GetFileName returns the name of the repository file.
|
|
|
|
// Each repository can ship arbitrary file that will be downloaded by the client
|
|
|
|
// in case of need, this gets the filename that the client will pull
|
2020-03-24 17:30:52 +00:00
|
|
|
func (f *LuetRepositoryFile) GetFileName() string {
|
|
|
|
return f.FileName
|
2020-03-23 22:56:29 +00:00
|
|
|
}
|
2021-01-22 10:59:56 +00:00
|
|
|
|
|
|
|
// SetCompressionType sets the compression type of the repository file.
|
|
|
|
// Each repository can ship arbitrary file that will be downloaded by the client
|
|
|
|
// in case of need, this sets the compression type that the client will use to uncompress the artifact
|
2020-03-23 22:56:29 +00:00
|
|
|
func (f *LuetRepositoryFile) SetCompressionType(c compiler.CompressionImplementation) {
|
|
|
|
f.CompressionType = c
|
|
|
|
}
|
2021-01-22 10:59:56 +00:00
|
|
|
|
|
|
|
// GetCompressionType gets the compression type of the repository file.
|
|
|
|
// Each repository can ship arbitrary file that will be downloaded by the client
|
|
|
|
// in case of need, this gets the compression type that the client will use to uncompress the artifact
|
2020-03-23 22:56:29 +00:00
|
|
|
func (f *LuetRepositoryFile) GetCompressionType() compiler.CompressionImplementation {
|
|
|
|
return f.CompressionType
|
|
|
|
}
|
2021-01-22 10:59:56 +00:00
|
|
|
|
|
|
|
// SetChecksums sets the checksum of the repository file.
|
|
|
|
// Each repository can ship arbitrary file that will be downloaded by the client
|
|
|
|
// in case of need, this sets the checksums that the client will use to verify the artifact
|
2020-03-23 22:56:29 +00:00
|
|
|
func (f *LuetRepositoryFile) SetChecksums(c compiler.Checksums) {
|
|
|
|
f.Checksums = c
|
|
|
|
}
|
2021-01-22 10:59:56 +00:00
|
|
|
|
|
|
|
// GetChecksums gets the checksum of the repository file.
|
|
|
|
// Each repository can ship arbitrary file that will be downloaded by the client
|
|
|
|
// in case of need, this gets the checksums that the client will use to verify the artifact
|
2020-03-23 22:56:29 +00:00
|
|
|
func (f *LuetRepositoryFile) GetChecksums() compiler.Checksums {
|
|
|
|
return f.Checksums
|
|
|
|
}
|
|
|
|
|
2021-01-22 10:59:56 +00:00
|
|
|
// GenerateRepository generates a new repository from the given argument.
|
|
|
|
// If the repository is of the docker type, it will also push the package images.
|
|
|
|
// In case the repository is local, it will build the package Index
|
2021-01-18 16:58:32 +00:00
|
|
|
func GenerateRepository(name, descr, t string, urls []string,
|
|
|
|
priority int, src string, treesDir []string, db pkg.PackageDatabase,
|
2021-01-19 11:00:51 +00:00
|
|
|
b compiler.CompilerBackend, imagePrefix string, pushImages, force bool) (Repository, error) {
|
2019-11-22 20:01:38 +00:00
|
|
|
|
2020-05-01 08:52:40 +00:00
|
|
|
tr := tree.NewInstallerRecipe(db)
|
2020-05-10 18:18:10 +00:00
|
|
|
|
|
|
|
for _, treeDir := range treesDir {
|
|
|
|
err := tr.Load(treeDir)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2019-11-22 20:01:38 +00:00
|
|
|
}
|
2020-05-01 08:52:40 +00:00
|
|
|
|
2021-01-19 14:44:46 +00:00
|
|
|
// if !strings.HasSuffix(imagePrefix, "/") {
|
|
|
|
// imagePrefix = imagePrefix + "/"
|
|
|
|
// }
|
|
|
|
|
2021-01-18 16:58:32 +00:00
|
|
|
var art []compiler.Artifact
|
|
|
|
var err error
|
|
|
|
switch t {
|
|
|
|
case DiskRepositoryType, HttpRepositoryType:
|
|
|
|
art, err = buildPackageIndex(src, tr.GetDatabase())
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
case DockerRepositoryType:
|
2021-01-19 11:00:51 +00:00
|
|
|
art, err = generatePackageImages(b, imagePrefix, src, tr.GetDatabase(), pushImages, force)
|
2021-01-18 16:58:32 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2019-11-22 22:24:22 +00:00
|
|
|
}
|
2019-11-22 20:01:38 +00:00
|
|
|
|
2021-01-18 16:58:32 +00:00
|
|
|
repo := NewLuetSystemRepository(
|
2020-01-12 22:31:43 +00:00
|
|
|
config.NewLuetRepository(name, t, descr, urls, priority, true, false),
|
2021-01-19 11:00:51 +00:00
|
|
|
art, tr, pushImages, force)
|
2021-01-18 16:58:32 +00:00
|
|
|
repo.SetBackend(b)
|
|
|
|
return repo, nil
|
2019-11-22 20:01:38 +00:00
|
|
|
}
|
|
|
|
|
2020-01-02 17:31:25 +00:00
|
|
|
func NewSystemRepository(repo config.LuetRepository) Repository {
|
2019-12-31 00:21:06 +00:00
|
|
|
return &LuetSystemRepository{
|
2020-03-23 22:56:29 +00:00
|
|
|
LuetRepository: &repo,
|
|
|
|
RepositoryFiles: map[string]LuetRepositoryFile{},
|
2019-12-31 00:21:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-19 11:00:51 +00:00
|
|
|
func NewLuetSystemRepository(repo *config.LuetRepository, art []compiler.Artifact, builder tree.Builder, pushImages, force bool) Repository {
|
2019-12-31 00:21:06 +00:00
|
|
|
return &LuetSystemRepository{
|
2020-03-23 22:56:29 +00:00
|
|
|
LuetRepository: repo,
|
|
|
|
Index: art,
|
|
|
|
Tree: builder,
|
|
|
|
RepositoryFiles: map[string]LuetRepositoryFile{},
|
2021-01-19 11:00:51 +00:00
|
|
|
PushImages: pushImages,
|
|
|
|
ForcePush: force,
|
2019-12-31 00:21:06 +00:00
|
|
|
}
|
2019-11-22 20:01:38 +00:00
|
|
|
}
|
|
|
|
|
2019-12-31 00:21:06 +00:00
|
|
|
func NewLuetSystemRepositoryFromYaml(data []byte, db pkg.PackageDatabase) (Repository, error) {
|
|
|
|
var p *LuetSystemRepositorySerialized
|
2019-11-22 20:01:38 +00:00
|
|
|
err := yaml.Unmarshal(data, &p)
|
|
|
|
if err != nil {
|
2019-11-23 14:42:05 +00:00
|
|
|
return nil, err
|
2019-11-22 20:01:38 +00:00
|
|
|
}
|
2021-03-11 16:04:26 +00:00
|
|
|
repo := config.NewLuetRepository(
|
|
|
|
p.Name,
|
|
|
|
p.Type,
|
|
|
|
p.Description,
|
|
|
|
p.Urls,
|
|
|
|
p.Priority,
|
|
|
|
true,
|
|
|
|
false,
|
|
|
|
)
|
|
|
|
repo.Verify = p.Verify
|
2020-03-23 22:56:29 +00:00
|
|
|
|
2019-12-31 00:21:06 +00:00
|
|
|
r := &LuetSystemRepository{
|
2021-03-11 16:04:26 +00:00
|
|
|
LuetRepository: repo,
|
2020-03-24 11:52:24 +00:00
|
|
|
RepositoryFiles: p.RepositoryFiles,
|
2019-12-31 00:21:06 +00:00
|
|
|
}
|
2021-03-11 16:04:26 +00:00
|
|
|
|
2020-01-03 19:09:29 +00:00
|
|
|
if p.Revision > 0 {
|
|
|
|
r.Revision = p.Revision
|
|
|
|
}
|
|
|
|
if p.LastUpdate != "" {
|
|
|
|
r.LastUpdate = p.LastUpdate
|
|
|
|
}
|
2019-11-23 14:42:05 +00:00
|
|
|
r.Tree = tree.NewInstallerRecipe(db)
|
|
|
|
|
|
|
|
return r, err
|
2019-11-22 20:01:38 +00:00
|
|
|
}
|
|
|
|
|
2021-01-19 11:00:51 +00:00
|
|
|
func pushImage(b compiler.CompilerBackend, image string, force bool) error {
|
|
|
|
if b.ImageAvailable(image) && !force {
|
|
|
|
Debug("Image", image, "already present, skipping")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return b.Push(compiler.CompilerBackendOptions{ImageName: image})
|
|
|
|
}
|
|
|
|
|
|
|
|
func generatePackageImages(b compiler.CompilerBackend, imagePrefix, path string, db pkg.PackageDatabase, imagePush, force bool) ([]compiler.Artifact, error) {
|
2021-01-22 09:25:58 +00:00
|
|
|
Info("Generating docker images for packages in", imagePrefix)
|
2021-01-18 16:58:32 +00:00
|
|
|
var art []compiler.Artifact
|
|
|
|
var ff = func(currentpath string, info os.FileInfo, err error) error {
|
|
|
|
|
|
|
|
if !strings.HasSuffix(info.Name(), ".metadata.yaml") {
|
|
|
|
return nil // Skip with no errors
|
|
|
|
}
|
|
|
|
|
|
|
|
dat, err := ioutil.ReadFile(currentpath)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "Error reading file "+currentpath)
|
|
|
|
}
|
|
|
|
|
|
|
|
artifact, err := compiler.NewPackageArtifactFromYaml(dat)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "Error reading yaml "+currentpath)
|
|
|
|
}
|
|
|
|
|
|
|
|
// We want to include packages that are ONLY referenced in the tree.
|
|
|
|
// the ones which aren't should be deleted. (TODO: by another cli command?)
|
|
|
|
if _, notfound := db.FindPackage(artifact.GetCompileSpec().GetPackage()); notfound != nil {
|
|
|
|
Debug(fmt.Sprintf("Package %s not found in tree. Ignoring it.",
|
|
|
|
artifact.GetCompileSpec().GetPackage().HumanReadableString()))
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-03-07 10:01:08 +00:00
|
|
|
packageImage := fmt.Sprintf("%s:%s", imagePrefix, artifact.GetCompileSpec().GetPackage().ImageID())
|
2021-01-22 09:25:58 +00:00
|
|
|
|
|
|
|
if imagePush && b.ImageAvailable(packageImage) && !force {
|
|
|
|
Info("Image", packageImage, "already present, skipping. use --force-push to override")
|
|
|
|
} else {
|
|
|
|
Info("Generating final image", packageImage,
|
|
|
|
"for package ", artifact.GetCompileSpec().GetPackage().HumanReadableString())
|
|
|
|
if opts, err := artifact.GenerateFinalImage(packageImage, b, true); err != nil {
|
|
|
|
return errors.Wrap(err, "Failed generating metadata tree"+opts.ImageName)
|
|
|
|
}
|
2021-01-18 16:58:32 +00:00
|
|
|
}
|
2021-01-19 11:00:51 +00:00
|
|
|
if imagePush {
|
|
|
|
if err := pushImage(b, packageImage, force); err != nil {
|
|
|
|
return errors.Wrapf(err, "Failed while pushing image: '%s'", packageImage)
|
|
|
|
}
|
|
|
|
}
|
2021-01-18 16:58:32 +00:00
|
|
|
|
|
|
|
art = append(art, artifact)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
err := filepath.Walk(path, ff)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
|
|
|
|
}
|
|
|
|
return art, nil
|
|
|
|
}
|
|
|
|
|
2020-05-01 08:52:40 +00:00
|
|
|
func buildPackageIndex(path string, db pkg.PackageDatabase) ([]compiler.Artifact, error) {
|
2019-11-22 20:01:38 +00:00
|
|
|
|
|
|
|
var art []compiler.Artifact
|
|
|
|
var ff = func(currentpath string, info os.FileInfo, err error) error {
|
|
|
|
|
|
|
|
if !strings.HasSuffix(info.Name(), ".metadata.yaml") {
|
|
|
|
return nil // Skip with no errors
|
|
|
|
}
|
|
|
|
|
|
|
|
dat, err := ioutil.ReadFile(currentpath)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "Error reading file "+currentpath)
|
|
|
|
}
|
|
|
|
|
|
|
|
artifact, err := compiler.NewPackageArtifactFromYaml(dat)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "Error reading yaml "+currentpath)
|
|
|
|
}
|
2020-05-01 08:52:40 +00:00
|
|
|
|
2020-05-01 09:07:14 +00:00
|
|
|
// We want to include packages that are ONLY referenced in the tree.
|
|
|
|
// the ones which aren't should be deleted. (TODO: by another cli command?)
|
2020-05-01 08:52:40 +00:00
|
|
|
if _, notfound := db.FindPackage(artifact.GetCompileSpec().GetPackage()); notfound != nil {
|
2021-01-18 16:58:32 +00:00
|
|
|
Debug(fmt.Sprintf("Package %s not found in tree. Ignoring it.",
|
2020-10-12 06:42:19 +00:00
|
|
|
artifact.GetCompileSpec().GetPackage().HumanReadableString()))
|
2020-05-01 08:52:40 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-11-22 20:01:38 +00:00
|
|
|
art = append(art, artifact)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
err := filepath.Walk(path, ff)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
|
|
|
|
}
|
|
|
|
return art, nil
|
|
|
|
}
|
|
|
|
|
2020-04-18 15:33:34 +00:00
|
|
|
func (r *LuetSystemRepository) SetPriority(n int) {
|
|
|
|
r.LuetRepository.Priority = n
|
|
|
|
}
|
|
|
|
|
2021-02-28 17:42:54 +00:00
|
|
|
// FileSearch search a pattern among the artifacts in a repository
|
|
|
|
func (r *LuetSystemRepository) FileSearch(pattern string) (pkg.Packages, error) {
|
|
|
|
var matches pkg.Packages
|
|
|
|
reg, err := regexp.Compile(pattern)
|
|
|
|
if err != nil {
|
|
|
|
return matches, err
|
|
|
|
}
|
|
|
|
ARTIFACT:
|
|
|
|
for _, a := range r.GetIndex() {
|
|
|
|
for _, f := range a.GetFiles() {
|
|
|
|
if reg.MatchString(f) {
|
|
|
|
matches = append(matches, a.GetCompileSpec().GetPackage())
|
|
|
|
continue ARTIFACT
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return matches, nil
|
|
|
|
}
|
|
|
|
|
2019-12-31 00:21:06 +00:00
|
|
|
func (r *LuetSystemRepository) GetName() string {
|
|
|
|
return r.LuetRepository.Name
|
2019-11-22 20:01:38 +00:00
|
|
|
}
|
2019-12-31 00:21:06 +00:00
|
|
|
func (r *LuetSystemRepository) GetDescription() string {
|
|
|
|
return r.LuetRepository.Description
|
2019-11-22 20:01:38 +00:00
|
|
|
}
|
2020-01-28 16:46:32 +00:00
|
|
|
|
2020-02-02 23:58:55 +00:00
|
|
|
func (r *LuetSystemRepository) GetAuthentication() map[string]string {
|
|
|
|
return r.LuetRepository.Authentication
|
|
|
|
}
|
|
|
|
|
2019-12-31 00:21:06 +00:00
|
|
|
func (r *LuetSystemRepository) GetType() string {
|
|
|
|
return r.LuetRepository.Type
|
2019-11-22 20:01:38 +00:00
|
|
|
}
|
2019-12-31 00:21:06 +00:00
|
|
|
func (r *LuetSystemRepository) SetType(p string) {
|
|
|
|
r.LuetRepository.Type = p
|
2019-11-23 14:42:05 +00:00
|
|
|
}
|
2020-05-24 10:16:02 +00:00
|
|
|
|
2021-01-18 16:58:32 +00:00
|
|
|
func (r *LuetSystemRepository) GetBackend() compiler.CompilerBackend {
|
|
|
|
return r.Backend
|
|
|
|
}
|
|
|
|
func (r *LuetSystemRepository) SetBackend(b compiler.CompilerBackend) {
|
|
|
|
r.Backend = b
|
|
|
|
}
|
|
|
|
|
2020-05-24 10:16:02 +00:00
|
|
|
func (r *LuetSystemRepository) SetName(p string) {
|
|
|
|
r.LuetRepository.Name = p
|
|
|
|
}
|
|
|
|
|
2019-12-31 00:21:06 +00:00
|
|
|
func (r *LuetSystemRepository) AddUrl(p string) {
|
|
|
|
r.LuetRepository.Urls = append(r.LuetRepository.Urls, p)
|
2019-11-22 20:01:38 +00:00
|
|
|
}
|
2019-12-31 00:21:06 +00:00
|
|
|
func (r *LuetSystemRepository) GetUrls() []string {
|
|
|
|
return r.LuetRepository.Urls
|
2019-11-22 20:01:38 +00:00
|
|
|
}
|
2019-12-31 00:21:06 +00:00
|
|
|
func (r *LuetSystemRepository) SetUrls(urls []string) {
|
|
|
|
r.LuetRepository.Urls = urls
|
2019-11-25 19:02:59 +00:00
|
|
|
}
|
2019-12-31 00:21:06 +00:00
|
|
|
func (r *LuetSystemRepository) GetPriority() int {
|
|
|
|
return r.LuetRepository.Priority
|
2019-12-30 21:51:51 +00:00
|
|
|
}
|
2019-12-31 00:21:06 +00:00
|
|
|
func (r *LuetSystemRepository) GetTreePath() string {
|
|
|
|
return r.TreePath
|
|
|
|
}
|
|
|
|
func (r *LuetSystemRepository) SetTreePath(p string) {
|
|
|
|
r.TreePath = p
|
2019-11-22 20:01:38 +00:00
|
|
|
}
|
2020-03-23 22:56:29 +00:00
|
|
|
func (r *LuetSystemRepository) GetMetaPath() string {
|
|
|
|
return r.MetaPath
|
|
|
|
}
|
|
|
|
func (r *LuetSystemRepository) SetMetaPath(p string) {
|
|
|
|
r.MetaPath = p
|
|
|
|
}
|
2019-12-31 00:21:06 +00:00
|
|
|
func (r *LuetSystemRepository) SetTree(b tree.Builder) {
|
|
|
|
r.Tree = b
|
2019-11-22 20:01:38 +00:00
|
|
|
}
|
2019-12-31 00:21:06 +00:00
|
|
|
func (r *LuetSystemRepository) GetIndex() compiler.ArtifactIndex {
|
2019-11-22 20:01:38 +00:00
|
|
|
return r.Index
|
|
|
|
}
|
2020-03-23 22:56:29 +00:00
|
|
|
func (r *LuetSystemRepository) SetIndex(i compiler.ArtifactIndex) {
|
|
|
|
r.Index = i
|
|
|
|
}
|
2019-12-31 00:21:06 +00:00
|
|
|
func (r *LuetSystemRepository) GetTree() tree.Builder {
|
2019-11-22 20:01:38 +00:00
|
|
|
return r.Tree
|
|
|
|
}
|
2020-01-03 23:31:11 +00:00
|
|
|
func (r *LuetSystemRepository) GetRevision() int {
|
2020-02-02 23:58:55 +00:00
|
|
|
return r.LuetRepository.Revision
|
2020-01-03 23:31:11 +00:00
|
|
|
}
|
|
|
|
func (r *LuetSystemRepository) GetLastUpdate() string {
|
2020-02-02 23:58:55 +00:00
|
|
|
return r.LuetRepository.LastUpdate
|
2020-01-03 23:31:11 +00:00
|
|
|
}
|
|
|
|
func (r *LuetSystemRepository) SetLastUpdate(u string) {
|
2020-02-02 23:58:55 +00:00
|
|
|
r.LuetRepository.LastUpdate = u
|
2020-01-03 23:31:11 +00:00
|
|
|
}
|
|
|
|
func (r *LuetSystemRepository) IncrementRevision() {
|
2020-02-02 23:58:55 +00:00
|
|
|
r.LuetRepository.Revision++
|
|
|
|
}
|
|
|
|
func (r *LuetSystemRepository) SetAuthentication(auth map[string]string) {
|
|
|
|
r.LuetRepository.Authentication = auth
|
2020-01-03 23:31:11 +00:00
|
|
|
}
|
2020-03-23 22:56:29 +00:00
|
|
|
func (r *LuetSystemRepository) GetRepositoryFile(name string) (LuetRepositoryFile, error) {
|
|
|
|
ans, ok := r.RepositoryFiles[name]
|
|
|
|
if ok {
|
|
|
|
return ans, nil
|
|
|
|
}
|
|
|
|
return ans, errors.New("Repository file " + name + " not found!")
|
|
|
|
}
|
|
|
|
func (r *LuetSystemRepository) SetRepositoryFile(name string, f LuetRepositoryFile) {
|
|
|
|
r.RepositoryFiles[name] = f
|
|
|
|
}
|
2020-01-03 23:31:11 +00:00
|
|
|
|
|
|
|
func (r *LuetSystemRepository) ReadSpecFile(file string, removeFile bool) (Repository, error) {
|
|
|
|
dat, err := ioutil.ReadFile(file)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "Error reading file "+file)
|
|
|
|
}
|
|
|
|
if removeFile {
|
|
|
|
defer os.Remove(file)
|
|
|
|
}
|
|
|
|
|
|
|
|
var repo Repository
|
|
|
|
repo, err = NewLuetSystemRepositoryFromYaml(dat, pkg.NewInMemoryDatabase(false))
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "Error reading repository from file "+file)
|
|
|
|
}
|
|
|
|
|
2020-03-24 11:52:24 +00:00
|
|
|
// Check if mandatory key are present
|
|
|
|
_, err = repo.GetRepositoryFile(REPOFILE_TREE_KEY)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.New("Invalid repository without the " + REPOFILE_TREE_KEY + " key file.")
|
|
|
|
}
|
|
|
|
_, err = repo.GetRepositoryFile(REPOFILE_META_KEY)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.New("Invalid repository without the " + REPOFILE_META_KEY + " key file.")
|
|
|
|
}
|
|
|
|
|
2020-01-03 23:31:11 +00:00
|
|
|
return repo, err
|
|
|
|
}
|
2019-11-22 20:01:38 +00:00
|
|
|
|
2021-01-18 16:58:32 +00:00
|
|
|
func (r *LuetSystemRepository) genLocalRepo(dst string, resetRevision bool) error {
|
2020-01-02 17:31:25 +00:00
|
|
|
err := os.MkdirAll(dst, os.ModePerm)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-01-03 19:09:29 +00:00
|
|
|
r.LastUpdate = strconv.FormatInt(time.Now().Unix(), 10)
|
2020-01-03 23:31:11 +00:00
|
|
|
|
|
|
|
repospec := filepath.Join(dst, REPOSITORY_SPECFILE)
|
|
|
|
if resetRevision {
|
|
|
|
r.Revision = 0
|
|
|
|
} else {
|
|
|
|
if _, err := os.Stat(repospec); !os.IsNotExist(err) {
|
|
|
|
// Read existing file for retrieve revision
|
|
|
|
spec, err := r.ReadSpecFile(repospec, false)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
r.Revision = spec.GetRevision()
|
|
|
|
}
|
|
|
|
}
|
2020-01-03 19:09:29 +00:00
|
|
|
r.Revision++
|
2019-11-29 18:01:59 +00:00
|
|
|
|
2020-01-03 23:31:11 +00:00
|
|
|
Info(fmt.Sprintf(
|
|
|
|
"For repository %s creating revision %d and last update %s...",
|
|
|
|
r.Name, r.Revision, r.LastUpdate,
|
|
|
|
))
|
|
|
|
|
2020-11-13 17:25:44 +00:00
|
|
|
bus.Manager.Publish(bus.EventRepositoryPreBuild, struct {
|
|
|
|
Repo LuetSystemRepository
|
|
|
|
Path string
|
|
|
|
}{
|
|
|
|
Repo: *r,
|
|
|
|
Path: dst,
|
|
|
|
})
|
|
|
|
|
2020-03-23 22:56:29 +00:00
|
|
|
// Create tree and repository file
|
2020-04-30 18:29:28 +00:00
|
|
|
archive, err := config.LuetCfg.GetSystem().TempDir("archive")
|
2019-11-22 20:01:38 +00:00
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "Error met while creating tempdir for archive")
|
|
|
|
}
|
|
|
|
defer os.RemoveAll(archive) // clean up
|
|
|
|
err = r.GetTree().Save(archive)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "Error met while saving the tree")
|
|
|
|
}
|
2020-03-23 22:56:29 +00:00
|
|
|
|
|
|
|
treeFile, err := r.GetRepositoryFile(REPOFILE_TREE_KEY)
|
|
|
|
if err != nil {
|
|
|
|
treeFile = NewDefaultTreeRepositoryFile()
|
|
|
|
r.SetRepositoryFile(REPOFILE_TREE_KEY, treeFile)
|
2020-01-28 16:46:32 +00:00
|
|
|
}
|
|
|
|
|
2020-03-24 17:30:52 +00:00
|
|
|
a := compiler.NewPackageArtifact(filepath.Join(dst, treeFile.GetFileName()))
|
2020-03-23 22:56:29 +00:00
|
|
|
a.SetCompressionType(treeFile.GetCompressionType())
|
2020-01-28 16:46:32 +00:00
|
|
|
err = a.Compress(archive, 1)
|
2019-11-22 20:01:38 +00:00
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "Error met while creating package archive")
|
|
|
|
}
|
2020-01-28 16:46:32 +00:00
|
|
|
|
2020-03-23 22:56:29 +00:00
|
|
|
// Update the tree name with the name created by compression selected.
|
2020-03-24 17:30:52 +00:00
|
|
|
treeFile.SetFileName(path.Base(a.GetPath()))
|
2020-01-28 16:46:32 +00:00
|
|
|
err = a.Hash()
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "Failed generating checksums for tree")
|
|
|
|
}
|
2020-03-23 22:56:29 +00:00
|
|
|
treeFile.SetChecksums(a.GetChecksums())
|
2020-03-23 23:31:41 +00:00
|
|
|
r.SetRepositoryFile(REPOFILE_TREE_KEY, treeFile)
|
2020-03-23 22:56:29 +00:00
|
|
|
|
|
|
|
// Create Metadata struct and serialized repository
|
|
|
|
meta, serialized := r.Serialize()
|
|
|
|
|
|
|
|
// Create metadata file and repository file
|
2020-04-30 18:29:28 +00:00
|
|
|
metaTmpDir, err := config.LuetCfg.GetSystem().TempDir("metadata")
|
2020-03-23 22:56:29 +00:00
|
|
|
defer os.RemoveAll(metaTmpDir) // clean up
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "Error met while creating tempdir for metadata")
|
|
|
|
}
|
|
|
|
|
|
|
|
metaFile, err := r.GetRepositoryFile(REPOFILE_META_KEY)
|
|
|
|
if err != nil {
|
|
|
|
metaFile = NewDefaultMetaRepositoryFile()
|
|
|
|
r.SetRepositoryFile(REPOFILE_META_KEY, metaFile)
|
|
|
|
}
|
|
|
|
|
|
|
|
repoMetaSpec := filepath.Join(metaTmpDir, REPOSITORY_METAFILE)
|
|
|
|
// Create repository.meta.yaml file
|
|
|
|
err = meta.WriteFile(repoMetaSpec)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-03-24 17:30:52 +00:00
|
|
|
a = compiler.NewPackageArtifact(filepath.Join(dst, metaFile.GetFileName()))
|
2020-03-23 22:56:29 +00:00
|
|
|
a.SetCompressionType(metaFile.GetCompressionType())
|
|
|
|
err = a.Compress(metaTmpDir, 1)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "Error met while archiving repository metadata")
|
|
|
|
}
|
|
|
|
|
2020-03-24 17:30:52 +00:00
|
|
|
metaFile.SetFileName(path.Base(a.GetPath()))
|
2020-03-23 23:31:41 +00:00
|
|
|
r.SetRepositoryFile(REPOFILE_META_KEY, metaFile)
|
2020-03-23 22:56:29 +00:00
|
|
|
err = a.Hash()
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "Failed generating checksums for metadata")
|
|
|
|
}
|
|
|
|
metaFile.SetChecksums(a.GetChecksums())
|
2020-01-28 16:46:32 +00:00
|
|
|
|
2020-03-23 22:56:29 +00:00
|
|
|
data, err := yaml.Marshal(serialized)
|
2020-01-28 16:46:32 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
err = ioutil.WriteFile(repospec, data, os.ModePerm)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-11-13 17:25:44 +00:00
|
|
|
bus.Manager.Publish(bus.EventRepositoryPostBuild, struct {
|
|
|
|
Repo LuetSystemRepository
|
|
|
|
Path string
|
|
|
|
}{
|
|
|
|
Repo: *r,
|
|
|
|
Path: dst,
|
|
|
|
})
|
2021-01-18 16:58:32 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *LuetSystemRepository) genDockerRepo(imagePrefix string, resetRevision, force bool) error {
|
|
|
|
// - Iterate over meta, build final images, push them if necessary
|
|
|
|
// - while pushing, check if image already exists, and if exist push them only if --force is supplied
|
|
|
|
// - Generate final images for metadata and push
|
|
|
|
|
2021-01-22 09:19:31 +00:00
|
|
|
imageRepository := fmt.Sprintf("%s:%s", imagePrefix, REPOSITORY_SPECFILE)
|
2021-01-18 16:58:32 +00:00
|
|
|
|
|
|
|
r.LastUpdate = strconv.FormatInt(time.Now().Unix(), 10)
|
2020-11-13 17:25:44 +00:00
|
|
|
|
2021-01-18 16:58:32 +00:00
|
|
|
repoTemp, err := config.LuetCfg.GetSystem().TempDir("repo")
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "Error met while creating tempdir for repository")
|
|
|
|
}
|
|
|
|
defer os.RemoveAll(repoTemp) // clean up
|
|
|
|
|
|
|
|
if r.GetBackend().ImageAvailable(imageRepository) {
|
|
|
|
if err := r.GetBackend().DownloadImage(compiler.CompilerBackendOptions{ImageName: imageRepository}); err != nil {
|
|
|
|
return errors.Wrapf(err, "while downloading '%s'", imageRepository)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := r.GetBackend().ExtractRootfs(compiler.CompilerBackendOptions{ImageName: imageRepository, Destination: repoTemp}, false); err != nil {
|
|
|
|
return errors.Wrapf(err, "while extracting '%s'", imageRepository)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
repospec := filepath.Join(repoTemp, REPOSITORY_SPECFILE)
|
|
|
|
if resetRevision {
|
|
|
|
r.Revision = 0
|
|
|
|
} else {
|
|
|
|
if _, err := os.Stat(repospec); !os.IsNotExist(err) {
|
|
|
|
// Read existing file for retrieve revision
|
|
|
|
spec, err := r.ReadSpecFile(repospec, false)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
r.Revision = spec.GetRevision()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r.Revision++
|
|
|
|
|
|
|
|
Info(fmt.Sprintf(
|
|
|
|
"For repository %s creating revision %d and last update %s...",
|
|
|
|
r.Name, r.Revision, r.LastUpdate,
|
|
|
|
))
|
|
|
|
|
|
|
|
bus.Manager.Publish(bus.EventRepositoryPreBuild, struct {
|
|
|
|
Repo LuetSystemRepository
|
|
|
|
Path string
|
|
|
|
}{
|
|
|
|
Repo: *r,
|
|
|
|
Path: imageRepository,
|
|
|
|
})
|
|
|
|
|
|
|
|
// Create tree and repository file
|
|
|
|
archive, err := config.LuetCfg.GetSystem().TempDir("archive")
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "Error met while creating tempdir for archive")
|
|
|
|
}
|
|
|
|
defer os.RemoveAll(archive) // clean up
|
|
|
|
err = r.GetTree().Save(archive)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "Error met while saving the tree")
|
|
|
|
}
|
|
|
|
|
2021-01-22 10:49:56 +00:00
|
|
|
treeFile, err := r.GetRepositoryFile(REPOFILE_TREE_KEY)
|
|
|
|
if err != nil {
|
|
|
|
treeFile = NewDefaultTreeRepositoryFile()
|
|
|
|
r.SetRepositoryFile(REPOFILE_TREE_KEY, treeFile)
|
|
|
|
}
|
|
|
|
|
2021-01-18 16:58:32 +00:00
|
|
|
a := compiler.NewPackageArtifact(filepath.Join(repoTemp, treeFile.GetFileName()))
|
|
|
|
a.SetCompressionType(treeFile.GetCompressionType())
|
|
|
|
err = a.Compress(archive, 1)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "Error met while creating package archive")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the tree name with the name created by compression selected.
|
2021-01-20 11:31:36 +00:00
|
|
|
treeFile.SetFileName(a.GetFileName())
|
2021-01-18 16:58:32 +00:00
|
|
|
err = a.Hash()
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "Failed generating checksums for tree")
|
|
|
|
}
|
|
|
|
treeFile.SetChecksums(a.GetChecksums())
|
|
|
|
r.SetRepositoryFile(REPOFILE_TREE_KEY, treeFile)
|
|
|
|
|
2021-01-20 11:31:36 +00:00
|
|
|
// we generate a new archive containing the required compressed file.
|
|
|
|
// TODO: Bundle all the extra files in 1 docker image only, instead of an image for each file
|
|
|
|
treeArchive, err := compiler.CreateArtifactForFile(a.GetPath())
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "Failed generating checksums for tree")
|
|
|
|
}
|
|
|
|
imageTree := fmt.Sprintf("%s:%s", imagePrefix, a.GetFileName())
|
2021-01-18 16:58:32 +00:00
|
|
|
Debug("Generating image", imageTree)
|
2021-01-20 11:31:36 +00:00
|
|
|
if opts, err := treeArchive.GenerateFinalImage(imageTree, r.GetBackend(), false); err != nil {
|
2021-01-18 16:58:32 +00:00
|
|
|
return errors.Wrap(err, "Failed generating metadata tree "+opts.ImageName)
|
|
|
|
}
|
2021-01-20 11:31:36 +00:00
|
|
|
if r.PushImages {
|
2021-01-19 11:00:51 +00:00
|
|
|
if err := pushImage(r.GetBackend(), imageTree, true); err != nil {
|
|
|
|
return errors.Wrapf(err, "Failed while pushing image: '%s'", imageTree)
|
|
|
|
}
|
|
|
|
}
|
2021-01-18 16:58:32 +00:00
|
|
|
|
|
|
|
// Create Metadata struct and serialized repository
|
|
|
|
meta, serialized := r.Serialize()
|
|
|
|
|
|
|
|
// Create metadata file and repository file
|
|
|
|
metaTmpDir, err := config.LuetCfg.GetSystem().TempDir("metadata")
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "Error met while creating tempdir for metadata")
|
|
|
|
}
|
|
|
|
defer os.RemoveAll(metaTmpDir) // clean up
|
|
|
|
|
|
|
|
metaFile, err := r.GetRepositoryFile(REPOFILE_META_KEY)
|
|
|
|
if err != nil {
|
|
|
|
metaFile = NewDefaultMetaRepositoryFile()
|
|
|
|
r.SetRepositoryFile(REPOFILE_META_KEY, metaFile)
|
|
|
|
}
|
|
|
|
|
|
|
|
repoMetaSpec := filepath.Join(metaTmpDir, REPOSITORY_METAFILE)
|
|
|
|
// Create repository.meta.yaml file
|
|
|
|
err = meta.WriteFile(repoMetaSpec)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// create temp dir for metafile
|
|
|
|
metaDir, err := config.LuetCfg.GetSystem().TempDir("metadata")
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "Error met while creating tempdir for metadata")
|
|
|
|
}
|
|
|
|
defer os.RemoveAll(metaDir) // clean up
|
|
|
|
|
|
|
|
a = compiler.NewPackageArtifact(filepath.Join(metaDir, metaFile.GetFileName()))
|
|
|
|
a.SetCompressionType(metaFile.GetCompressionType())
|
|
|
|
err = a.Compress(metaTmpDir, 1)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "Error met while archiving repository metadata")
|
|
|
|
}
|
|
|
|
|
2021-01-20 11:31:36 +00:00
|
|
|
metaFile.SetFileName(a.GetFileName())
|
2021-01-18 16:58:32 +00:00
|
|
|
r.SetRepositoryFile(REPOFILE_META_KEY, metaFile)
|
|
|
|
err = a.Hash()
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "Failed generating checksums for metadata")
|
|
|
|
}
|
|
|
|
metaFile.SetChecksums(a.GetChecksums())
|
|
|
|
|
2021-01-20 11:31:36 +00:00
|
|
|
// Files are downloaded as-is from docker images
|
|
|
|
// we generate a new archive containing the required compressed file.
|
|
|
|
// TODO: Bundle all the extra files in 1 docker image only, instead of an image for each file
|
|
|
|
metaArchive, err := compiler.CreateArtifactForFile(a.GetPath())
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "Failed generating checksums for tree")
|
|
|
|
}
|
|
|
|
imageMetaTree := fmt.Sprintf("%s:%s", imagePrefix, a.GetFileName())
|
|
|
|
if opts, err := metaArchive.GenerateFinalImage(imageMetaTree, r.GetBackend(), false); err != nil {
|
2021-01-18 16:58:32 +00:00
|
|
|
return errors.Wrap(err, "Failed generating metadata tree"+opts.ImageName)
|
|
|
|
}
|
2021-01-20 11:31:36 +00:00
|
|
|
if r.PushImages {
|
2021-01-19 11:00:51 +00:00
|
|
|
if err := pushImage(r.GetBackend(), imageMetaTree, true); err != nil {
|
|
|
|
return errors.Wrapf(err, "Failed while pushing image: '%s'", imageMetaTree)
|
|
|
|
}
|
|
|
|
}
|
2021-01-18 16:58:32 +00:00
|
|
|
data, err := yaml.Marshal(serialized)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
err = ioutil.WriteFile(repospec, data, os.ModePerm)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
tempRepoFile := filepath.Join(metaDir, REPOSITORY_SPECFILE+".tar")
|
|
|
|
if err := helpers.Tar(repospec, tempRepoFile); err != nil {
|
|
|
|
return errors.Wrap(err, "Error met while archiving repository file")
|
|
|
|
}
|
|
|
|
|
|
|
|
a = compiler.NewPackageArtifact(tempRepoFile)
|
2021-01-19 14:44:46 +00:00
|
|
|
imageRepo := fmt.Sprintf("%s:%s", imagePrefix, REPOSITORY_SPECFILE)
|
2021-01-18 16:58:32 +00:00
|
|
|
if opts, err := a.GenerateFinalImage(imageRepo, r.GetBackend(), false); err != nil {
|
|
|
|
return errors.Wrap(err, "Failed generating repository image"+opts.ImageName)
|
|
|
|
}
|
2021-01-20 11:31:36 +00:00
|
|
|
if r.PushImages {
|
2021-01-19 11:00:51 +00:00
|
|
|
if err := pushImage(r.GetBackend(), imageRepo, true); err != nil {
|
|
|
|
return errors.Wrapf(err, "Failed while pushing image: '%s'", imageRepo)
|
|
|
|
}
|
|
|
|
}
|
2021-01-18 16:58:32 +00:00
|
|
|
|
|
|
|
bus.Manager.Publish(bus.EventRepositoryPostBuild, struct {
|
|
|
|
Repo LuetSystemRepository
|
|
|
|
Path string
|
|
|
|
}{
|
|
|
|
Repo: *r,
|
|
|
|
Path: imagePrefix,
|
|
|
|
})
|
2019-11-22 20:01:38 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-01-18 16:58:32 +00:00
|
|
|
// Write writes the repository metadata to the supplied destination
|
|
|
|
func (r *LuetSystemRepository) Write(dst string, resetRevision, force bool) error {
|
|
|
|
switch r.GetType() {
|
|
|
|
case DiskRepositoryType, HttpRepositoryType:
|
|
|
|
return r.genLocalRepo(dst, resetRevision)
|
|
|
|
case DockerRepositoryType:
|
|
|
|
return r.genDockerRepo(dst, resetRevision, force)
|
|
|
|
}
|
|
|
|
return errors.New("invalid repository type")
|
|
|
|
}
|
|
|
|
|
2019-12-31 00:21:06 +00:00
|
|
|
func (r *LuetSystemRepository) Client() Client {
|
2019-11-22 22:12:03 +00:00
|
|
|
switch r.GetType() {
|
2021-01-18 16:58:32 +00:00
|
|
|
case DiskRepositoryType:
|
2019-12-30 21:51:51 +00:00
|
|
|
return client.NewLocalClient(client.RepoData{Urls: r.GetUrls()})
|
2021-01-18 16:58:32 +00:00
|
|
|
case HttpRepositoryType:
|
2020-02-02 23:58:55 +00:00
|
|
|
return client.NewHttpClient(
|
|
|
|
client.RepoData{
|
|
|
|
Urls: r.GetUrls(),
|
|
|
|
Authentication: r.GetAuthentication(),
|
|
|
|
})
|
2019-11-22 22:12:03 +00:00
|
|
|
|
2021-01-19 11:00:51 +00:00
|
|
|
case DockerRepositoryType:
|
|
|
|
return client.NewDockerClient(
|
|
|
|
client.RepoData{
|
|
|
|
Urls: r.GetUrls(),
|
|
|
|
Authentication: r.GetAuthentication(),
|
2021-03-11 16:04:26 +00:00
|
|
|
Verify: r.Verify,
|
2021-01-19 11:00:51 +00:00
|
|
|
})
|
|
|
|
}
|
2019-11-22 22:12:03 +00:00
|
|
|
return nil
|
|
|
|
}
|
2021-01-18 16:58:32 +00:00
|
|
|
|
2021-02-28 17:42:54 +00:00
|
|
|
func (r *LuetSystemRepository) SearchArtefact(p pkg.Package) (compiler.Artifact, error) {
|
|
|
|
for _, a := range r.GetIndex() {
|
|
|
|
if a.GetCompileSpec().GetPackage().Matches(p) {
|
|
|
|
return a, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, errors.New("Not found")
|
|
|
|
}
|
|
|
|
|
2020-01-12 22:31:43 +00:00
|
|
|
func (r *LuetSystemRepository) Sync(force bool) (Repository, error) {
|
|
|
|
var repoUpdated bool = false
|
2020-03-23 22:56:29 +00:00
|
|
|
var treefs, metafs string
|
2020-05-09 08:08:21 +00:00
|
|
|
aurora := GetAurora()
|
2020-01-12 22:31:43 +00:00
|
|
|
|
|
|
|
Debug("Sync of the repository", r.Name, "in progress...")
|
2019-11-22 22:12:03 +00:00
|
|
|
c := r.Client()
|
2019-11-23 14:42:05 +00:00
|
|
|
if c == nil {
|
2021-01-19 14:44:46 +00:00
|
|
|
return nil, errors.New("no client could be generated from repository")
|
2019-11-23 14:42:05 +00:00
|
|
|
}
|
2020-01-12 22:31:43 +00:00
|
|
|
|
|
|
|
// Retrieve remote repository.yaml for retrieve revision and date
|
2020-01-03 23:31:11 +00:00
|
|
|
file, err := c.DownloadFile(REPOSITORY_SPECFILE)
|
2019-11-22 20:01:38 +00:00
|
|
|
if err != nil {
|
2020-01-03 23:31:11 +00:00
|
|
|
return nil, errors.Wrap(err, "While downloading "+REPOSITORY_SPECFILE)
|
2019-11-22 20:01:38 +00:00
|
|
|
}
|
2020-01-12 22:31:43 +00:00
|
|
|
|
2020-02-12 09:20:07 +00:00
|
|
|
repobasedir := config.LuetCfg.GetSystem().GetRepoDatabaseDirPath(r.GetName())
|
2020-01-12 22:31:43 +00:00
|
|
|
repo, err := r.ReadSpecFile(file, false)
|
2019-11-22 20:01:38 +00:00
|
|
|
if err != nil {
|
2020-01-03 23:31:11 +00:00
|
|
|
return nil, err
|
2019-11-22 20:01:38 +00:00
|
|
|
}
|
2021-01-19 09:46:31 +00:00
|
|
|
// Remove temporary file that contains repository.yaml
|
2020-01-12 22:31:43 +00:00
|
|
|
// Example: /tmp/HttpClient236052003
|
|
|
|
defer os.RemoveAll(file)
|
|
|
|
|
|
|
|
if r.Cached {
|
|
|
|
if !force {
|
|
|
|
localRepo, _ := r.ReadSpecFile(filepath.Join(repobasedir, REPOSITORY_SPECFILE), false)
|
|
|
|
if localRepo != nil {
|
|
|
|
if localRepo.GetRevision() == repo.GetRevision() &&
|
|
|
|
localRepo.GetLastUpdate() == repo.GetLastUpdate() {
|
|
|
|
repoUpdated = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if r.GetTreePath() == "" {
|
|
|
|
treefs = filepath.Join(repobasedir, "treefs")
|
|
|
|
} else {
|
|
|
|
treefs = r.GetTreePath()
|
|
|
|
}
|
2020-03-23 22:56:29 +00:00
|
|
|
if r.GetMetaPath() == "" {
|
|
|
|
metafs = filepath.Join(repobasedir, "metafs")
|
|
|
|
} else {
|
|
|
|
metafs = r.GetMetaPath()
|
|
|
|
}
|
2019-11-22 20:01:38 +00:00
|
|
|
|
2020-01-12 22:31:43 +00:00
|
|
|
} else {
|
2020-04-30 18:29:28 +00:00
|
|
|
treefs, err = config.LuetCfg.GetSystem().TempDir("treefs")
|
2020-01-12 22:31:43 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "Error met while creating tempdir for rootfs")
|
|
|
|
}
|
2020-04-30 18:29:28 +00:00
|
|
|
metafs, err = config.LuetCfg.GetSystem().TempDir("metafs")
|
2020-03-23 22:56:29 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "Error met whilte creating tempdir for metafs")
|
|
|
|
}
|
2019-11-22 20:01:38 +00:00
|
|
|
}
|
|
|
|
|
2020-03-23 22:56:29 +00:00
|
|
|
// POST: treeFile and metaFile are present. I check this inside
|
|
|
|
// ReadSpecFile and NewLuetSystemRepositoryFromYaml
|
|
|
|
treeFile, _ := repo.GetRepositoryFile(REPOFILE_TREE_KEY)
|
|
|
|
metaFile, _ := repo.GetRepositoryFile(REPOFILE_META_KEY)
|
|
|
|
|
2020-01-12 22:31:43 +00:00
|
|
|
if !repoUpdated {
|
2020-01-28 16:46:32 +00:00
|
|
|
|
2020-03-23 22:56:29 +00:00
|
|
|
// Get Tree
|
2021-01-19 09:46:31 +00:00
|
|
|
downloadedTreeFile, err := c.DownloadFile(treeFile.GetFileName())
|
2020-01-12 22:31:43 +00:00
|
|
|
if err != nil {
|
2020-03-24 17:30:52 +00:00
|
|
|
return nil, errors.Wrap(err, "While downloading "+treeFile.GetFileName())
|
2020-01-28 16:46:32 +00:00
|
|
|
}
|
2021-01-19 09:46:31 +00:00
|
|
|
defer os.Remove(downloadedTreeFile)
|
2020-01-28 16:46:32 +00:00
|
|
|
|
2021-01-19 09:46:31 +00:00
|
|
|
// Treat the file as artifact, in order to verify it
|
|
|
|
treeFileArtifact := compiler.NewPackageArtifact(downloadedTreeFile)
|
|
|
|
treeFileArtifact.SetChecksums(treeFile.GetChecksums())
|
|
|
|
treeFileArtifact.SetCompressionType(treeFile.GetCompressionType())
|
2020-01-28 16:46:32 +00:00
|
|
|
|
2021-01-19 09:46:31 +00:00
|
|
|
err = treeFileArtifact.Verify()
|
2020-01-28 16:46:32 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "Tree integrity check failure")
|
2020-01-12 22:31:43 +00:00
|
|
|
}
|
2019-11-22 20:01:38 +00:00
|
|
|
|
2020-01-12 22:31:43 +00:00
|
|
|
Debug("Tree tarball for the repository " + r.GetName() + " downloaded correctly.")
|
2019-11-22 20:01:38 +00:00
|
|
|
|
2020-03-23 22:56:29 +00:00
|
|
|
// Get Repository Metadata
|
2021-01-19 09:46:31 +00:00
|
|
|
downloadedMeta, err := c.DownloadFile(metaFile.GetFileName())
|
2020-03-23 22:56:29 +00:00
|
|
|
if err != nil {
|
2020-03-24 17:30:52 +00:00
|
|
|
return nil, errors.Wrap(err, "While downloading "+metaFile.GetFileName())
|
2020-03-23 22:56:29 +00:00
|
|
|
}
|
2021-01-19 09:46:31 +00:00
|
|
|
defer os.Remove(downloadedMeta)
|
2020-03-23 22:56:29 +00:00
|
|
|
|
2021-01-19 09:46:31 +00:00
|
|
|
metaFileArtifact := compiler.NewPackageArtifact(downloadedMeta)
|
|
|
|
metaFileArtifact.SetChecksums(metaFile.GetChecksums())
|
|
|
|
metaFileArtifact.SetCompressionType(metaFile.GetCompressionType())
|
2020-03-23 22:56:29 +00:00
|
|
|
|
2021-01-19 09:46:31 +00:00
|
|
|
err = metaFileArtifact.Verify()
|
2020-03-23 22:56:29 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "Metadata integrity check failure")
|
|
|
|
}
|
|
|
|
|
|
|
|
Debug("Metadata tarball for the repository " + r.GetName() + " downloaded correctly.")
|
|
|
|
|
2020-01-12 22:31:43 +00:00
|
|
|
if r.Cached {
|
|
|
|
// Copy updated repository.yaml file to repo dir now that the tree is synced.
|
|
|
|
err = helpers.CopyFile(file, filepath.Join(repobasedir, REPOSITORY_SPECFILE))
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "Error on update "+REPOSITORY_SPECFILE)
|
|
|
|
}
|
|
|
|
// Remove previous tree
|
|
|
|
os.RemoveAll(treefs)
|
2020-03-23 22:56:29 +00:00
|
|
|
// Remove previous meta dir
|
|
|
|
os.RemoveAll(metafs)
|
2020-01-12 22:31:43 +00:00
|
|
|
}
|
2020-01-28 16:46:32 +00:00
|
|
|
Debug("Decompress tree of the repository " + r.Name + "...")
|
|
|
|
|
2021-01-19 09:46:31 +00:00
|
|
|
err = treeFileArtifact.Unpack(treefs, true)
|
2020-01-12 22:31:43 +00:00
|
|
|
if err != nil {
|
2020-01-28 16:46:32 +00:00
|
|
|
return nil, errors.Wrap(err, "Error met while unpacking tree")
|
2020-01-12 22:31:43 +00:00
|
|
|
}
|
|
|
|
|
2020-03-23 22:56:29 +00:00
|
|
|
// FIXME: It seems that tar with only one file doesn't create destination
|
|
|
|
// directory. I create directory directly for now.
|
|
|
|
os.MkdirAll(metafs, os.ModePerm)
|
2021-01-19 09:46:31 +00:00
|
|
|
err = metaFileArtifact.Unpack(metafs, true)
|
2020-03-23 22:56:29 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "Error met while unpacking metadata")
|
|
|
|
}
|
|
|
|
|
2020-01-12 22:31:43 +00:00
|
|
|
tsec, _ := strconv.ParseInt(repo.GetLastUpdate(), 10, 64)
|
|
|
|
|
|
|
|
InfoC(
|
2020-05-09 08:08:21 +00:00
|
|
|
aurora.Bold(
|
|
|
|
aurora.Red(":house: Repository "+repo.GetName()+" revision: ")).String() +
|
|
|
|
aurora.Bold(aurora.Green(repo.GetRevision())).String() + " - " +
|
|
|
|
aurora.Bold(aurora.Green(time.Unix(tsec, 0).String())).String(),
|
2020-01-12 22:31:43 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
} else {
|
2020-04-18 15:33:46 +00:00
|
|
|
Info("Repository", repo.GetName(), "is already up to date.")
|
2019-11-22 20:01:38 +00:00
|
|
|
}
|
|
|
|
|
2020-03-23 22:56:29 +00:00
|
|
|
meta, err := NewLuetSystemRepositoryMetadata(
|
|
|
|
filepath.Join(metafs, REPOSITORY_METAFILE), false,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "While processing "+REPOSITORY_METAFILE)
|
|
|
|
}
|
2020-05-01 09:07:14 +00:00
|
|
|
repo.SetIndex(meta.ToArtifactIndex())
|
2020-03-23 22:56:29 +00:00
|
|
|
|
2020-01-02 17:31:25 +00:00
|
|
|
reciper := tree.NewInstallerRecipe(pkg.NewInMemoryDatabase(false))
|
2019-11-22 20:01:38 +00:00
|
|
|
err = reciper.Load(treefs)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "Error met while unpacking rootfs")
|
|
|
|
}
|
2020-01-12 22:31:43 +00:00
|
|
|
|
2019-11-23 14:42:05 +00:00
|
|
|
repo.SetTree(reciper)
|
2019-11-22 20:01:38 +00:00
|
|
|
repo.SetTreePath(treefs)
|
2020-04-18 15:33:46 +00:00
|
|
|
|
|
|
|
// Copy the local available data to the one which was synced
|
|
|
|
// e.g. locally we can override the type (disk), or priority
|
|
|
|
// while remotely it could be advertized differently
|
2019-12-30 21:51:51 +00:00
|
|
|
repo.SetUrls(r.GetUrls())
|
2020-02-02 23:58:55 +00:00
|
|
|
repo.SetAuthentication(r.GetAuthentication())
|
2020-04-18 15:33:46 +00:00
|
|
|
repo.SetType(r.GetType())
|
|
|
|
repo.SetPriority(r.GetPriority())
|
2020-05-24 10:16:02 +00:00
|
|
|
repo.SetName(r.GetName())
|
2020-04-18 15:33:46 +00:00
|
|
|
InfoC(
|
2020-12-02 17:24:32 +00:00
|
|
|
aurora.Yellow(":information_source:").String() +
|
|
|
|
aurora.Magenta("Repository: ").String() +
|
|
|
|
aurora.Green(aurora.Bold(repo.GetName()).String()).String() +
|
|
|
|
aurora.Magenta(" Priority: ").String() +
|
|
|
|
aurora.Bold(aurora.Green(repo.GetPriority())).String() +
|
|
|
|
aurora.Magenta(" Type: ").String() +
|
2020-05-09 08:08:21 +00:00
|
|
|
aurora.Bold(aurora.Green(repo.GetType())).String(),
|
2020-04-18 15:33:46 +00:00
|
|
|
)
|
2019-11-22 20:01:38 +00:00
|
|
|
return repo, nil
|
|
|
|
}
|
|
|
|
|
2020-03-23 22:56:29 +00:00
|
|
|
func (r *LuetSystemRepository) Serialize() (*LuetSystemRepositoryMetadata, LuetSystemRepositorySerialized) {
|
|
|
|
|
|
|
|
serialized := LuetSystemRepositorySerialized{
|
|
|
|
Name: r.Name,
|
|
|
|
Description: r.Description,
|
|
|
|
Urls: r.Urls,
|
|
|
|
Priority: r.Priority,
|
|
|
|
Type: r.Type,
|
|
|
|
Revision: r.Revision,
|
|
|
|
LastUpdate: r.LastUpdate,
|
|
|
|
RepositoryFiles: r.RepositoryFiles,
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if is needed set the index or simply use
|
|
|
|
// value returned by CleanPath
|
|
|
|
r.Index = r.Index.CleanPath()
|
|
|
|
|
|
|
|
meta := &LuetSystemRepositoryMetadata{
|
|
|
|
Index: []*compiler.PackageArtifact{},
|
|
|
|
}
|
|
|
|
for _, a := range r.Index {
|
|
|
|
art := a.(*compiler.PackageArtifact)
|
|
|
|
meta.Index = append(meta.Index, art)
|
|
|
|
}
|
|
|
|
|
|
|
|
return meta, serialized
|
|
|
|
}
|
|
|
|
|
2019-11-22 20:01:38 +00:00
|
|
|
func (r Repositories) Len() int { return len(r) }
|
|
|
|
func (r Repositories) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
|
|
|
|
func (r Repositories) Less(i, j int) bool {
|
|
|
|
return r[i].GetPriority() < r[j].GetPriority()
|
|
|
|
}
|
|
|
|
|
2020-04-04 12:29:08 +00:00
|
|
|
func (r Repositories) World() pkg.Packages {
|
2019-11-22 20:01:38 +00:00
|
|
|
cache := map[string]pkg.Package{}
|
2020-04-04 12:29:08 +00:00
|
|
|
world := pkg.Packages{}
|
2019-11-22 20:01:38 +00:00
|
|
|
|
|
|
|
// Get Uniques. Walk in reverse so the definitions of most prio-repo overwrites lower ones
|
|
|
|
// In this way, when we will walk again later the deps sorting them by most higher prio we have better chance of success.
|
|
|
|
for i := len(r) - 1; i >= 0; i-- {
|
2019-11-29 18:01:52 +00:00
|
|
|
for _, p := range r[i].GetTree().GetDatabase().World() {
|
2019-11-22 20:01:38 +00:00
|
|
|
cache[p.GetFingerPrint()] = p
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, v := range cache {
|
|
|
|
world = append(world, v)
|
|
|
|
}
|
|
|
|
|
|
|
|
return world
|
|
|
|
}
|
|
|
|
|
2019-11-29 18:01:52 +00:00
|
|
|
func (r Repositories) SyncDatabase(d pkg.PackageDatabase) {
|
|
|
|
cache := map[string]bool{}
|
|
|
|
|
|
|
|
// Get Uniques. Walk in reverse so the definitions of most prio-repo overwrites lower ones
|
|
|
|
// In this way, when we will walk again later the deps sorting them by most higher prio we have better chance of success.
|
|
|
|
for i := len(r) - 1; i >= 0; i-- {
|
|
|
|
for _, p := range r[i].GetTree().GetDatabase().World() {
|
|
|
|
if _, ok := cache[p.GetFingerPrint()]; !ok {
|
|
|
|
cache[p.GetFingerPrint()] = true
|
|
|
|
d.CreatePackage(p)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-11-22 20:01:38 +00:00
|
|
|
type PackageMatch struct {
|
2021-02-28 17:42:54 +00:00
|
|
|
Repo Repository
|
|
|
|
Artifact compiler.Artifact
|
|
|
|
Package pkg.Package
|
2019-11-22 20:01:38 +00:00
|
|
|
}
|
|
|
|
|
2020-04-04 12:29:08 +00:00
|
|
|
func (re Repositories) PackageMatches(p pkg.Packages) []PackageMatch {
|
2019-11-22 20:01:38 +00:00
|
|
|
// TODO: Better heuristic. here we pick the first repo that contains the atom, sorted by priority but
|
|
|
|
// we should do a permutations and get the best match, and in case there are more solutions the user should be able to pick
|
|
|
|
sort.Sort(re)
|
|
|
|
|
|
|
|
var matches []PackageMatch
|
|
|
|
PACKAGE:
|
|
|
|
for _, pack := range p {
|
|
|
|
for _, r := range re {
|
2019-11-29 18:01:52 +00:00
|
|
|
c, err := r.GetTree().GetDatabase().FindPackage(pack)
|
2019-11-22 20:01:38 +00:00
|
|
|
if err == nil {
|
|
|
|
matches = append(matches, PackageMatch{Package: c, Repo: r})
|
|
|
|
continue PACKAGE
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return matches
|
|
|
|
|
|
|
|
}
|
2019-11-25 19:03:17 +00:00
|
|
|
|
2020-04-04 12:29:08 +00:00
|
|
|
func (re Repositories) ResolveSelectors(p pkg.Packages) pkg.Packages {
|
2020-02-04 19:15:59 +00:00
|
|
|
// If a selector is given, get the best from each repo
|
|
|
|
sort.Sort(re) // respect prio
|
2020-04-04 12:29:08 +00:00
|
|
|
var matches pkg.Packages
|
2020-02-04 19:15:59 +00:00
|
|
|
PACKAGE:
|
|
|
|
for _, pack := range p {
|
2020-02-17 16:20:52 +00:00
|
|
|
REPOSITORY:
|
2020-02-04 19:15:59 +00:00
|
|
|
for _, r := range re {
|
|
|
|
if pack.IsSelector() {
|
|
|
|
c, err := r.GetTree().GetDatabase().FindPackageCandidate(pack)
|
2020-02-17 16:20:52 +00:00
|
|
|
// If FindPackageCandidate returns the same package, it means it couldn't find one.
|
|
|
|
// Skip this repository and keep looking.
|
2020-12-19 13:57:42 +00:00
|
|
|
if err != nil { //c.String() == pack.String() {
|
2020-02-17 16:20:52 +00:00
|
|
|
continue REPOSITORY
|
|
|
|
}
|
2020-12-19 13:57:42 +00:00
|
|
|
matches = append(matches, c)
|
|
|
|
continue PACKAGE
|
2020-02-04 19:15:59 +00:00
|
|
|
} else {
|
2020-02-17 16:20:52 +00:00
|
|
|
// If it's not a selector, just append it
|
2020-02-04 19:15:59 +00:00
|
|
|
matches = append(matches, pack)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return matches
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-02-28 17:42:54 +00:00
|
|
|
func (re Repositories) SearchPackages(p string, t LuetSearchModeType) []PackageMatch {
|
2019-11-25 19:03:17 +00:00
|
|
|
sort.Sort(re)
|
|
|
|
var matches []PackageMatch
|
2020-03-20 22:47:35 +00:00
|
|
|
var err error
|
2019-11-25 19:03:17 +00:00
|
|
|
|
|
|
|
for _, r := range re {
|
2020-04-04 12:29:08 +00:00
|
|
|
var repoMatches pkg.Packages
|
2020-03-20 22:47:35 +00:00
|
|
|
|
2021-02-28 17:42:54 +00:00
|
|
|
switch t {
|
2020-03-22 09:46:51 +00:00
|
|
|
case SRegexPkg:
|
|
|
|
repoMatches, err = r.GetTree().GetDatabase().FindPackageMatch(p)
|
|
|
|
case SLabel:
|
2020-03-20 22:47:35 +00:00
|
|
|
repoMatches, err = r.GetTree().GetDatabase().FindPackageLabel(p)
|
2020-03-22 09:46:51 +00:00
|
|
|
case SRegexLabel:
|
2020-03-20 22:47:35 +00:00
|
|
|
repoMatches, err = r.GetTree().GetDatabase().FindPackageLabelMatch(p)
|
2021-02-28 17:42:54 +00:00
|
|
|
case FileSearch:
|
|
|
|
repoMatches, err = r.FileSearch(p)
|
2020-03-20 22:47:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if err == nil && len(repoMatches) > 0 {
|
|
|
|
for _, pack := range repoMatches {
|
2021-02-28 17:42:54 +00:00
|
|
|
a, _ := r.SearchArtefact(pack)
|
|
|
|
matches = append(matches, PackageMatch{Package: pack, Repo: r, Artifact: a})
|
2019-11-25 19:03:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return matches
|
|
|
|
}
|
2020-03-20 22:47:35 +00:00
|
|
|
|
|
|
|
func (re Repositories) SearchLabelMatch(s string) []PackageMatch {
|
2021-02-28 17:42:54 +00:00
|
|
|
return re.SearchPackages(s, SRegexLabel)
|
2020-03-20 22:47:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (re Repositories) SearchLabel(s string) []PackageMatch {
|
2021-02-28 17:42:54 +00:00
|
|
|
return re.SearchPackages(s, SLabel)
|
2020-03-20 22:47:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (re Repositories) Search(s string) []PackageMatch {
|
2021-02-28 17:42:54 +00:00
|
|
|
return re.SearchPackages(s, SRegexPkg)
|
2020-03-20 22:47:35 +00:00
|
|
|
}
|