Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deduplicate path separator duplicates #10646

Draft
wants to merge 36 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
d791a4b
Use OS-specific splitPath before comparing projects
philderbeast Dec 17, 2024
87c97fd
Add else.project test
philderbeast Dec 17, 2024
8732b02
Use normalizeWindowsOutput
philderbeast Dec 17, 2024
5c48293
Use pathSeparator instead of literal char
philderbeast Dec 17, 2024
ba3cc28
Use isPathSeparator predicate
philderbeast Dec 17, 2024
fac2b78
Add a changelog entry
philderbeast Dec 17, 2024
fd7d33c
Update expectation
philderbeast Dec 17, 2024
0405ae3
Use concatOutput on needle
philderbeast Dec 18, 2024
14f730b
Include output
philderbeast Dec 18, 2024
1e7609a
Align lines
philderbeast Dec 18, 2024
a5b9faf
Show modified output
philderbeast Dec 18, 2024
a2a7a3e
Apply concatOutput to the needle
philderbeast Dec 18, 2024
1be777d
Show start and end of lines with ASCII ^ and $
philderbeast Dec 18, 2024
06aa1e5
Use \n in multiline string expectation
philderbeast Dec 18, 2024
3570021
Multliline expectations
philderbeast Dec 18, 2024
b998deb
Redo ConditionalAndImport with multiline expectations
philderbeast Dec 18, 2024
3e587e7
Add test of string expectation start and end marking
philderbeast Dec 18, 2024
83c7d5e
Rename encodeLf and decodeLfMarkLines
philderbeast Dec 18, 2024
0355fb7
Add assertOutputContainsWrapped
philderbeast Dec 18, 2024
b3d84d4
Use multiline and wrapped assertions
philderbeast Dec 18, 2024
4d615ba
Satisfy fix-whitespace
philderbeast Dec 18, 2024
072cc9c
DedupUsingConfigFromComplex multiline assertion
philderbeast Dec 18, 2024
503a8ab
Remove redundant tests that fail on Windows
philderbeast Dec 18, 2024
e9da58d
Use normalizeWindowsOutput in ConditionalAndImport
philderbeast Dec 19, 2024
e57e129
Forward conversion applied twice by mistake
philderbeast Dec 19, 2024
0f9696e
Add NeedleHaystack
philderbeast Dec 19, 2024
d371c5c
Add expectNeedleInHaystack field to NeedleHaystack
philderbeast Dec 19, 2024
6e67893
Remove 3 assert*Contains functions
philderbeast Dec 19, 2024
301c685
Add TxContains record
philderbeast Dec 19, 2024
0cf90fd
Apply the txBwd transformations before display
philderbeast Dec 19, 2024
010c6e9
Add displayHaystack field
philderbeast Dec 19, 2024
a57e90a
Switch to using <EOL> as the marker
philderbeast Dec 19, 2024
51d6c9c
Use ++ rather than cons with reversals
philderbeast Dec 19, 2024
66fb928
Rerun ParseErrorProvenance test
philderbeast Dec 19, 2024
c07bc26
Satisfy hlint
philderbeast Dec 19, 2024
c06ba60
Add doctests for single line strings
philderbeast Dec 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,16 @@ import Data.Coerce (coerce)
import Data.List.NonEmpty ((<|))
import Network.URI (parseURI, parseAbsoluteURI)
import System.Directory
import System.FilePath
import System.FilePath hiding (splitPath)
import qualified System.FilePath as FP (splitPath)
import qualified System.FilePath.Posix as Posix
import qualified System.FilePath.Windows as Windows
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)
import Distribution.System (OS(Windows), buildOS)

-- | 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
Expand All @@ -58,6 +62,14 @@ newtype ProjectConfigPath = ProjectConfigPath (NonEmpty FilePath)
-- 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.
--
-- For comparison purposes, path separators are normalized to the @buildOS@
-- platform's path separator.
--
-- >>> let abFwd = ProjectConfigPath $ "a/b.config" :| []
-- >>> let abBwd = ProjectConfigPath $ "a\\b.config" :| []
-- >>> compare abFwd abBwd
-- EQ
instance Ord ProjectConfigPath where
compare pa@(ProjectConfigPath (NE.toList -> as)) pb@(ProjectConfigPath (NE.toList -> bs)) =
case (as, bs) of
Expand All @@ -66,7 +78,7 @@ instance Ord ProjectConfigPath where
-- 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
([a], [b]) -> compare (splitPath a) (splitPath b)
([_], _) -> LT
(_, [_]) -> GT

