From 9aa315978789f3d89f59a30cddc09cf86d8673bc Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Thu, 29 Jul 2021 10:14:05 +0200 Subject: [PATCH] Check for file conflicts before install Fixes #88 --- pkg/helpers/slice.go | 10 ++++++++ pkg/installer/installer.go | 52 +++++++++++++++++++++++++++++++++++++- pkg/installer/system.go | 15 +++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 pkg/helpers/slice.go diff --git a/pkg/helpers/slice.go b/pkg/helpers/slice.go new file mode 100644 index 00000000..d7bb04d1 --- /dev/null +++ b/pkg/helpers/slice.go @@ -0,0 +1,10 @@ +package helpers + +func Contains(s []string, e string) bool { + for _, a := range s { + if a == e { + return true + } + } + return false +} diff --git a/pkg/installer/installer.go b/pkg/installer/installer.go index b4bc8fce..02eb1043 100644 --- a/pkg/installer/installer.go +++ b/pkg/installer/installer.go @@ -27,6 +27,7 @@ import ( "github.com/mudler/luet/pkg/bus" artifact "github.com/mudler/luet/pkg/compiler/types/artifact" "github.com/mudler/luet/pkg/config" + "github.com/mudler/luet/pkg/helpers" fileHelper "github.com/mudler/luet/pkg/helpers/file" "github.com/mudler/luet/pkg/helpers/match" . "github.com/mudler/luet/pkg/logger" @@ -755,12 +756,61 @@ func (l *LuetInstaller) getFinalizers(allRepos pkg.PackageDatabase, solution sol return toFinalize, nil } +func (l *LuetInstaller) checkFileconflicts(toInstall map[string]ArtifactMatch, s *System) error { + Info("Checking for file conflicts..") + filesToInstall := []string{} + for _, m := range toInstall { + a, err := l.downloadPackage(m) + if err != nil && !l.Options.Force { + return errors.Wrap(err, "Failed downloading package") + } + files, err := a.FileList() + if err != nil && !l.Options.Force { + return errors.Wrapf(err, "Could not get filelist for %s", a.CompileSpec.Package.HumanReadableString()) + } + + for _, f := range files { + if helpers.Contains(filesToInstall, f) { + return fmt.Errorf( + "file conflict between packages to be installed", + ) + } + + exists, p, err := s.ExistsPackageFile(f) + if err != nil { + return errors.Wrap(err, "failed checking into system db") + } + if exists { + return fmt.Errorf( + "file conflict between '%s' and '%s' ( file: %s )", + p.HumanReadableString(), + m.Package.HumanReadableString(), + f, + ) + } + } + filesToInstall = append(filesToInstall, files...) + } + + return nil +} + func (l *LuetInstaller) install(o Option, syncedRepos Repositories, toInstall map[string]ArtifactMatch, p pkg.Packages, solution solver.PackagesAssertions, allRepos pkg.PackageDatabase, s *System) error { - // Install packages into rootfs in parallel. + + // Download packages in parallel first if err := l.download(syncedRepos, toInstall); err != nil { return errors.Wrap(err, "Downloading packages") } + // Check file conflicts + if err := l.checkFileconflicts(toInstall, s); err != nil { + if !l.Options.Force { + return errors.Wrap(err, "file conflict found") + } else { + Warning("file conflict found", err.Error()) + } + } + if l.Options.DownloadOnly { return nil } diff --git a/pkg/installer/system.go b/pkg/installer/system.go index 496651cc..a61f21ee 100644 --- a/pkg/installer/system.go +++ b/pkg/installer/system.go @@ -52,3 +52,18 @@ func (s *System) ExecuteFinalizers(packs []pkg.Package) error { } return errs } + +func (s *System) ExistsPackageFile(file string) (bool, pkg.Package, error) { + for _, p := range s.Database.World() { + files, err := s.Database.GetPackageFiles(p) + if err != nil { + return false, nil, err + } + for _, f := range files { + if f == file { + return true, p, nil + } + } + } + return false, nil, nil +}