Skip to content

Commit 65a4fb1

Browse files
committed
refactor(Cabal-syntax): Improve Graph.broken
If a node has dangling edges, then the list of missing neighbours cannot be empty.
1 parent eab5a10 commit 65a4fb1

File tree

7 files changed

+35
-27
lines changed

7 files changed

+35
-27
lines changed

Cabal-syntax/src/Distribution/Compat/Graph.hs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,10 @@ import Distribution.Utils.Structured (Structure (..), Structured (..))
100100
import qualified Data.Array as Array
101101
import qualified Data.Foldable as Foldable
102102
import qualified Data.Graph as G
103+
import qualified Data.List.NonEmpty as NE
103104
import qualified Data.Map.Strict as Map
104105
import qualified Data.Set as Set
105106
import qualified Data.Tree as Tree
106-
import qualified Distribution.Compat.Prelude as Prelude
107107
import GHC.Stack (HasCallStack)
108108

109109
-- | A graph of nodes @a@. The nodes are expected to have instance
@@ -115,7 +115,7 @@ data Graph a = Graph
115115
, graphAdjoint :: G.Graph
116116
, graphVertexToNode :: G.Vertex -> a
117117
, graphKeyToVertex :: Key a -> Maybe G.Vertex
118-
, graphBroken :: [(a, [Key a])]
118+
, graphBroken :: [(a, NonEmpty (Key a))]
119119
}
120120

121121
-- NB: Not a Functor! (or Traversable), because you need
@@ -285,7 +285,7 @@ cycles g = [vs | CyclicSCC vs <- stronglyConnComp g]
285285
-- | /O(1)/. Return a list of nodes paired with their broken
286286
-- neighbors (i.e., neighbor keys which are not in the graph).
287287
-- Requires amortized construction of graph.
288-
broken :: Graph a -> [(a, [Key a])]
288+
broken :: Graph a -> [(a, NonEmpty (Key a))]
289289
broken g = graphBroken g
290290

291291
-- | Lookup the immediate neighbors from a key in the graph.
@@ -344,7 +344,7 @@ revTopSort g = map (graphVertexToNode g) $ G.topSort (graphAdjoint g)
344344
-- if you can't fulfill this invariant use @'fromList' ('Data.Map.elems' m)@
345345
-- instead. The values of the map are assumed to already
346346
-- be in WHNF.
347-
fromMap :: IsNode a => Map (Key a) a -> Graph a
347+
fromMap :: forall a. (IsNode a, Eq (Key a)) => Map (Key a) a -> Graph a
348348
fromMap m =
349349
Graph
350350
{ graphMap = m
@@ -353,17 +353,26 @@ fromMap m =
353353
, graphAdjoint = G.transposeG g
354354
, graphVertexToNode = vertex_to_node
355355
, graphKeyToVertex = key_to_vertex
356-
, graphBroken = broke
356+
, graphBroken =
357+
map (\ns'' -> (fst (NE.head ns''), NE.map snd ns'')) $
358+
NE.groupWith (nodeKey . fst) $
359+
brokenEdges'
357360
}
358361
where
359-
try_key_to_vertex k = maybe (Left k) Right (key_to_vertex k)
362+
brokenEdges' :: [(a, Key a)]
363+
brokenEdges' = concat brokenEdges
360364

