-- | Require installed packages.
requireInstalled :: (PN -> Bool) -> Tree (QGoalReasons, a) -> Tree (QGoalReasons, a)
requireInstalled p = trav go
  where
    go (PChoiceF v@(Q _ pn) i@(gr, _) cs)
      | p pn      = PChoiceF v i (P.mapWithKey installed cs)
      | otherwise = PChoiceF v i                         cs
      where
        installed (I _ (Inst _)) x = x
        installed _              _ = Fail (toConflictSet (Goal (P v) gr)) CannotInstall
    go x          = x

-- | Avoid reinstalls.
--
-- This is a tricky strategy. If a package version is installed already and the
-- same version is available from a repo, the repo version will never be chosen.
-- This would result in a reinstall (either destructively, or potentially,
-- shadowing). The old instance won't be visible or even present anymore, but
-- other packages might have depended on it.
--
-- TODO: It would be better to actually check the reverse dependencies of installed
-- packages. If they're not depended on, then reinstalling should be fine. Even if
-- they are, perhaps this should just result in trying to reinstall those other
-- packages as well. However, doing this all neatly in one pass would require to
-- change the builder, or at least to change the goal set after building.
requireInstalled :: (PN -> Bool) -> Tree (QGoalReasons, a) -> Tree (QGoalReasons, a)
requireInstalled p = trav go
  where
    go (PChoiceF v@(Q _ pn) i@(gr, _) cs)
      | p pn      = PChoiceF v i (P.mapWithKey installed cs)
      | otherwise = PChoiceF v i                         cs
      where
        installed (I _ (Inst _)) x = x
        installed _              _ = Fail (toConflictSet (Goal (P v) gr)) CannotInstall
    go x          = x

-- | Avoid reinstalls.
--
-- This is a tricky strategy. If a package version is installed already and the
-- same version is available from a repo, the repo version will never be chosen.
-- This would result in a reinstall (either destructively, or potentially,
-- shadowing). The old instance won't be visible or even present anymore, but
-- other packages might have depended on it.
--
-- TODO: It would be better to actually check the reverse dependencies of installed
-- packages. If they're not depended on, then reinstalling should be fine. Even if
-- they are, perhaps this should just result in trying to reinstall those other
-- packages as well. However, doing this all neatly in one pass would require to
-- change the builder, or at least to change the goal set after building.
requireInstalled p = trav go
  where
    go (PChoiceF v@(Q _ pn) i@(gr, _) cs)
      | p pn      = PChoiceF v i (P.mapWithKey installed cs)
      | otherwise = PChoiceF v i                         cs
      where
        installed (I _ (Inst _)) x = x
        installed _              _ = Fail (toConflictSet (Goal (P v) gr)) CannotInstall
    go x          = x

-- | Avoid reinstalls.
--
-- This is a tricky strategy. If a package version is installed already and the
-- same version is available from a repo, the repo version will never be chosen.
-- This would result in a reinstall (either destructively, or potentially,
-- shadowing). The old instance won't be visible or even present anymore, but
-- other packages might have depended on it.
--
-- TODO: It would be better to actually check the reverse dependencies of installed
-- packages. If they're not depended on, then reinstalling should be fine. Even if
-- they are, perhaps this should just result in trying to reinstall those other
-- packages as well. However, doing this all neatly in one pass would require to
-- change the builder, or at least to change the goal set after building.