Skip to content

Commit

Permalink
Merge pull request #10646 from cabalism/fix/path-sep-duplicates
Browse files Browse the repository at this point in the history
Deduplicate path separator duplicates
  • Loading branch information
mergify[bot] authored Jan 5, 2025
2 parents e98bc7f + 32b820b commit 2040d21
Show file tree
Hide file tree
Showing 24 changed files with 766 additions and 185 deletions.
9 changes: 6 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -395,9 +395,12 @@ description: {
}
```

Changelogs may also be written in "markdown-frontmatter" format. This is useful if your
description contains braces, which must be escaped with backslashes in `.cabal` file
format. The front matter is in YAML syntax, not `.cabal` file syntax, and the file
Changelogs may also be written in "markdown-frontmatter" format. This is useful
if your description contains braces, which must be escaped with backslashes in
`.cabal` file format. Another benefit of using an `.md` extension with your
changelog is that it will be checked for typos.

The front matter is in YAML syntax, not `.cabal` file syntax, and the file
_must_ begin with a line containing only hyphens.

```markdown
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,17 @@ 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 Distribution.Utils.String (trim)
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 @@ -61,6 +65,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 @@ -69,7 +81,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 @@ -83,6 +95,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 ()
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
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.
120 changes: 11 additions & 109 deletions cabal-testsuite/PackageTests/ConditionalAndImport/cabal.test.hs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
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 ((&))
import Data.Functor ((<&>))

main = cabalTest . withRepo "repo" . recordMode RecordMarked $ do
let log = recordHeader . pure
Expand Down Expand Up @@ -79,7 +79,7 @@ main = cabalTest . withRepo "repo" . recordMode RecordMarked $ do
-- +-- etc
log "checking that cyclical check catches a same file name that imports itself"
cyclical4a <- fails $ cabal' "v2-build" [ "--project-file=cyclical-same-filename-out-out-self.project" ]
assertOutputContains (normalizeWindowsOutput "cyclical import of same-filename/cyclical-same-filename-out-out-self.config") cyclical4a
assertOutputContains (normalizePathSeparators "cyclical import of same-filename/cyclical-same-filename-out-out-self.config") cyclical4a

-- +-- cyclical-same-filename-out-out-backback.project
-- +-- cyclical-same-filename-out-out-backback.config
Expand Down Expand Up @@ -111,89 +111,9 @@ 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
readFileVerbatim "hops.expect.txt" >>=
flip (assertOn multilineNeedleHaystack) hopping . normalizePathSeparators

-- The project is named oops as it is like hops but has conflicting constraints.
-- +-- oops-0.project
Expand All @@ -208,22 +128,9 @@ 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
readFileVerbatim "oops.expect.txt"
>>= flip (assertOn multilineNeedleHaystack) oopsing . normalizePathSeparators

-- 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 +171,8 @@ 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

readFileVerbatim "cabal-missing-package.expect.txt"
>>= flip (assertOn multilineNeedleHaystack) missing . normalizePathSeparators

return ()
56 changes: 56 additions & 0 deletions cabal-testsuite/PackageTests/ConditionalAndImport/hops.expect.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
Configuration is affected by the following files:
- hops-0.project
- hops-2.config
imported by: hops/hops-1.config
imported by: hops-0.project
- 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
- 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
- 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
- hops/hops-1.config
imported by: hops-0.project
- hops/hops-3.config
imported by: hops-2.config
imported by: hops/hops-1.config
imported by: hops-0.project
- 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
- 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
- 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
16 changes: 16 additions & 0 deletions cabal-testsuite/PackageTests/ConditionalAndImport/oops.expect.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Could not resolve dependencies:
[__0] trying: oops-0.1 (user goal)
[__1] next goal: hashable (dependency of oops)
[__1] rejecting: hashable-1.4.3.0
(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
[__1] rejecting: hashable-1.4.2.0
(constraint from oops-0.project requires ==1.4.3.0)
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,3 +1,4 @@
# checking "using config from message" with URI imports
# check "using config from message" with URI imports
# cabal v2-build
# checking that package directories and locations are reported in order
# check project configuration with URI imports is listed in full and
# check package directories and locations are reported in order
Loading

0 comments on commit 2040d21

Please sign in to comment.