| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
Distribution.Solver.Types.ProjectConfigPath
Synopsis
- newtype ProjectConfigPath = ProjectConfigPath (NonEmpty FilePath)
- compareLexicographically :: ProjectConfigPath -> ProjectConfigPath -> Ordering
- compareSegmentally :: ProjectConfigPath -> ProjectConfigPath -> Ordering
- projectConfigPathRoot :: ProjectConfigPath -> FilePath
- nullProjectConfigPath :: ProjectConfigPath
- consProjectConfigPath :: FilePath -> ProjectConfigPath -> ProjectConfigPath
- unconsProjectConfigPath :: ProjectConfigPath -> (FilePath, Maybe ProjectConfigPath)
- currentProjectConfigPath :: ProjectConfigPath -> FilePath
- docProjectConfigPath :: ProjectConfigPath -> Doc
- docProjectImportedBy :: ProjectConfigPath -> Doc
- docProjectConfigPathFailReason :: VR -> ProjectConfigPath -> Doc
- quoteUntrimmed :: FilePath -> Doc
- isCyclicConfigPath :: ProjectConfigPath -> Bool
- isTopLevelConfigPath :: ProjectConfigPath -> Bool
- isUntrimmedUriConfigPath :: ProjectConfigPath -> Bool
- canonicalizeConfigPath :: FilePath -> ProjectConfigPath -> IO ProjectConfigPath
Project Config Path Manipulation
newtype ProjectConfigPath Source #
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
build up by prepending relative imports with consProjectConfigPath.
An import can be a URI, such as a stackage cabal.config, but we do not support URIs in the middle of the path, URIs that import other URIs, or URIs that import local files.
List elements are relative to each other but once canonicalized, elements are relative to the directory of the project root.
Constructors
| ProjectConfigPath (NonEmpty FilePath) |
Instances
| Pretty ProjectConfigPath Source # | |||||
Defined in Distribution.Solver.Types.ProjectConfigPath Methods pretty :: ProjectConfigPath -> Doc # prettyVersioned :: CabalSpecVersion -> ProjectConfigPath -> Doc # | |||||
| Structured ProjectConfigPath Source # | |||||
Defined in Distribution.Solver.Types.ProjectConfigPath Methods structure :: Proxy ProjectConfigPath -> Structure # structureHash' :: Tagged ProjectConfigPath MD5 | |||||
| Binary ProjectConfigPath Source # | |||||
Defined in Distribution.Solver.Types.ProjectConfigPath Methods put :: ProjectConfigPath -> Put # get :: Get ProjectConfigPath # putList :: [ProjectConfigPath] -> Put # | |||||
| NFData ProjectConfigPath Source # | |||||
Defined in Distribution.Solver.Types.ProjectConfigPath Methods rnf :: ProjectConfigPath -> () # | |||||
| Generic ProjectConfigPath Source # | |||||
Defined in Distribution.Solver.Types.ProjectConfigPath Associated Types
Methods from :: ProjectConfigPath -> Rep ProjectConfigPath x # to :: Rep ProjectConfigPath x -> ProjectConfigPath # | |||||
| Show ProjectConfigPath Source # | |||||
Defined in Distribution.Solver.Types.ProjectConfigPath Methods showsPrec :: Int -> ProjectConfigPath -> ShowS # show :: ProjectConfigPath -> String # showList :: [ProjectConfigPath] -> ShowS # | |||||
| Eq ProjectConfigPath Source # | |||||
Defined in Distribution.Solver.Types.ProjectConfigPath Methods (==) :: ProjectConfigPath -> ProjectConfigPath -> Bool # (/=) :: ProjectConfigPath -> ProjectConfigPath -> Bool # | |||||
| Ord ProjectConfigPath Source # | 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. For comparison purposes, path separators are normalized to the
| ||||
Defined in Distribution.Solver.Types.ProjectConfigPath Methods compare :: ProjectConfigPath -> ProjectConfigPath -> Ordering # (<) :: ProjectConfigPath -> ProjectConfigPath -> Bool # (<=) :: ProjectConfigPath -> ProjectConfigPath -> Bool # (>) :: ProjectConfigPath -> ProjectConfigPath -> Bool # (>=) :: ProjectConfigPath -> ProjectConfigPath -> Bool # max :: ProjectConfigPath -> ProjectConfigPath -> ProjectConfigPath # min :: ProjectConfigPath -> ProjectConfigPath -> ProjectConfigPath # | |||||
| type Rep ProjectConfigPath Source # | |||||
Defined in Distribution.Solver.Types.ProjectConfigPath type Rep ProjectConfigPath = D1 ('MetaData "ProjectConfigPath" "Distribution.Solver.Types.ProjectConfigPath" "cabal-install-solver-3.18.1.0-inplace" 'True) (C1 ('MetaCons "ProjectConfigPath" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (NonEmpty FilePath)))) | |||||
compareLexicographically :: ProjectConfigPath -> ProjectConfigPath -> Ordering Source #
A comparison that puts projects first, URLs last and sorts the other paths lexically.
compareSegmentally :: ProjectConfigPath -> ProjectConfigPath -> Ordering Source #
A comparison that puts projects first, URLs last and sorts the other paths by putting longer paths after shorter ones as measured by the number of path segments. If still equal, then sorting is lexical.
projectConfigPathRoot :: ProjectConfigPath -> FilePath Source #
The root of the path, the project itself.
nullProjectConfigPath :: ProjectConfigPath Source #
Used by some tests as a dummy "unused" project root.
consProjectConfigPath :: FilePath -> ProjectConfigPath -> ProjectConfigPath Source #
Prepends the path of the importee to the importer path.
unconsProjectConfigPath :: ProjectConfigPath -> (FilePath, Maybe ProjectConfigPath) Source #
Split the path into the importee and the importer path.
Messages
docProjectConfigPath :: ProjectConfigPath -> Doc Source #
Renders the path like this;
D.config imported by: C.config imported by: B.config imported by: A.project
>>>render . docProjectConfigPath $ ProjectConfigPath $ "D.config" :| ["C.config", "B.config", "A.project"]"D.config\n imported by: C.config\n imported by: B.config\n imported by: A.project"
docProjectImportedBy :: ProjectConfigPath -> Doc Source #
Render the paths which imports this config.
quoteUntrimmed :: FilePath -> Doc Source #
If the path has leading or trailing spaces then show it quoted.
Checks and Normalization
isCyclicConfigPath :: ProjectConfigPath -> Bool Source #
Check if the path has duplicates. A cycle of imports is not allowed. This
check should only be done after the path has been canonicalized with
canonicalizeConfigPath. This is because the import path may contain paths
that are the same in relation to their importers but different in relation to
the project root directory.
isTopLevelConfigPath :: ProjectConfigPath -> Bool Source #
Check if the project config path is top-level, meaning it was not included by some other project config.
isUntrimmedUriConfigPath :: ProjectConfigPath -> Bool Source #
Check if the last segment of the path (root or importee) is a URI that has leading or trailing spaces.
canonicalizeConfigPath :: FilePath -> ProjectConfigPath -> IO ProjectConfigPath Source #
Normalizes and canonicalizes a path removing . and '..' indirections.
Makes the path relative to the given directory (typically the project root)
instead of relative to the file it was imported from.
It converts paths like this:
hops-0.project
└─ hops/hops-1.config
└─ ../hops-2.config
└─ hops/hops-3.config
└─ ../hops-4.config
└─ hops/hops-5.config
└─ ../hops-6.config
└─ hops/hops-7.config
└─ ../hops-8.config
└─ hops/hops-9.configInto paths like this:
hops-0.project
└─ hops/hops-1.config
└─ hops-2.config
└─ hops/hops-3.config
└─ hops-4.config
└─ hops/hops-5.config
└─ hops-6.config
└─ hops/hops-7.config
└─ hops-8.config
└─ hops/hops-9.configThat way we have hops-8.config instead of
.hops..hops..hops..hops../hops-8.config.
Let's see how canonicalizePath works that is used in the implementation
then we'll see how canonicalizeConfigPath works.
>>>let d = testDir>>>makeRelative d <$> canonicalizePath (d </> "hops/../hops/../hops/../hops/../hops-8.config")"hops-8.config"
>>>let d = testDir>>>p <- canonicalizeConfigPath d (ProjectConfigPath $ (d </> "hops/../hops/../hops/../hops/../hops-8.config") :| [])>>>render $ docProjectConfigPath p"hops-8.config"
>>>:{do let expected = unlines [ "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" ] let d = testDir let configPath = ProjectConfigPath ("hops/hops-9.config" :| [ "../hops-8.config" , "hops/hops-7.config" , "../hops-6.config" , "hops/hops-5.config" , "../hops-4.config" , "hops/hops-3.config" , "../hops-2.config" , "hops/hops-1.config" , d </> "hops-0.project"]) p <- canonicalizeConfigPath d configPath return $ expected == render (docProjectConfigPath p) ++ "\n" :} True
"A string is a valid URL potentially surrounded by spaces if, after stripping leading and trailing whitespace from it, it is a valid URL." W3CHTML5URLs
Trailing spaces for ProjectConfigPath URLs are trimmed.
>>>p <- canonicalizeConfigPath "" (ProjectConfigPath $ ("https://www.stackage.org/nightly-2024-12-05/cabal.config ") :| [])>>>render $ docProjectConfigPath p"https://www.stackage.org/nightly-2024-12-05/cabal.config"
>>>let d = testDir>>>p <- canonicalizeConfigPath d (ProjectConfigPath $ ("https://www.stackage.org/nightly-2024-12-05/cabal.config ") :| [d </> "cabal.project"])>>>render $ docProjectConfigPath p"https://www.stackage.org/nightly-2024-12-05/cabal.config\n imported by: cabal.project"