Expand All @@ -80,6 +92,16 @@ instance Ord ProjectConfigPath where
P.<> compare (length aPaths) (length bPaths)
P.<> compare aPaths bPaths
where
splitPath = FP.splitPath . normSep where
normSep p =
if buildOS == Windows
then
Windows.joinPath $ Windows.splitDirectories
[if Posix.isPathSeparator c then Windows.pathSeparator else c| c <- p]
else
Posix.joinPath $ Posix.splitDirectories
[if Windows.isPathSeparator c then Posix.pathSeparator else c| c <- p]

aPaths = splitPath <$> as
bPaths = splitPath <$> bs
aImporters = snd $ unconsProjectConfigPath pa
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ main = setupAndCabalTest . withPackageDb $ do
assertEqual
("executable should have linked with the internal library")
("foo foo myLibFunc internal")
(concatOutput (resultOutput r))
(lineBreaksToSpaces $ resultOutput r)
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ main = setupAndCabalTest . withPackageDb $ do
assertEqual
("executable should have linked with the internal library")
("foo foo myLibFunc internal")
(concatOutput (resultOutput r))
(lineBreaksToSpaces $ resultOutput r)
8 changes: 6 additions & 2 deletions cabal-testsuite/PackageTests/CheckSetup/setup.test.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@ main = cabalTest $ do
"The dependency 'setup-depends: 'base' does not specify "
++ "an upper bound on the version number"

-- Replace line breaks with spaces in the haystack so that we can search
-- for a string that wraps lines.
let lineBreakBlind = needleHaystack{txHaystack = txContainsId{txFwd = lineBreaksToSpaces}}

-- Asserts for the desired check messages after configure.
assertOutputContains libError1 checkResult
assertOutputContains libError2 checkResult
assertOn lineBreakBlind libError1 checkResult
assertOn lineBreakBlind libError2 checkResult

return ()
195 changes: 87 additions & 108 deletions cabal-testsuite/PackageTests/ConditionalAndImport/cabal.test.hs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import Test.Cabal.Prelude

normalizeWindowsOutput :: String -> String
normalizeWindowsOutput = if isWindows then map (\x -> case x of '/' -> '\\'; _ -> x) else id
import Test.Cabal.OutputNormalizer
import Data.Function ((&))

main = cabalTest . withRepo "repo" . recordMode RecordMarked $ do
let log = recordHeader . pure
Expand Down Expand Up @@ -111,89 +110,65 @@ main = cabalTest . withRepo "repo" . recordMode RecordMarked $ do
-- +-- hops/hops-9.config (no further imports so not cyclical)
log "checking that imports work skipping into a subfolder and then back out again and again"
hopping <- cabal' "v2-build" [ "--project-file=hops-0.project" ]
assertOutputContains "Configuration is affected by the following files" hopping
assertOutputContains "- hops-0.project" hopping

assertOutputContains
(normalizeWindowsOutput "- hops-2.config \
\ imported by: hops/hops-1.config \
\ imported by: hops-0.project")
hopping

assertOutputContains
(normalizeWindowsOutput "- hops-4.config \
\ imported by: hops/hops-3.config \
\ imported by: hops-2.config \
\ imported by: hops/hops-1.config \
\ imported by: hops-0.project")
hopping

assertOutputContains
(normalizeWindowsOutput "- hops-6.config \
\ imported by: hops/hops-5.config \
\ imported by: hops-4.config \
\ imported by: hops/hops-3.config \
\ imported by: hops-2.config \
\ imported by: hops/hops-1.config \
\ imported by: hops-0.project")
hopping

assertOutputContains
(normalizeWindowsOutput "- hops-8.config \
\ imported by: hops/hops-7.config \
\ imported by: hops-6.config \
\ imported by: hops/hops-5.config \
\ imported by: hops-4.config \
\ imported by: hops/hops-3.config \
\ imported by: hops-2.config \
\ imported by: hops/hops-1.config \
\ imported by: hops-0.project")
hopping

assertOutputContains
(normalizeWindowsOutput "- hops/hops-1.config \
\ imported by: hops-0.project")
hopping

assertOutputContains
(normalizeWindowsOutput "- hops/hops-3.config \
\ imported by: hops-2.config \
\ imported by: hops/hops-1.config \
\ imported by: hops-0.project")
hopping

assertOutputContains
(normalizeWindowsOutput "- hops/hops-5.config \
\ imported by: hops-4.config \
\ imported by: hops/hops-3.config \
\ imported by: hops-2.config \
\ imported by: hops/hops-1.config \
\ imported by: hops-0.project")
hopping

assertOutputContains
(normalizeWindowsOutput "- hops/hops-7.config \
\ imported by: hops-6.config \
\ imported by: hops/hops-5.config \
\ imported by: hops-4.config \
\ imported by: hops/hops-3.config \
\ imported by: hops-2.config \
\ imported by: hops/hops-1.config \
\ imported by: hops-0.project")
hopping

