From 124d47163bde123c66543e78327f7c1c5aaa27fd Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Mon, 11 Nov 2024 07:45:55 -0500 Subject: [PATCH 1/2] Add Ord instance for ProjectConfigPath - Consider URI in Ord instance - Use <> in Ord instance of ProjectConfigPath - Add unconsProjectConfigPath - Add docProjectConfigFiles - Remove docProjectConfigPaths - Clarify sorting haddocks for Ord ProjectConfigPath --- .../Solver/Types/ProjectConfigPath.hs | 61 ++++++++++++++++--- .../src/Distribution/Client/ProjectConfig.hs | 2 +- changelog.d/pr-10546 | 9 +++ 3 files changed, 62 insertions(+), 10 deletions(-) create mode 100644 changelog.d/pr-10546 diff --git a/cabal-install-solver/src/Distribution/Solver/Types/ProjectConfigPath.hs b/cabal-install-solver/src/Distribution/Solver/Types/ProjectConfigPath.hs index bb1a81bc1b5..84375b0f4de 100644 --- a/cabal-install-solver/src/Distribution/Solver/Types/ProjectConfigPath.hs +++ b/cabal-install-solver/src/Distribution/Solver/Types/ProjectConfigPath.hs @@ -1,4 +1,5 @@ {-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE ViewPatterns #-} module Distribution.Solver.Types.ProjectConfigPath ( @@ -7,10 +8,11 @@ module Distribution.Solver.Types.ProjectConfigPath , projectConfigPathRoot , nullProjectConfigPath , consProjectConfigPath + , unconsProjectConfigPath -- * Messages , docProjectConfigPath - , docProjectConfigPaths + , docProjectConfigFiles , cyclicalImportMsg , docProjectConfigPathFailReason @@ -21,17 +23,19 @@ module Distribution.Solver.Types.ProjectConfigPath ) where import Distribution.Solver.Compat.Prelude hiding (toList, (<>)) +import qualified Distribution.Solver.Compat.Prelude as P ((<>)) import Prelude (sequence) import Data.Coerce (coerce) import Data.List.NonEmpty ((<|)) -import Network.URI (parseURI) +import Network.URI (parseURI, parseAbsoluteURI) import System.Directory import System.FilePath import qualified Data.List.NonEmpty as NE import Distribution.Solver.Modular.Version (VR) import Distribution.Pretty (prettyShow) import Text.PrettyPrint +import Distribution.Simple.Utils (ordNub) -- | Path to a configuration file, either a singleton project root, or a longer -- list representing a path to an import. The path is a non-empty list that we @@ -45,7 +49,41 @@ import Text.PrettyPrint -- List elements are relative to each other but once canonicalized, elements are -- relative to the directory of the project root. newtype ProjectConfigPath = ProjectConfigPath (NonEmpty FilePath) - deriving (Eq, Ord, Show, Generic) + deriving (Eq, Show, Generic) + +-- | Sorts URIs after local file paths and longer file paths after shorter ones +-- as measured by the number of path segments. If still equal, then sorting is +-- lexical. +-- +-- The project itself, a single element root path, compared to any of the +-- configuration paths it imports, should always sort first. Comparing one +-- project root path against another is done lexically. +instance Ord ProjectConfigPath where + compare pa@(ProjectConfigPath (NE.toList -> as)) pb@(ProjectConfigPath (NE.toList -> bs)) = + case (as, bs) of + -- There should only ever be one root project path, only one path + -- with length 1. Comparing it to itself should be EQ. Don't assume + -- this though, do a comparison anyway when both sides have length + -- 1. The root path, the project itself, should always be the first + -- path in a sorted listing. + ([a], [b]) -> compare a b + ([_], _) -> LT + (_, [_]) -> GT + + (a:_, b:_) -> case (parseAbsoluteURI a, parseAbsoluteURI b) of + (Just ua, Just ub) -> compare ua ub P.<> compare aImporters bImporters + (Just _, Nothing) -> GT + (Nothing, Just _) -> LT + (Nothing, Nothing) -> compare (splitPath a) (splitPath b) P.<> compare aImporters bImporters + _ -> + compare (length as) (length bs) + P.<> compare (length aPaths) (length bPaths) + P.<> compare aPaths bPaths + where + aPaths = splitPath <$> as + bPaths = splitPath <$> bs + aImporters = snd $ unconsProjectConfigPath pa + bImporters = snd $ unconsProjectConfigPath pb instance Binary ProjectConfigPath instance Structured ProjectConfigPath @@ -95,15 +133,16 @@ docProjectConfigPath (ProjectConfigPath (p :| ps)) = vcat $ -- , ProjectConfigPath ("project-cabal/pkgs/integration-tests.config" :| ["project-cabal/pkgs.config","cabal.project"]) -- , ProjectConfigPath ("project-cabal/pkgs/tests.config" :| ["project-cabal/pkgs.config","cabal.project"]) -- ] --- return . render $ docProjectConfigPaths ps +-- return . render $ docProjectConfigFiles ps -- :} -- "- 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" -docProjectConfigPaths :: [ProjectConfigPath] -> Doc -docProjectConfigPaths ps = vcat - [ text "-" <+> text p | ProjectConfigPath (p :| _) <- ps ] +docProjectConfigFiles :: [ProjectConfigPath] -> Doc +docProjectConfigFiles ps = vcat + [ text "-" <+> text p + | p <- ordNub [ p | ProjectConfigPath (p :| _) <- ps ] + ] --- | A message for a cyclical import, assuming the head of the path is the --- duplicate. +-- | A message for a cyclical import, a "cyclical import of". cyclicalImportMsg :: ProjectConfigPath -> Doc cyclicalImportMsg path@(ProjectConfigPath (duplicate :| _)) = vcat @@ -148,6 +187,10 @@ isTopLevelConfigPath (ProjectConfigPath p) = NE.length p == 1 consProjectConfigPath :: FilePath -> ProjectConfigPath -> ProjectConfigPath consProjectConfigPath p ps = ProjectConfigPath (p <| coerce ps) +-- | Split the path into the importee and the importer path. +unconsProjectConfigPath :: ProjectConfigPath -> (FilePath, Maybe ProjectConfigPath) +unconsProjectConfigPath ps = fmap ProjectConfigPath <$> NE.uncons (coerce ps) + -- | Make paths relative to the directory of the root of the project, not -- relative to the file they were imported from. makeRelativeConfigPath :: FilePath -> ProjectConfigPath -> ProjectConfigPath diff --git a/cabal-install/src/Distribution/Client/ProjectConfig.hs b/cabal-install/src/Distribution/Client/ProjectConfig.hs index eea6b958b70..5f31dc0fab5 100644 --- a/cabal-install/src/Distribution/Client/ProjectConfig.hs +++ b/cabal-install/src/Distribution/Client/ProjectConfig.hs @@ -951,7 +951,7 @@ renderBadPackageLocations (BadPackageLocations provenance bpls) renderExplicit = "When using configuration from:\n" - ++ render (nest 2 . docProjectConfigPaths $ mapMaybe getExplicit (Set.toList provenance)) + ++ render (nest 2 . docProjectConfigFiles $ mapMaybe getExplicit (Set.toList provenance)) ++ "\nThe following errors occurred:\n" ++ render (nest 2 $ vcat ((text "-" <+>) . text <$> map renderBadPackageLocation bpls)) diff --git a/changelog.d/pr-10546 b/changelog.d/pr-10546 new file mode 100644 index 00000000000..1851e21c0e4 --- /dev/null +++ b/changelog.d/pr-10546 @@ -0,0 +1,9 @@ +--- +synopsis: Add an Ord instance for ProjectConfigPath +packages: [cabal-install-solver] +prs: 10546 +--- + +Add an `Ord` instance for `ProjectConfigPath` that sorts URIs after local paths +and longer paths after shorter ones. Deduplicate the printing of "Configuration is +affected by the following files" messages. From 73a13f125a1c93b1e1500346713f69152ce4993a Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Mon, 9 Dec 2024 19:51:54 -0500 Subject: [PATCH 2/2] Add test projects - Add woops test - Regen expected output without duplication - Add "when using config from" tests - Remove unnecessary normalizeWindowsOutput - Change assertion message - Match on (\n|\r\n) for line endings - Note /tmp/cabal-testsuite-*/ not seen on Windows - Always have the project itself sort first - Use with-ghc.config with woops project - Remove docProjectConfigPaths - docProjectConfigFiles is the better name when not reporting "imported by" - Use --dry-run for config listing tests - Only use woops project once in tests - Don't use same project twice in tests - Put dedup test into its own folder - Simplify the project file names - Can be done now that the test is in its own folder - Move using config dedup test to ProjectImport dir - Remove an additional test on yops project - checking "using config from message" without URI imports - Add simple test for changelog - Better explain the message changes - Redo the test so the project doesn't sort 1st - Don't need to specify default project explicitly - Add a z-empty.config lexically sorted last --- .../ConditionalAndImport/cabal.out | 4 +- .../ConditionalAndImport/with-ghc.config | 7 ++ .../DedupUsingConfigFromComplex/0.config | 7 ++ .../DedupUsingConfigFromComplex/2.config | 2 + .../DedupUsingConfigFromComplex/4.config | 2 + .../DedupUsingConfigFromComplex/6.config | 2 + .../DedupUsingConfigFromComplex/8.config | 2 + .../DedupUsingConfigFromComplex/cabal.out | 3 + .../DedupUsingConfigFromComplex/cabal.test.hs | 42 ++++++++++ .../DedupUsingConfigFromComplex/cfg/1.config | 2 + .../DedupUsingConfigFromComplex/cfg/3.config | 2 + .../DedupUsingConfigFromComplex/cfg/5.config | 2 + .../DedupUsingConfigFromComplex/cfg/7.config | 2 + .../DedupUsingConfigFromComplex/cfg/9.config | 2 + .../no-pkg-1/README.md | 2 + .../no-pkg-3/README.md | 2 + .../no-pkgs.project | 7 ++ .../with-ghc.config | 7 ++ .../a-very-extra.config | 2 + .../an-extra.config | 2 + .../DedupUsingConfigFromSimple/cabal.out | 1 + .../DedupUsingConfigFromSimple/cabal.project | 9 +++ .../DedupUsingConfigFromSimple/cabal.test.hs | 24 ++++++ .../with-ghc.config | 7 ++ .../DedupUsingConfigFromSimple/z-empty.config | 1 + changelog.d/pr-10546 | 81 ++++++++++++++++++- 26 files changed, 220 insertions(+), 6 deletions(-) create mode 100644 cabal-testsuite/PackageTests/ConditionalAndImport/with-ghc.config create mode 100644 cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/0.config create mode 100644 cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/2.config create mode 100644 cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/4.config create mode 100644 cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/6.config create mode 100644 cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/8.config create mode 100644 cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cabal.out create mode 100644 cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cabal.test.hs create mode 100644 cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cfg/1.config create mode 100644 cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cfg/3.config create mode 100644 cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cfg/5.config create mode 100644 cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cfg/7.config create mode 100644 cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cfg/9.config create mode 100644 cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/no-pkg-1/README.md create mode 100644 cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/no-pkg-3/README.md create mode 100644 cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/no-pkgs.project create mode 100644 cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/with-ghc.config create mode 100644 cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/a-very-extra.config create mode 100644 cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/an-extra.config create mode 100644 cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/cabal.out create mode 100644 cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/cabal.project create mode 100644 cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/cabal.test.hs create mode 100644 cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/with-ghc.config create mode 100644 cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/z-empty.config diff --git a/cabal-testsuite/PackageTests/ConditionalAndImport/cabal.out b/cabal-testsuite/PackageTests/ConditionalAndImport/cabal.out index c2690ee4366..fd408a95505 100644 --- a/cabal-testsuite/PackageTests/ConditionalAndImport/cabal.out +++ b/cabal-testsuite/PackageTests/ConditionalAndImport/cabal.out @@ -67,9 +67,9 @@ cyclical import of cyclical-2-out-out-self-b.config; # checking that cyclical check doesn't false-positive on same file names in different folders; hoping within a folder and then into a subfolder # cabal v2-build Configuration is affected by the following files: +- noncyclical-same-filename-a.project - noncyclical-same-filename-a.config imported by: noncyclical-same-filename-a.project -- noncyclical-same-filename-a.project - same-filename/noncyclical-same-filename-a.config imported by: noncyclical-same-filename-a.config imported by: noncyclical-same-filename-a.project @@ -83,10 +83,10 @@ Building library for my-0.1... # checking that cyclical check doesn't false-positive on same file names in different folders; hoping into a subfolder and then back out again # cabal v2-build Configuration is affected by the following files: +- noncyclical-same-filename-b.project - noncyclical-same-filename-b.config imported by: same-filename/noncyclical-same-filename-b.config imported by: noncyclical-same-filename-b.project -- noncyclical-same-filename-b.project - same-filename/noncyclical-same-filename-b.config imported by: noncyclical-same-filename-b.project Up to date diff --git a/cabal-testsuite/PackageTests/ConditionalAndImport/with-ghc.config b/cabal-testsuite/PackageTests/ConditionalAndImport/with-ghc.config new file mode 100644 index 00000000000..140a00be1b9 --- /dev/null +++ b/cabal-testsuite/PackageTests/ConditionalAndImport/with-ghc.config @@ -0,0 +1,7 @@ +-- WARNING: Override the `with-compiler: ghc-x.y.z` of the stackage import, of +-- https://www.stackage.org/nightly-yyyy-mm-dd/cabal.config. Otherwise tests +-- will fail with: +-- -Error: [Cabal-5490] +-- -Cannot find the program 'ghc'. User-specified path 'ghc-x.y.z' does not +-- refer to an executable and the program is not on the system path. +with-compiler: ghc diff --git a/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/0.config b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/0.config new file mode 100644 index 00000000000..05195095cb0 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/0.config @@ -0,0 +1,7 @@ +import: cfg/1.config +import: cfg/3.config +import: cfg/5.config +import: cfg/7.config +import: cfg/9.config + +import: with-ghc.config diff --git a/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/2.config b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/2.config new file mode 100644 index 00000000000..80143e396c8 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/2.config @@ -0,0 +1,2 @@ +import: cfg/3.config +import: https://www.stackage.org/lts-21.25/cabal.config diff --git a/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/4.config b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/4.config new file mode 100644 index 00000000000..8b84982cc3e --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/4.config @@ -0,0 +1,2 @@ +import: cfg/5.config +import: https://www.stackage.org/lts-21.25/cabal.config diff --git a/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/6.config b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/6.config new file mode 100644 index 00000000000..43ce76e8766 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/6.config @@ -0,0 +1,2 @@ +import: cfg/7.config +import: https://www.stackage.org/lts-21.25/cabal.config diff --git a/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/8.config b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/8.config new file mode 100644 index 00000000000..28d0551160f --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/8.config @@ -0,0 +1,2 @@ +import: cfg/9.config +import: https://www.stackage.org/lts-21.25/cabal.config diff --git a/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cabal.out b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cabal.out new file mode 100644 index 00000000000..437612a2eca --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cabal.out @@ -0,0 +1,3 @@ +# checking "using config from message" with URI imports +# cabal v2-build +# checking that package directories and locations are reported in order diff --git a/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cabal.test.hs b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cabal.test.hs new file mode 100644 index 00000000000..e354b356d7f --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cabal.test.hs @@ -0,0 +1,42 @@ +import Test.Cabal.Prelude + +main = cabalTest . recordMode RecordMarked $ do + let log = recordHeader . pure + + log "checking \"using config from message\" with URI imports" + out <- fails $ cabal' "v2-build" [ "all", "--dry-run", "--project-file=no-pkgs.project" ] + + -- Use assertRegex when the output is tainted by the temp directory, like + -- this: + -- + -- When using configuration from: + -- - /tmp/cabal-testsuite-282695/cabal.project + -- - /tmp/cabal-testsuite-282695/2.config etc + assertRegex + "Project configuration with URI imports is listed in full" + "When using configuration from:(\n|\r\n) \ + \ .*no-pkgs\\.project(\n|\r\n) \ + \ .*0\\.config(\n|\r\n) \ + \ .*2\\.config(\n|\r\n) \ + \ .*4\\.config(\n|\r\n) \ + \ .*6\\.config(\n|\r\n) \ + \ .*8\\.config(\n|\r\n) \ + \ .*1\\.config(\n|\r\n) \ + \ .*3\\.config(\n|\r\n) \ + \ .*5\\.config(\n|\r\n) \ + \ .*7\\.config(\n|\r\n) \ + \ .*9\\.config(\n|\r\n) \ + \ .*with-ghc\\.config(\n|\r\n) \ + \ .*https://www.stackage.org/lts-21.25/cabal.config(\n|\r\n)" + out + + log "checking that package directories and locations are reported in order" + assertOutputContains + "The following errors occurred: \ + \ - The package directory 'no-pkg-1' does not contain any .cabal file. \ + \ - The package location 'no-pkg-2-dir' does not exist. \ + \ - The package directory 'no-pkg-3' does not contain any .cabal file. \ + \ - The package location 'no-pkg-4-dir' does not exist." + out + + return () diff --git a/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cfg/1.config b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cfg/1.config new file mode 100644 index 00000000000..126a94da61d --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cfg/1.config @@ -0,0 +1,2 @@ +import: ../2.config +import: https://www.stackage.org/lts-21.25/cabal.config diff --git a/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cfg/3.config b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cfg/3.config new file mode 100644 index 00000000000..f40b183e472 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cfg/3.config @@ -0,0 +1,2 @@ +import: ../4.config +import: https://www.stackage.org/lts-21.25/cabal.config diff --git a/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cfg/5.config b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cfg/5.config new file mode 100644 index 00000000000..7f579a54345 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cfg/5.config @@ -0,0 +1,2 @@ +import: ../6.config +import: https://www.stackage.org/lts-21.25/cabal.config diff --git a/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cfg/7.config b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cfg/7.config new file mode 100644 index 00000000000..7cd98c9c244 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cfg/7.config @@ -0,0 +1,2 @@ +import: ../8.config +import: https://www.stackage.org/lts-21.25/cabal.config diff --git a/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cfg/9.config b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cfg/9.config new file mode 100644 index 00000000000..44d1cc5e562 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/cfg/9.config @@ -0,0 +1,2 @@ +-- No imports here +import: https://www.stackage.org/lts-21.25/cabal.config diff --git a/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/no-pkg-1/README.md b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/no-pkg-1/README.md new file mode 100644 index 00000000000..ba73c42531f --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/no-pkg-1/README.md @@ -0,0 +1,2 @@ +There's intentionally no package here but the directory for the package exists +so that the project can find it. diff --git a/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/no-pkg-3/README.md b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/no-pkg-3/README.md new file mode 100644 index 00000000000..ba73c42531f --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/no-pkg-3/README.md @@ -0,0 +1,2 @@ +There's intentionally no package here but the directory for the package exists +so that the project can find it. diff --git a/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/no-pkgs.project b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/no-pkgs.project new file mode 100644 index 00000000000..0d723a9e298 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/no-pkgs.project @@ -0,0 +1,7 @@ +packages: + no-pkg-1 + no-pkg-2-dir + no-pkg-3 + no-pkg-4-dir + +import: 0.config diff --git a/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/with-ghc.config b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/with-ghc.config new file mode 100644 index 00000000000..140a00be1b9 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromComplex/with-ghc.config @@ -0,0 +1,7 @@ +-- WARNING: Override the `with-compiler: ghc-x.y.z` of the stackage import, of +-- https://www.stackage.org/nightly-yyyy-mm-dd/cabal.config. Otherwise tests +-- will fail with: +-- -Error: [Cabal-5490] +-- -Cannot find the program 'ghc'. User-specified path 'ghc-x.y.z' does not +-- refer to an executable and the program is not on the system path. +with-compiler: ghc diff --git a/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/a-very-extra.config b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/a-very-extra.config new file mode 100644 index 00000000000..c0f8dc3cc73 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/a-very-extra.config @@ -0,0 +1,2 @@ +import: https://www.stackage.org/lts-21.25/cabal.config +import: https://www.stackage.org/lts-21.25/cabal.config diff --git a/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/an-extra.config b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/an-extra.config new file mode 100644 index 00000000000..c0f8dc3cc73 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/an-extra.config @@ -0,0 +1,2 @@ +import: https://www.stackage.org/lts-21.25/cabal.config +import: https://www.stackage.org/lts-21.25/cabal.config diff --git a/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/cabal.out b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/cabal.out new file mode 100644 index 00000000000..92fd8204a40 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/cabal.out @@ -0,0 +1 @@ +# cabal v2-build diff --git a/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/cabal.project b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/cabal.project new file mode 100644 index 00000000000..32308f3491f --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/cabal.project @@ -0,0 +1,9 @@ +packages: no-pkg-dir +import: z-empty.config +import: an-extra.config +import: an-extra.config +import: a-very-extra.config +import: a-very-extra.config +import: https://www.stackage.org/lts-21.25/cabal.config +import: https://www.stackage.org/lts-21.25/cabal.config +import: with-ghc.config diff --git a/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/cabal.test.hs b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/cabal.test.hs new file mode 100644 index 00000000000..cf37d1621a6 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/cabal.test.hs @@ -0,0 +1,24 @@ +import Test.Cabal.Prelude + +main = cabalTest . recordMode RecordMarked $ do + let log = recordHeader . pure + + out <- fails $ cabal' "v2-build" [ "all", "--dry-run" ] + + -- Use assertRegex when the output is tainted by the temp directory, like + -- this: + -- + -- When using configuration from: + -- - /tmp/cabal-testsuite-282695/cabal.project + assertRegex + "Project configuration is listed in full and deduplicated" + "When using configuration from:(\n|\r\n) \ + \ .*cabal\\.project(\n|\r\n) \ + \ .*a-very-extra\\.config(\n|\r\n) \ + \ .*an-extra\\.config(\n|\r\n) \ + \ .*with-ghc\\.config(\n|\r\n) \ + \ .*z-empty\\.config(\n|\r\n) \ + \ .*https://www.stackage.org/lts-21.25/cabal.config(\n|\r\n)" + out + + return () diff --git a/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/with-ghc.config b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/with-ghc.config new file mode 100644 index 00000000000..140a00be1b9 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/with-ghc.config @@ -0,0 +1,7 @@ +-- WARNING: Override the `with-compiler: ghc-x.y.z` of the stackage import, of +-- https://www.stackage.org/nightly-yyyy-mm-dd/cabal.config. Otherwise tests +-- will fail with: +-- -Error: [Cabal-5490] +-- -Cannot find the program 'ghc'. User-specified path 'ghc-x.y.z' does not +-- refer to an executable and the program is not on the system path. +with-compiler: ghc diff --git a/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/z-empty.config b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/z-empty.config new file mode 100644 index 00000000000..771bb389fde --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/DedupUsingConfigFromSimple/z-empty.config @@ -0,0 +1 @@ +-- This file is intentionally empty, just this comment. diff --git a/changelog.d/pr-10546 b/changelog.d/pr-10546 index 1851e21c0e4..db0951505f0 100644 --- a/changelog.d/pr-10546 +++ b/changelog.d/pr-10546 @@ -1,9 +1,82 @@ --- -synopsis: Add an Ord instance for ProjectConfigPath +synopsis: Deduplicate "using configuration from" message packages: [cabal-install-solver] prs: 10546 --- -Add an `Ord` instance for `ProjectConfigPath` that sorts URIs after local paths -and longer paths after shorter ones. Deduplicate the printing of "Configuration is -affected by the following files" messages. +## Using Configuration From Message Changes + +Deduplicates and sorts the list of configuration files and URIs printed with the +"using configuration from" message. This message is shown when there's a build +failure. We can trigger that message by using a non-existant package in the +project, "no-pkg-dir". + +If an import is repeated in a `.project` or `.config` file it only imported once +but if the same import is made from an imported file then it was being repeated +in the message. Additional problems were not showing the project first and +mixing configuration files and URIs together. + +* The test set up: + + ``` + $ cat cabal.project + cat cabal.project + packages: no-pkg-dir + import: z-empty.config + import: an-extra.config + import: an-extra.config + import: a-very-extra.config + import: a-very-extra.config + import: https://www.stackage.org/lts-21.25/cabal.config + import: https://www.stackage.org/lts-21.25/cabal.config + + $ cat an-extra.config + import: https://www.stackage.org/lts-21.25/cabal.config + import: https://www.stackage.org/lts-21.25/cabal.config + + $ cat a-very-extra.config + import: https://www.stackage.org/lts-21.25/cabal.config + import: https://www.stackage.org/lts-21.25/cabal.config + + $ cat z-empty.config + - This file is intentionally empty, just this comment. + ``` + +* Before the fix: + + ``` + $ ~/.ghcup/bin/cabal-3.12.1.0 build all --dry-run + When using configuration from: + - a-very-extra.config + - an-extra.config + - cabal.project + - https://www.stackage.org/lts-21.25/cabal.config + - https://www.stackage.org/lts-21.25/cabal.config + - https://www.stackage.org/lts-21.25/cabal.config + - z-empty.config + The following errors occurred: + - The package location 'no-pkg-dir' does not exist. + ``` + +* After the fix: + + ``` + $ cabal build all --dry-run + When using configuration from: + - cabal.project + - a-very-extra.config + - an-extra.config + - z-empty.config + - https://www.stackage.org/lts-21.25/cabal.config + The following errors occurred: + - The package location 'no-pkg-dir' does not exist. + ``` + +## Ord ProjectConfigPath Instance Changes + +Adds a custom `Ord` instance for `ProjectConfigPath` that sorts URIs after local +file paths and longer file paths after shorter ones as measured by the number of +path segments. If still equal, then sorting is lexical. The project itself, a +single element root path, compared to any of the configuration paths it imports, +should always sort first. Comparing one project root path against another is +done lexically.