Skip to content

Commit b0c0c77

Browse files
committed
Render project configs in provenance message
- Use real-life example from Cabal project in doctest
1 parent 47e7295 commit b0c0c77

File tree

8 files changed

+67
-7
lines changed

8 files changed

+67
-7
lines changed

cabal-install-solver/src/Distribution/Solver/Types/ProjectConfigPath.hs

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
{-# LANGUAGE DeriveGeneric #-}
2-
{-# LANGUAGE LambdaCase #-}
32

43
module Distribution.Solver.Types.ProjectConfigPath
54
(
@@ -11,6 +10,7 @@ module Distribution.Solver.Types.ProjectConfigPath
1110

1211
-- * Messages
1312
, docProjectConfigPath
13+
, docProjectConfigPaths
1414
, cyclicalImportMsg
1515
, docProjectConfigPathFailReason
1616

@@ -56,13 +56,51 @@ instance Structured ProjectConfigPath
5656
-- imported by: B.config
5757
-- imported by: A.project
5858
-- @
59-
-- >>> render . docProjectConfigPath $ ProjectConfigPath $ "D.config" :| ["C.config", "B.config", "A.project" ]
59+
-- >>> render . docProjectConfigPath $ ProjectConfigPath $ "D.config" :| ["C.config", "B.config", "A.project"]
6060
-- "D.config\n imported by: C.config\n imported by: B.config\n imported by: A.project"
6161
docProjectConfigPath :: ProjectConfigPath -> Doc
6262
docProjectConfigPath (ProjectConfigPath (p :| [])) = text p
6363
docProjectConfigPath (ProjectConfigPath (p :| ps)) = vcat $
6464
text p : [ text " " <+> text "imported by:" <+> text l | l <- ps ]
6565

66+
-- | Renders the paths as a list without showing which path imports another,
67+
-- like this;
68+
-- @
69+
-- - cabal.project
70+
-- - project-cabal/constraints.config
71+
-- - project-cabal/ghc-latest.config
72+
-- - project-cabal/ghc-options.config
73+
-- - project-cabal/pkgs.config
74+
-- - project-cabal/pkgs/benchmarks.config
75+
-- - project-cabal/pkgs/buildinfo.config
76+
-- - project-cabal/pkgs/cabal.config
77+
-- - project-cabal/pkgs/install.config
78+
-- - project-cabal/pkgs/integration-tests.config
79+
-- - project-cabal/pkgs/tests.config
80+
-- @
81+
--
82+
-- >>> :{
83+
-- do
84+
-- let ps =
85+
-- [ ProjectConfigPath ("cabal.project" :| [])
86+
-- , ProjectConfigPath ("project-cabal/constraints.config" :| ["cabal.project"])
87+
-- , ProjectConfigPath ("project-cabal/ghc-latest.config" :| ["cabal.project"])
88+
-- , ProjectConfigPath ("project-cabal/ghc-options.config" :| ["cabal.project"])
89+
-- , ProjectConfigPath ("project-cabal/pkgs.config" :| ["cabal.project"])
90+
-- , ProjectConfigPath ("project-cabal/pkgs/benchmarks.config" :| ["project-cabal/pkgs.config","cabal.project"])
91+
-- , ProjectConfigPath ("project-cabal/pkgs/buildinfo.config" :| ["project-cabal/pkgs.config","cabal.project"])
92+
-- , ProjectConfigPath ("project-cabal/pkgs/cabal.config" :| ["project-cabal/pkgs.config","cabal.project"])
93+
-- , ProjectConfigPath ("project-cabal/pkgs/install.config" :| ["project-cabal/pkgs.config","cabal.project"])
94+
-- , ProjectConfigPath ("project-cabal/pkgs/integration-tests.config" :| ["project-cabal/pkgs.config","cabal.project"])
95+
-- , ProjectConfigPath ("project-cabal/pkgs/tests.config" :| ["project-cabal/pkgs.config","cabal.project"])
96+
-- ]
97+
-- return . render $ docProjectConfigPaths ps
98+
-- :}
99+
-- "- cabal.project\n- project-cabal/constraints.config\n- project-cabal/ghc-latest.config\n- project-cabal/ghc-options.config\n- project-cabal/pkgs.config\n- project-cabal/pkgs/benchmarks.config\n- project-cabal/pkgs/buildinfo.config\n- project-cabal/pkgs/cabal.config\n- project-cabal/pkgs/install.config\n- project-cabal/pkgs/integration-tests.config\n- project-cabal/pkgs/tests.config"
100+
docProjectConfigPaths :: [ProjectConfigPath] -> Doc
101+
docProjectConfigPaths ps = vcat
102+
[ text "-" <+> text p | ProjectConfigPath (p :| _) <- ps ]
103+
66104
-- | A message for a cyclical import, assuming the head of the path is the
67105
-- duplicate.
68106
cyclicalImportMsg :: ProjectConfigPath -> Doc

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ module Distribution.Client.ProjectConfig
5858
) where
5959

6060
import Distribution.Client.Compat.Prelude
61-
import Text.PrettyPrint (render)
61+
import Text.PrettyPrint (nest, render, text, vcat)
6262
import Prelude ()
6363

6464
import Distribution.Client.Glob
@@ -882,10 +882,10 @@ renderBadPackageLocations (BadPackageLocations provenance bpls)
882882
renderErrors f = unlines (map f bpls)
883883

884884
renderExplicit =
885-
"When using configuration(s) from "
886-
++ intercalate ", " (render . docProjectConfigPath <$> mapMaybe getExplicit (Set.toList provenance))
887-
++ ", the following errors occurred:\n"
888-
++ renderErrors renderBadPackageLocation
885+
"When using configuration from:\n"
886+
++ render (nest 2 . docProjectConfigPaths $ mapMaybe getExplicit (Set.toList provenance))
887+
++ "\nThe following errors occurred:\n"
888+
++ render (nest 2 $ vcat ((text "-" <+>) . text <$> map renderBadPackageLocation bpls))
889889

890890
getExplicit (Explicit path) = Just path
891891
getExplicit Implicit = Nothing
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import: missing/pkgs.config

cabal-testsuite/PackageTests/ConditionalAndImport/cabal.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,5 @@ After searching the rest of the dependency tree exhaustively, these were the goa
129129
Error: [Cabal-7090]
130130
Error parsing project file <ROOT>/bad-conditional.project:
131131
Cannot set compiler in a conditional clause of a cabal project file
132+
# checking that missing package message lists configuration provenance
133+
# cabal v2-build

cabal-testsuite/PackageTests/ConditionalAndImport/cabal.test.hs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,4 +226,15 @@ main = cabalTest . withRepo "repo" . recordMode RecordMarked $ do
226226
badIf <- fails $ cabal' "v2-build" [ "--project-file=bad-conditional.project" ]
227227
assertOutputContains "Cannot set compiler in a conditional clause of a cabal project file" badIf
228228

229+
log "checking that missing package message lists configuration provenance"
230+
missing <- fails $ cabal' "v2-build" [ "--project-file=cabal-missing-package.project" ]
231+
assertOutputContains
232+
"When using configuration from: \
233+
\ - cabal-missing-package.project \
234+
\ - missing/pkgs.config \
235+
\ - missing/pkgs/default.config \
236+
\The following errors occurred: \
237+
\ - The package location 'pkg-doesnt-exist' does not exist."
238+
missing
239+
229240
return ()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import: pkgs/default.config
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
packages: pkg-doesnt-exist

changelog.d/issue-9971

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
synopsis: Renders project configuration provenance as a list of canonical paths
2+
packages: cabal-install cabal-install-solver
3+
prs: #9985
4+
issues: #9971
5+
6+
description: Removes interleaved rendering of project imports.

0 commit comments

Comments
 (0)