365+
brokenEdges :: [[(a, Key a)]]
361366
(brokenEdges, edges) =
362-
unzip $
363-
[ partitionEithers (map try_key_to_vertex (nodeNeighbors n))
367+
unzip
368+
[ partitionEithers
369+
[ case key_to_vertex n' of
370+
Just v -> Right v
371+
Nothing -> Left (n, n')
372+
| n' <- nodeNeighbors n
373+
]
364374
| n <- ns
365375
]
366-
broke = filter (not . Prelude.null . snd) (zip ns brokenEdges)
367376

368377
g = Array.listArray bounds edges
369378

Cabal/src/Distribution/Backpack/Configure.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,14 +283,14 @@ toComponentLocalBuildInfos
283283
[ "installed package "
284284
++ prettyShow (packageId pkg)
285285
++ " is broken due to missing package "
286-
++ intercalate ", " (map prettyShow deps)
286+
++ intercalate ", " (map prettyShow $ toList deps)
287287
| (Left pkg, deps) <- broken
288288
]
289289
++ unlines
290290
[ "planned package "
291291
++ prettyShow (packageId pkg)
292292
++ " is broken due to missing package "
293-
++ intercalate ", " (map prettyShow deps)
293+
++ intercalate ", " (map prettyShow $ toList deps)
294294
| (Right pkg, deps) <- broken
295295
]
296296

cabal-install/src/Distribution/Client/CmdErrorMessages.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ renderCannotPruneDependencies (CannotPruneDependencies brokenPackages) =
501501
where
502502
-- throw away the details and just list the deps that are needed
503503
pkgids :: [PackageId]
504-
pkgids = nub . map packageId . concatMap snd $ brokenPackages
504+
pkgids = nub . map packageId . concatMap (NE.toList . snd) $ brokenPackages
505505

506506
{-
507507
++ "Syntax:\n"

cabal-install/src/Distribution/Client/Install.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,7 @@ pruneInstallPlan pkgSpecifiers =
715715
nub
716716
[ depid
717717
| SolverInstallPlan.PackageMissingDeps _ depids <- problems
718-
, depid <- depids
718+
, depid <- toList depids
719719
, packageName depid `elem` targetnames
720720
]
721721

cabal-install/src/Distribution/Client/InstallPlan.hs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1048,7 +1048,7 @@ data PlanProblem ipkg srcpkg
10481048
= PackageMissingDeps
10491049
(GenericPlanPackage ipkg srcpkg)
10501050
-- ^ The package that is missing dependencies
1051-
[GraphKey ipkg srcpkg]
1051+
(NonEmpty (GraphKey ipkg srcpkg))
10521052
-- ^ The missing dependencies
10531053
| -- | The packages involved in a dependency cycle
10541054
PackageCycle
@@ -1079,7 +1079,7 @@ renderPlanProblem (PackageMissingDeps pkg missingDeps) =
10791079
[ text "Package"
10801080
, pretty (nodeKey pkg)
10811081
, text "depends on the following packages which are missing from the plan:"
1082-
, fsep (punctuate comma (map pretty missingDeps))
1082+
, fsep (punctuate comma (map pretty $ NE.toList missingDeps))
10831083
]
10841084
renderPlanProblem (PackageCycle cycleGroup) =
10851085
fsep
@@ -1121,10 +1121,7 @@ checkForMissingDeps
11211121
checkForMissingDeps graph =
11221122
[ PackageMissingDeps
11231123
pkg
1124-
( mapMaybe
1125-
(fmap nodeKey . flip Graph.lookup graph)
1126-
missingDeps
1127-
)
1124+
missingDeps
11281125
| (pkg, missingDeps) <- Graph.broken graph
11291126
]
11301127

cabal-install/src/Distribution/Client/ProjectPlanning.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3907,7 +3907,7 @@ pruneInstallPlanToDependencies pkgTargets installPlan =
39073907
CannotPruneDependencies
39083908
[ (pkg, missingDeps)
39093909
| (pkg, missingDepIds) <- brokenPackages
3910-
, let missingDeps = mapMaybe lookupDep missingDepIds
3910+
, let missingDeps = NE.map (fromMaybe (error "should not happen") . lookupDep) missingDepIds
39113911
]
39123912
where
39133913
-- lookup in the original unpruned graph
@@ -3922,7 +3922,7 @@ pruneInstallPlanToDependencies pkgTargets installPlan =
39223922
newtype CannotPruneDependencies
39233923
= CannotPruneDependencies
39243924
[ ( ElaboratedPlanPackage
3925-
, [ElaboratedPlanPackage]
3925+
, NonEmpty ElaboratedPlanPackage
39263926
)
39273927
]
39283928
deriving (Show)

cabal-install/src/Distribution/Client/SolverInstallPlan.hs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ import Distribution.Solver.Types.SolverPackage
7373
import Data.Array ((!))
7474
import qualified Data.Foldable as Foldable
7575
import qualified Data.Graph as OldGraph
76+
import qualified Data.List.NonEmpty as NE
7677
import qualified Data.Map as Map
7778
import Distribution.Compat.Graph (Graph, IsNode (..))
7879
import qualified Distribution.Compat.Graph as Graph
@@ -171,7 +172,7 @@ valid = null . problems
171172
data SolverPlanProblem
172173
= PackageMissingDeps
173174
SolverPlanPackage
174-
[PackageIdentifier]
175+
(NE.NonEmpty PackageIdentifier)
175176
| PackageCycle [SolverPlanPackage]
176177
| PackageInconsistency QPN [(SolverId, SolverId)]
177178
| PackageStateInvalid SolverPlanPackage SolverPlanPackage
@@ -181,7 +182,7 @@ showPlanProblem (PackageMissingDeps pkg missingDeps) =
181182
"Package "
182183
++ prettyShow (packageId pkg)
183184
++ " depends on the following packages which are missing from the plan: "
184-
++ intercalate ", " (map prettyShow missingDeps)
185+
++ intercalate ", " (map prettyShow (NE.toList missingDeps))
185186
showPlanProblem (PackageCycle cycleGroup) =
186187
"The following packages are involved in a dependency cycle "
187188
++ intercalate ", " (map (prettyShow . packageId) cycleGroup)
@@ -220,10 +221,11 @@ problems
220221
problems index =
221222
[ PackageMissingDeps
222223
pkg
223-
( mapMaybe
224-
(fmap packageId . flip Graph.lookup index)
225-
missingDeps
226-
)
224+
-- ( mapMaybe
225+
-- (fmap packageId . flip Graph.lookup index)
226+
-- missingDeps
227+
-- )
228+
(NE.map (packageId . fromMaybe (error "should not happen") . flip Graph.lookup index) missingDeps)
227229
| (pkg, missingDeps) <- Graph.broken index
228230
]
229231
++ [ PackageCycle cycleGroup

0 commit comments

Comments
 (0)