Compare commits

..

3 Commits

Author SHA1 Message Date
Ettore Di Giacinto
fd90e0d627 🆕 Tag 0.21.2 2021-12-18 17:30:30 +01:00
Ettore Di Giacinto
20d01e43c7 🎨 Update repos automatically only if out-of-sync
Fixes #274
Fixes #212
2021-12-18 16:32:03 +01:00
Ettore Di Giacinto
ed63236516 🔧 take into account of multiple installs 2021-12-18 15:32:35 +01:00
4 changed files with 120 additions and 43 deletions

View File

@@ -1,5 +1,6 @@
// Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org> // Copyright © 2019 Ettore Di Giacinto <mudler@gentoo.org>
// Daniele Rondina <geaaru@sabayonlinux.org> // Daniele Rondina <geaaru@sabayonlinux.org>
// Copyright © 2021 Ettore Di Giacinto <mudler@mocaccino.org>
// //
// This program is free software; you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
@@ -24,7 +25,7 @@ import (
) )
func NewRepoUpdateCommand() *cobra.Command { func NewRepoUpdateCommand() *cobra.Command {
var ans = &cobra.Command{ var repoUpdate = &cobra.Command{
Use: "update [repo1] [repo2] [OPTIONS]", Use: "update [repo1] [repo2] [OPTIONS]",
Short: "Update a specific cached repository or all cached repositories.", Short: "Update a specific cached repository or all cached repositories.",
Example: ` Example: `
@@ -72,8 +73,8 @@ $> luet repo update repo1 repo2
}, },
} }
ans.Flags().BoolP("ignore-errors", "i", false, "Ignore errors on sync repositories.") repoUpdate.Flags().BoolP("ignore-errors", "i", false, "Ignore errors on sync repositories.")
ans.Flags().BoolP("force", "f", false, "Force resync.") repoUpdate.Flags().BoolP("force", "f", true, "Force resync.")
return ans return repoUpdate
} }

View File

@@ -30,7 +30,7 @@ var cfgFile string
var Verbose bool var Verbose bool
const ( const (
LuetCLIVersion = "0.21.1" LuetCLIVersion = "0.21.2"
LuetEnvPrefix = "LUET" LuetEnvPrefix = "LUET"
) )

View File

