diff --git a/pkg/installer/installer.go b/pkg/installer/installer.go index f665eb57..f27e6e0c 100644 --- a/pkg/installer/installer.go +++ b/pkg/installer/installer.go @@ -21,6 +21,7 @@ import ( "io/ioutil" "os" "os/exec" + "path/filepath" "sort" "sync" @@ -311,8 +312,60 @@ func (l *LuetInstaller) installerWorker(i int, wg *sync.WaitGroup, c <-chan Arti return nil } -func (l *LuetInstaller) Uninstall(p []pkg.Package, s *System) error { + +func (l *LuetInstaller) uninstall(p pkg.Package, s *System) error { + files, err := s.Database.GetPackageFiles(p) + if err != nil { + return errors.Wrap(err, "Failed getting installed files") + } + + // Remove from target + for _, f := range files { + target := filepath.Join(s.Target, f) + Info("Removing", target) + err := os.Remove(target) + if err != nil { + Warning("Failed removing", target) + } + } + + err = s.Database.RemovePackage(p) + if err != nil { + return errors.Wrap(err, "Failed removing package from database") + } + + err = s.Database.RemovePackageFiles(p) + if err != nil { + return errors.Wrap(err, "Failed removing package files from database") + } + Info(p.GetFingerPrint(), "Removed") + return nil +} + +func (l *LuetInstaller) Uninstall(p pkg.Package, s *System) error { // compute uninstall from all world - remove packages in parallel - run uninstall finalizer (in order) - mark the uninstallation in db + // Get installed definition + installed, err := s.World() + if err != nil { + return errors.Wrap(err, "Failed generating installed world ") + } + + var selected pkg.Package + for _, i := range installed { + if i.Matches(p) { + selected = i + } + } + if selected == nil { + return errors.Wrap(err, "Package not installed") + } + + solv := solver.NewSolver(installed, installed, pkg.NewInMemoryDatabase(false)) + solution, err := solv.Uninstall(selected) + for _, p := range solution { + Info("Uninstalling", p.GetFingerPrint()) + l.uninstall(p, s) + } return nil } diff --git a/pkg/installer/installer_test.go b/pkg/installer/installer_test.go index 1733907e..06f47ca3 100644 --- a/pkg/installer/installer_test.go +++ b/pkg/installer/installer_test.go @@ -124,6 +124,18 @@ uri: "`+tmpdir+`" files, err := systemDB.GetPackageFiles(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) Expect(files).To(Equal([]string{"artifact42", "test5", "test6"})) Expect(err).ToNot(HaveOccurred()) + + err = inst.Uninstall(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}, system) + Expect(err).ToNot(HaveOccurred()) + + // Nothing should be there anymore (files, packagedb entry) + Expect(helpers.Exists(filepath.Join(fakeroot, "test5"))).ToNot(BeTrue()) + Expect(helpers.Exists(filepath.Join(fakeroot, "test6"))).ToNot(BeTrue()) + + _, err = systemDB.FindPackage(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + Expect(err).To(HaveOccurred()) + _, err = systemDB.GetPackageFiles(&pkg.DefaultPackage{Name: "b", Category: "test", Version: "1.0"}) + Expect(err).To(HaveOccurred()) }) }) diff --git a/pkg/installer/interface.go b/pkg/installer/interface.go index 5531143b..a06becdb 100644 --- a/pkg/installer/interface.go +++ b/pkg/installer/interface.go @@ -24,7 +24,7 @@ import ( type Installer interface { Install([]pkg.Package, *System) error - Uninstall([]pkg.Package, *System) error + Uninstall(pkg.Package, *System) error Repositories([]Repository) } diff --git a/pkg/package/database.go b/pkg/package/database.go index c0f3af1a..af1ccc93 100644 --- a/pkg/package/database.go +++ b/pkg/package/database.go @@ -35,6 +35,7 @@ type PackageSet interface { FindPackage(Package) (Package, error) UpdatePackage(p Package) error GetAllPackages(packages chan Package) error + RemovePackage(Package) error GetPackageFiles(Package) ([]string, error) SetPackageFiles(PackageFile) error diff --git a/pkg/package/database_boltdb.go b/pkg/package/database_boltdb.go index 8e42e93b..3cee5139 100644 --- a/pkg/package/database_boltdb.go +++ b/pkg/package/database_boltdb.go @@ -224,3 +224,16 @@ func (db *BoltDatabase) RemovePackageFiles(p Package) error { } return files.DeleteStruct(&pf) } + +func (db *BoltDatabase) RemovePackage(p Package) error { + bolt, err := storm.Open(db.Path, storm.BoltOptions(0600, &bbolt.Options{Timeout: 30 * time.Second})) + if err != nil { + return errors.Wrap(err, "Error opening boltdb "+db.Path) + } + defer bolt.Close() + p, err = db.FindPackage(p) + if err != nil { + return errors.Wrap(err, "No package found") + } + return bolt.DeleteStruct(p) +} diff --git a/pkg/package/database_mem.go b/pkg/package/database_mem.go index 0e364ea8..de57f3e9 100644 --- a/pkg/package/database_mem.go +++ b/pkg/package/database_mem.go @@ -230,3 +230,19 @@ func (db *InMemoryDatabase) RemovePackageFiles(p Package) error { delete(db.FileDatabase, p.GetFingerPrint()) return nil } + +func (db *InMemoryDatabase) RemovePackage(p Package) error { + for _, k := range db.GetPackages() { + pack, err := db.GetPackage(k) + if err != nil { + return err + } + if pack.Matches(p) { + db.Lock() + delete(db.Database, k) + db.Unlock() + return nil + } + } + return errors.New("Package not found") +}