assertOutputContains
(normalizeWindowsOutput "- hops/hops-9.config \
\ imported by: hops-8.config \
\ imported by: hops/hops-7.config \
\ imported by: hops-6.config \
\ imported by: hops/hops-5.config \
\ imported by: hops-4.config \
\ imported by: hops/hops-3.config \
\ imported by: hops-2.config \
\ imported by: hops/hops-1.config \
\ imported by: hops-0.project")
hopping
"Configuration is affected by the following files:\n\
\- hops-0.project\n\
\- hops-2.config\n\
\ imported by: hops/hops-1.config\n\
\ imported by: hops-0.project\n\
\- hops-4.config\n\
\ imported by: hops/hops-3.config\n\
\ imported by: hops-2.config\n\
\ imported by: hops/hops-1.config\n\
\ imported by: hops-0.project\n\
\- hops-6.config\n\
\ imported by: hops/hops-5.config\n\
\ imported by: hops-4.config\n\
\ imported by: hops/hops-3.config\n\
\ imported by: hops-2.config\n\
\ imported by: hops/hops-1.config\n\
\ imported by: hops-0.project\n\
\- hops-8.config\n\
\ imported by: hops/hops-7.config\n\
\ imported by: hops-6.config\n\
\ imported by: hops/hops-5.config\n\
\ imported by: hops-4.config\n\
\ imported by: hops/hops-3.config\n\
\ imported by: hops-2.config\n\
\ imported by: hops/hops-1.config\n\
\ imported by: hops-0.project\n\
\- hops/hops-1.config\n\
\ imported by: hops-0.project\n\
\- hops/hops-3.config\n\
\ imported by: hops-2.config\n\
\ imported by: hops/hops-1.config\n\
\ imported by: hops-0.project\n\
\- hops/hops-5.config\n\
\ imported by: hops-4.config\n\
\ imported by: hops/hops-3.config\n\
\ imported by: hops-2.config\n\
\ imported by: hops/hops-1.config\n\
\ imported by: hops-0.project\n\
\- hops/hops-7.config\n\
\ imported by: hops-6.config\n\
\ imported by: hops/hops-5.config\n\
\ imported by: hops-4.config\n\
\ imported by: hops/hops-3.config\n\
\ imported by: hops-2.config\n\
\ imported by: hops/hops-1.config\n\
\ imported by: hops-0.project\n\
\- hops/hops-9.config\n\
\ imported by: hops-8.config\n\
\ imported by: hops/hops-7.config\n\
\ imported by: hops-6.config\n\
\ imported by: hops/hops-5.config\n\
\ imported by: hops-4.config\n\
\ imported by: hops/hops-3.config\n\
\ imported by: hops-2.config\n\
\ imported by: hops/hops-1.config\n\
\ imported by: hops-0.project"
& normalizeWindowsOutput
& flip (assertOn multilineNeedleHaystack) hopping

-- The project is named oops as it is like hops but has conflicting constraints.
-- +-- oops-0.project
Expand All @@ -208,22 +183,25 @@ main = cabalTest . withRepo "repo" . recordMode RecordMarked $ do
-- +-- oops/oops-9.config (has conflicting constraints)
log "checking conflicting constraints skipping into a subfolder and then back out again and again"
oopsing <- fails $ cabal' "v2-build" [ "all", "--project-file=oops-0.project" ]
assertOutputContains "rejecting: hashable-1.4.2.0" oopsing
assertOutputContains "rejecting: hashable-1.4.3.0" oopsing
assertOutputContains "(constraint from oops-0.project requires ==1.4.3.0)" oopsing

assertOutputContains
(normalizeWindowsOutput " (constraint from oops/oops-9.config requires ==1.4.2.0) \
\ imported by: oops-8.config \
\ imported by: oops/oops-7.config \
\ imported by: oops-6.config \
\ imported by: oops/oops-5.config \
\ imported by: oops-4.config \
\ imported by: oops/oops-3.config \
\ imported by: oops-2.config \
\ imported by: oops/oops-1.config \
\ imported by: oops-0.project")
oopsing
"Could not resolve dependencies:\n\
\[__0] trying: oops-0.1 (user goal)\n\
\[__1] next goal: hashable (dependency of oops)\n\
\[__1] rejecting: hashable-1.4.3.0\n\
\ (constraint from oops/oops-9.config requires ==1.4.2.0)\n\
\ imported by: oops-8.config\n\
\ imported by: oops/oops-7.config\n\
\ imported by: oops-6.config\n\
\ imported by: oops/oops-5.config\n\
\ imported by: oops-4.config\n\
\ imported by: oops/oops-3.config\n\
\ imported by: oops-2.config\n\
\ imported by: oops/oops-1.config\n\
\ imported by: oops-0.project\n\
\[__1] rejecting: hashable-1.4.2.0\n\
\ (constraint from oops-0.project requires ==1.4.3.0)"
& normalizeWindowsOutput
& flip (assertOn multilineNeedleHaystack) oopsing

