diff --git a/cabal-install/Distribution/Client/InstallPlan.hs b/cabal-install/Distribution/Client/InstallPlan.hs
index bbfaaab5e4570ee5191c59e8c79ee8896d6c8291..9db8d97bf6b1261708a63af5823261f80fead9af 100644
--- a/cabal-install/Distribution/Client/InstallPlan.hs
+++ b/cabal-install/Distribution/Client/InstallPlan.hs
@@ -30,6 +30,9 @@ module Distribution.Client.InstallPlan (
   configureInstallPlan,
   remove,
   preexisting,
+  lookup,
+  directDeps,
+  revDirectDeps,
 
   -- * Traversal
   executionOrder,
@@ -49,6 +52,7 @@ module Distribution.Client.InstallPlan (
 
   -- * Graph-like operations
   reverseTopologicalOrder,
+  reverseDependencyClosure,
   ) where
 
 import Distribution.Client.Types hiding (BuildResults)
@@ -92,6 +96,8 @@ import           Data.Map (Map)
 import qualified Data.Set as Set
 import           Data.Set (Set)
 
+import Prelude hiding (lookup)
+
 
 -- When cabal tries to install a number of packages, including all their
 -- dependencies it has a non-trivial problem to solve.
@@ -299,6 +305,39 @@ preexisting pkgid ipkg plan = assert (invariant plan') plan'
                   $ planIndex plan
     }
 
+-- | Lookup a package in the plan.
+--
+lookup :: (HasUnitId ipkg,   PackageFixedDeps ipkg,
+           HasUnitId srcpkg, PackageFixedDeps srcpkg)
+       => GenericInstallPlan ipkg srcpkg
+       -> UnitId
+       -> Maybe (GenericPlanPackage ipkg srcpkg)
+lookup plan pkgid = Graph.lookup pkgid (planIndex plan)
+
+-- | Find all the direct depencencies of the given package.
+--
+-- Note that the package must exist in the plan or it is an error.
+--
+directDeps :: GenericInstallPlan ipkg srcpkg
+           -> UnitId
+           -> [GenericPlanPackage ipkg srcpkg]
+directDeps plan pkgid =
+  case Graph.neighbors (planIndex plan) pkgid of
+    Just deps -> deps
+    Nothing   -> internalError "directDeps: package not in graph"
+
+-- | Find all the direct reverse depencencies of the given package.
+--
+-- Note that the package must exist in the plan or it is an error.
+--
+revDirectDeps :: GenericInstallPlan ipkg srcpkg
+              -> UnitId
+              -> [GenericPlanPackage ipkg srcpkg]
+revDirectDeps plan pkgid =
+  case Graph.revNeighbors (planIndex plan) pkgid of
+    Just deps -> deps
+    Nothing   -> internalError "revDirectDeps: package not in graph"
+
 
 -- ------------------------------------------------------------
 -- * Checking validity of plans
@@ -381,6 +420,16 @@ reverseTopologicalOrder :: GenericInstallPlan ipkg srcpkg
 reverseTopologicalOrder plan = Graph.revTopSort (planIndex plan)
 
 
+-- | Return the packages in the plan that depend directly or indirectly on the
+-- given packages.
+--
+reverseDependencyClosure :: GenericInstallPlan ipkg srcpkg
+                         -> [UnitId]
+                         -> [GenericPlanPackage ipkg srcpkg]
+reverseDependencyClosure plan = fromMaybe []
+                              . Graph.revClosure (planIndex plan)
+
+
 fromSolverInstallPlan ::
       (HasUnitId ipkg,   PackageFixedDeps ipkg,
        HasUnitId srcpkg, PackageFixedDeps srcpkg)
@@ -591,21 +640,6 @@ failed plan (Processing processingSet completedSet failedSet) pkgid =
     asConfiguredPackage (Configured pkg) = pkg
     asConfiguredPackage _ = internalError "not in configured state"
 
-directDeps, revDirectDeps
-  :: GenericInstallPlan ipkg srcpkg
-  -> UnitId
-  -> [GenericPlanPackage ipkg srcpkg]
-
-directDeps plan pkgid =
-  case Graph.neighbors (planIndex plan) pkgid of
-    Just deps -> deps
-    Nothing   -> internalError "directDeps: package not in graph"
-
-revDirectDeps plan pkgid =
-  case Graph.revNeighbors (planIndex plan) pkgid of
-    Just deps -> deps
-    Nothing   -> internalError "directDeps: package not in graph"
-
 processingInvariant :: (HasUnitId ipkg,   PackageFixedDeps ipkg,
                         HasUnitId srcpkg, PackageFixedDeps srcpkg)
                     => GenericInstallPlan ipkg srcpkg