@@ -279,19 +279,17 @@ func (l *LuetInstaller) swap(o Option, syncedRepos Repositories, toRemove pkg.Pa
} }
l.Options.Context.Info("Computed operations") l.Options.Context.Info("Computed operations")
for _, o := range ops {
for _, o := range ops {
toUninstall := "" toUninstall := ""
toInstall := "" toInstall := ""
for _, u := range o.Uninstall { for _, u := range o.Uninstall {
toUninstall += u.Package.HumanReadableString() toUninstall += fmt.Sprintf(" %s", u.Package.HumanReadableString())
} }
for _, u := range o.Install { for _, u := range o.Install {
toInstall += u.Package.HumanReadableString() toInstall += fmt.Sprintf(" %s", u.Package.HumanReadableString())
} }
l.Options.Context.Info(fmt.Sprintf("%s -> %s", toUninstall, toInstall)) l.Options.Context.Info(fmt.Sprintf("%s -> %s", toUninstall, toInstall))
} }
err = l.runOps(ops, s) err = l.runOps(ops, s)
@@ -417,16 +415,19 @@ func (l *LuetInstaller) getOpsWithOptions(
l.Options.Context.Debug("Computing installation order") l.Options.Context.Debug("Computing installation order")
resOps := []installerOp{} resOps := []installerOp{}
insertPackage := func(install pkg.Package, uninstall ...pkg.Package) { insertPackage := func(install []pkg.Package, uninstall ...pkg.Package) {
if len(install) == 0 && len(uninstall) == 0 {
return
}
uOpts := []operation{} uOpts := []operation{}
for _, u := range uninstall { for _, u := range uninstall {
uOpts = append(uOpts, operation{Package: u, Option: uninstallOpt}) uOpts = append(uOpts, operation{Package: u, Option: uninstallOpt})
} }
resOps = append(resOps, installerOp{ iOpts := []installOperation{}
Uninstall: uOpts, for _, u := range install {
Install: []installOperation{{ iOpts = append(iOpts, installOperation{
operation: operation{ operation: operation{
Package: install, Package: u,
Option: installOpt, Option: installOpt,
}, },
Matches: installMatch, Matches: installMatch,
@@ -434,11 +435,43 @@ func (l *LuetInstaller) getOpsWithOptions(
Reposiories: syncedRepos, Reposiories: syncedRepos,
Assertions: solution, Assertions: solution,
Database: allRepos, Database: allRepos,
}}, })
}
resOps = append(resOps, installerOp{
Uninstall: uOpts,
Install: iOpts,
}) })
} }
removals := make(map[string]interface{}) removals := make(map[string]interface{})
additions := make(map[string]interface{})
remove := func(p pkg.Package) {
removals[p.GetPackageName()] = nil
}
add := func(p pkg.Package) {
additions[p.GetPackageName()] = nil
}
added := func(p pkg.Package) bool {
_, exists := additions[p.GetPackageName()]
return exists
}
removed := func(p pkg.Package) bool {
_, exists := removals[p.GetPackageName()]
return exists
}
findToBeInstalled := func(p pkg.Package) pkg.Package {
for _, m := range installMatch {
if m.Package.GetPackageName() == p.GetPackageName() {
return m.Package
}
}
return nil
}
fileIndex := s.FileIndex() fileIndex := s.FileIndex()
@@ -478,21 +511,39 @@ func (l *LuetInstaller) getOpsWithOptions(
foundPackages[pack.HumanReadableString()] = pack foundPackages[pack.HumanReadableString()] = pack
} }
toInstall := []pkg.Package{}
if !added(match.Package) {
toInstall = append(toInstall, match.Package)
add(match.Package)
}
toRemove := []pkg.Package{} toRemove := []pkg.Package{}
for _, p := range foundPackages { for _, p := range foundPackages {
if _, ok := removals[p.GetPackageName()]; !ok { if !removed(p) {
toRemove = append(toRemove, p) toRemove = append(toRemove, p)
removals[p.GetPackageName()] = nil if pp := findToBeInstalled(p); pp != nil && !added(pp) {
toInstall = append(toInstall, pp)
add(pp)
}
remove(p)
} }
} }
insertPackage(match.Package, toRemove...) // toInstall needs to have:
// equivalent of what was found in foundPackages AND
// was not already added to installation
insertPackage(toInstall, toRemove...)
} else if pack, err := toUninstall.Find(match.Package.GetPackageName()); err == nil { } else if pack, err := toUninstall.Find(match.Package.GetPackageName()); err == nil {
if _, ok := removals[pack.GetPackageName()]; !ok { if !removed(pack) {
insertPackage(match.Package, pack) toInstall := []pkg.Package{}
removals[pack.GetPackageName()] = nil if !added(match.Package) {
toInstall = append(toInstall, match.Package)
add(match.Package)
}
insertPackage(toInstall, pack)
remove(pack)
} }
} else { } else if !added(match.Package) {
insertPackage(match.Package) insertPackage([]pkg.Package{match.Package})
add(match.Package)
} }
} }

View File

