2023-11-28 22:51:51 +00:00
|
|
|
package cwhub
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"slices"
|
|
|
|
)
|
|
|
|
|
|
|
|
// purge removes the actual config file that was downloaded.
|
|
|
|
func (i *Item) purge() (bool, error) {
|
|
|
|
if !i.State.Downloaded {
|
2023-12-19 16:20:09 +00:00
|
|
|
i.hub.logger.Debugf("removing %s: not downloaded -- no need to remove", i.Name)
|
2023-11-28 22:51:51 +00:00
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
src, err := i.downloadPath()
|
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := os.Remove(src); err != nil {
|
|
|
|
if os.IsNotExist(err) {
|
2023-12-19 16:20:09 +00:00
|
|
|
i.hub.logger.Debugf("%s doesn't exist, no need to remove", src)
|
2023-11-28 22:51:51 +00:00
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return false, fmt.Errorf("while removing file: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
i.State.Downloaded = false
|
2023-12-19 16:20:09 +00:00
|
|
|
i.hub.logger.Infof("Removed source file [%s]: %s", i.Name, src)
|
2023-11-28 22:51:51 +00:00
|
|
|
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// disable removes the install link, and optionally the downloaded content.
|
|
|
|
func (i *Item) disable(purge bool, force bool) (bool, error) {
|
|
|
|
didRemove := true
|
|
|
|
|
|
|
|
err := i.removeInstallLink()
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
if !purge && !force {
|
|
|
|
link, _ := i.installPath()
|
|
|
|
return false, fmt.Errorf("link %s does not exist (override with --force or --purge)", link)
|
|
|
|
}
|
2023-12-15 14:27:22 +00:00
|
|
|
|
2023-11-28 22:51:51 +00:00
|
|
|
didRemove = false
|
|
|
|
} else if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
i.State.Installed = false
|
|
|
|
didPurge := false
|
2023-12-15 14:27:22 +00:00
|
|
|
|
2023-11-28 22:51:51 +00:00
|
|
|
if purge {
|
|
|
|
if didPurge, err = i.purge(); err != nil {
|
|
|
|
return didRemove, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret := didRemove || didPurge
|
|
|
|
|
|
|
|
return ret, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove disables the item, optionally removing the downloaded content.
|
|
|
|
func (i *Item) Remove(purge bool, force bool) (bool, error) {
|
2023-12-05 12:38:52 +00:00
|
|
|
if i.State.IsLocal() {
|
2023-12-19 16:20:09 +00:00
|
|
|
i.hub.logger.Warningf("%s is a local item, please delete manually", i.Name)
|
2023-11-28 22:51:51 +00:00
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if i.State.Tainted && !force {
|
|
|
|
return false, fmt.Errorf("%s is tainted, use '--force' to remove", i.Name)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !i.State.Installed && !purge {
|
2023-12-19 16:20:09 +00:00
|
|
|
i.hub.logger.Infof("removing %s: not installed -- no need to remove", i.Name)
|
2023-11-28 22:51:51 +00:00
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
removed := false
|
|
|
|
|
|
|
|
descendants, err := i.descendants()
|
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
|
|
|
|
ancestors := i.Ancestors()
|
|
|
|
|
|
|
|
for _, sub := range i.SubItems() {
|
|
|
|
if !sub.State.Installed {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// if the sub depends on a collection that is not a direct or indirect dependency
|
|
|
|
// of the current item, it is not removed
|
|
|
|
for _, subParent := range sub.Ancestors() {
|
|
|
|
if !purge && !subParent.State.Installed {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// the ancestor that would block the removal of the sub item is also an ancestor
|
|
|
|
// of the item we are removing, so we don't want false warnings
|
|
|
|
// (e.g. crowdsecurity/sshd-logs was not removed because it also belongs to crowdsecurity/linux,
|
|
|
|
// while we are removing crowdsecurity/sshd)
|
|
|
|
if slices.Contains(ancestors, subParent) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// the sub-item belongs to the item we are removing, but we already knew that
|
|
|
|
if subParent == i {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if !slices.Contains(descendants, subParent) {
|
2023-12-19 16:20:09 +00:00
|
|
|
i.hub.logger.Infof("%s was not removed because it also belongs to %s", sub.Name, subParent.Name)
|
2023-11-28 22:51:51 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
subRemoved, err := sub.Remove(purge, force)
|
|
|
|
if err != nil {
|
|
|
|
return false, fmt.Errorf("unable to disable %s: %w", i.Name, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
removed = removed || subRemoved
|
|
|
|
}
|
|
|
|
|
|
|
|
didDisable, err := i.disable(purge, force)
|
|
|
|
if err != nil {
|
|
|
|
return false, fmt.Errorf("while removing %s: %w", i.Name, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
removed = removed || didDisable
|
|
|
|
|
|
|
|
return removed, nil
|
|
|
|
}
|