-- The project is named yops as it is like hops but with y's for forks.
-- +-- yops-0.project
Expand Down Expand Up @@ -264,13 +242,14 @@ main = cabalTest . withRepo "repo" . recordMode RecordMarked $ do

log "checking that missing package message lists configuration provenance"
missing <- fails $ cabal' "v2-build" [ "--project-file=cabal-missing-package.project" ]
assertOutputContains
(normalizeWindowsOutput "When using configuration from: \
\ - cabal-missing-package.project \
\ - missing/pkgs.config \
\ - missing/pkgs/default.config \
\The following errors occurred: \
\ - The package location 'pkg-doesnt-exist' does not exist.")
missing

"When using configuration from:\n\
\ - cabal-missing-package.project\n\
\ - missing/pkgs.config\n\
\ - missing/pkgs/default.config\n\
\The following errors occurred:\n\
\ - The package location 'pkg-doesnt-exist' does not exist."
& normalizeWindowsOutput
& flip (assertOn multilineNeedleHaystack) missing

return ()
10 changes: 5 additions & 5 deletions cabal-testsuite/PackageTests/NewBuild/T4288/cabal.test.hs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Test.Cabal.Prelude
import Data.Function ((&))

-- This test is similar to the simplified example in issue #4288. The package's
-- setup script only depends on base and setup-helper. setup-helper exposes a
Expand All @@ -10,8 +11,7 @@ main = cabalTest $ do
skipUnless "no v2-build compatible boot-Cabal" =<< hasNewBuildCompatBootCabal
r <- recordMode DoNotRecord $ cabal' "v2-build" ["T4288"]
assertOutputContains "This is setup-helper-1.0." r
assertOutputContains
("In order, the following will be built: "
++ " - setup-helper-1.0 (lib:setup-helper) (first run) "
++ " - T4288-1.0 (lib:T4288) (first run)")
r
"In order, the following will be built:\n\
\ - setup-helper-1.0 (lib:setup-helper) (first run)\n\
\ - T4288-1.0 (lib:T4288) (first run)"
& flip (assertOn multilineNeedleHaystack) r
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Test.Cabal.Prelude
import Data.Function ((&))

main = cabalTest . recordMode RecordMarked $ do
let log = recordHeader . pure
Expand Down Expand Up @@ -31,12 +32,12 @@ main = cabalTest . recordMode RecordMarked $ do
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

"The following errors occurred:\n\
\ - The package directory 'no-pkg-1' does not contain any .cabal file.\n\
\ - The package location 'no-pkg-2-dir' does not exist.\n\
\ - The package directory 'no-pkg-3' does not contain any .cabal file.\n\
\ - The package location 'no-pkg-4-dir' does not exist."
& flip (assertOn multilineNeedleHaystack) out

return ()
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# cabal v2-build
Warning: <ROOT>/else.project, else.project: Unrecognized section '_' on line 3
# Multiline string marking:
# ^When using configuration from:$
# ^ - else.project$
# ^ - dir-else/else.config$
# ^The following errors occurred:$
# ^ - The package location 'no-pkg-here' does not exist.$
# Pseudo multiline string marking:
# ^When using configuration from: - else.project - dir-else/else.configThe following errors occurred: - The package location 'no-pkg-here' does not exist.$
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Test.Cabal.Prelude

main = cabalTest . recordMode RecordMarked $ do
let log = recordHeader . pure

let expectMulti =
"When using configuration from:\n\
\ - else.project\n\
\ - dir-else/else.config\n\
\The following errors occurred:\n\
\ - The package location 'no-pkg-here' does not exist."

outElse <- fails $ cabal' "v2-build" [ "all", "--dry-run", "--project-file=else.project" ]

let expectSingle = filter (/= '\n') expectMulti

log "Multiline string marking:"
mapM_ log (lines . decodeLfMarkLines $ encodeLf expectMulti)

log "Pseudo multiline string marking:"
mapM_ log (lines . decodeLfMarkLines $ encodeLf expectSingle)

assertOn multilineNeedleHaystack expectMulti outElse
assertOn multilineNeedleHaystack{expectNeedleInHaystack = False} expectSingle outElse

assertOutputDoesNotContain expectMulti outElse
assertOutputDoesNotContain expectSingle outElse

return ()
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
if false
else
_
packages: no-pkg-here
Loading
Loading