@@ -856,7 +856,20 @@ func (r *LuetSystemRepository) Sync(ctx *types.Context, force bool) (*LuetSystem
var repoUpdated bool = false var repoUpdated bool = false
var treefs, metafs string var treefs, metafs string
repobasedir := ctx.Config.GetSystem().GetRepoDatabaseDirPath(r.GetName())
toTimeSync := false
dat, err := ioutil.ReadFile(filepath.Join(repobasedir, "SYNCTIME"))
if err == nil {
parsed, _ := time.Parse(time.RFC3339, string(dat))
if time.Now().After(parsed.Add(24 * time.Hour)) {
toTimeSync = true
ctx.Debug(r.Name, "is old, refresh is suggested")
}
}
ctx.Debug("Sync of the repository", r.Name, "in progress...") ctx.Debug("Sync of the repository", r.Name, "in progress...")
c := r.Client(ctx) c := r.Client(ctx)
if c == nil { if c == nil {
return nil, errors.New("no client could be generated from repository") return nil, errors.New("no client could be generated from repository")
@@ -864,20 +877,29 @@ func (r *LuetSystemRepository) Sync(ctx *types.Context, force bool) (*LuetSystem
repositoryReferenceID := r.referenceID() repositoryReferenceID := r.referenceID()
// Retrieve remote repository.yaml for retrieve revision and date var downloadedRepoMeta *LuetSystemRepository
file, err := c.DownloadFile(repositoryReferenceID) var file string
if err != nil { repoFile := filepath.Join(repobasedir, repositoryReferenceID)
return nil, errors.Wrap(err, "while downloading "+repositoryReferenceID)
}
repobasedir := ctx.Config.GetSystem().GetRepoDatabaseDirPath(r.GetName()) _, repoExistsErr := os.Stat(repoFile)
downloadedRepoMeta, err := r.ReadSpecFile(file) if toTimeSync || force || os.IsNotExist(repoExistsErr) {
if err != nil { // Retrieve remote repository.yaml for retrieve revision and date
return nil, err file, err = c.DownloadFile(repositoryReferenceID)
if err != nil {
return nil, errors.Wrap(err, "while downloading "+repositoryReferenceID)
}
downloadedRepoMeta, err = r.ReadSpecFile(file)
if err != nil {
return nil, err
}
defer os.RemoveAll(file)
} else {
downloadedRepoMeta, err = r.ReadSpecFile(repoFile)
if err != nil {
return nil, err
}
repoUpdated = true
} }
// Remove temporary file that contains repository.yaml
// Example: /tmp/HttpClient236052003
defer os.RemoveAll(file)
if r.Cached { if r.Cached {
if !force { if !force {
@@ -968,8 +990,8 @@ func (r *LuetSystemRepository) Sync(ctx *types.Context, force bool) (*LuetSystem
downloadedRepoMeta.GetRevision(), downloadedRepoMeta.GetRevision(),
time.Unix(tsec, 0).String())) time.Unix(tsec, 0).String()))
} else { now := time.Now().Format(time.RFC3339)
ctx.Info("Repository", downloadedRepoMeta.GetName(), "is already up to date.") ioutil.WriteFile(filepath.Join(repobasedir, "SYNCTIME"), []byte(now), os.ModePerm)
} }
meta, err := NewLuetSystemRepositoryMetadata( meta, err := NewLuetSystemRepositoryMetadata(
@@ -993,11 +1015,14 @@ func (r *LuetSystemRepository) Sync(ctx *types.Context, force bool) (*LuetSystem
// e.g. locally we can override the type (disk), or priority // e.g. locally we can override the type (disk), or priority
// while remotely it could be advertized differently // while remotely it could be advertized differently
r.fill(downloadedRepoMeta) r.fill(downloadedRepoMeta)
ctx.Info(
fmt.Sprintf(":information_source: Repository: %s Priority: %d Type: %s", if !repoUpdated {
downloadedRepoMeta.GetName(), ctx.Info(
downloadedRepoMeta.GetPriority(), fmt.Sprintf(":information_source: Repository: %s Priority: %d Type: %s",
downloadedRepoMeta.GetType())) downloadedRepoMeta.GetName(),
downloadedRepoMeta.GetPriority(),
downloadedRepoMeta.GetType()))
}
return downloadedRepoMeta, nil return downloadedRepoMeta, nil
} }