packages feed

cabal-install-parsers 0.2 → 0.3

raw patch · 12 files changed

+142/−29 lines, 12 filesdep +criteriondep +deepseqdep ~Cabaldep ~basedep ~bytestringPVP ok

version bump matches the API change (PVP)

Dependencies added: criterion, deepseq

Dependency ranges changed: Cabal, base, bytestring, containers, directory, filepath, pretty

API changes (from Hackage documentation)

- Cabal.Parse: instance GHC.Exception.Type.Exception Cabal.Parse.ParseError
- Cabal.Parse: instance GHC.Show.Show Cabal.Parse.ParseError
- Cabal.Project: [prjOrigFields] :: Project uri opt pkg -> [PrettyField ()]
+ Cabal.Config: instance Control.DeepSeq.NFData (f GHC.IO.FilePath) => Control.DeepSeq.NFData (Cabal.Config.Config f)
+ Cabal.Config: instance Control.DeepSeq.NFData Cabal.Config.Repo
+ Cabal.Config: instance GHC.Generics.Generic Cabal.Config.Repo
+ Cabal.Optimization: instance Control.DeepSeq.NFData Cabal.Optimization.Optimization
+ Cabal.Parse: instance (Data.Foldable.Foldable f, GHC.Show.Show (f Distribution.Parsec.Error.PError), Data.Typeable.Internal.Typeable f) => GHC.Exception.Type.Exception (Cabal.Parse.ParseError f)
+ Cabal.Parse: instance Control.DeepSeq.NFData (f Distribution.Parsec.Error.PError) => Control.DeepSeq.NFData (Cabal.Parse.ParseError f)
+ Cabal.Parse: instance GHC.Generics.Generic (Cabal.Parse.ParseError f)
+ Cabal.Parse: instance GHC.Show.Show (f Distribution.Parsec.Error.PError) => GHC.Show.Show (Cabal.Parse.ParseError f)
+ Cabal.Project: [prjOtherFields] :: Project uri opt pkg -> [PrettyField ()]
+ Cabal.Project: instance (Control.DeepSeq.NFData c, Control.DeepSeq.NFData b, Control.DeepSeq.NFData a) => Control.DeepSeq.NFData (Cabal.Project.Project c b a)
+ Cabal.SourceRepo: instance Control.DeepSeq.NFData (f GHC.IO.FilePath) => Control.DeepSeq.NFData (Cabal.SourceRepo.SourceRepositoryPackage f)
- Cabal.Config: parseConfig :: FilePath -> ByteString -> Either ParseError (Config Maybe)
+ Cabal.Config: parseConfig :: FilePath -> ByteString -> Either (ParseError NonEmpty) (Config Maybe)
- Cabal.Package: parsePackage :: FilePath -> ByteString -> Either ParseError GenericPackageDescription
+ Cabal.Package: parsePackage :: FilePath -> ByteString -> Either (ParseError NonEmpty) GenericPackageDescription
- Cabal.Parse: ParseError :: FilePath -> ByteString -> [PError] -> [PWarning] -> ParseError
+ Cabal.Parse: ParseError :: FilePath -> ByteString -> f PError -> [PWarning] -> ParseError f
- Cabal.Parse: [peContents] :: ParseError -> ByteString
+ Cabal.Parse: [peContents] :: ParseError f -> ByteString
- Cabal.Parse: [peErrors] :: ParseError -> [PError]
+ Cabal.Parse: [peErrors] :: ParseError f -> f PError
- Cabal.Parse: [peFilename] :: ParseError -> FilePath
+ Cabal.Parse: [peFilename] :: ParseError f -> FilePath
- Cabal.Parse: [peWarnings] :: ParseError -> [PWarning]
+ Cabal.Parse: [peWarnings] :: ParseError f -> [PWarning]
- Cabal.Parse: data ParseError
+ Cabal.Parse: data ParseError f
- Cabal.Parse: parseWith :: ([Field Position] -> ParseResult a) -> FilePath -> ByteString -> Either ParseError a
+ Cabal.Parse: parseWith :: ([Field Position] -> ParseResult a) -> FilePath -> ByteString -> Either (ParseError NonEmpty) a
- Cabal.Parse: renderParseError :: ParseError -> String
+ Cabal.Parse: renderParseError :: Foldable f => ParseError f -> String
- Cabal.Project: parseProject :: FilePath -> ByteString -> Either ParseError (Project Void String String)
+ Cabal.Project: parseProject :: FilePath -> ByteString -> Either (ParseError NonEmpty) (Project Void String String)
- Cabal.Project: readPackagesOfProject :: Project uri opt FilePath -> IO (Either ParseError (Project uri opt (FilePath, GenericPackageDescription)))
+ Cabal.Project: readPackagesOfProject :: Project uri opt FilePath -> IO (Either (ParseError NonEmpty) (Project uri opt (FilePath, GenericPackageDescription)))

Files

Changelog.md view
@@ -1,3 +1,16 @@+## 0.3++- Require `Cabal-3.2`.+- Rename `prjOrigFields` to `prjOtherFields` to reflect its intended purpose:+  contain all fields of a `cabal.project` file that are not already covered by+  a different field of `Project`, such as `prjPackages`, `prjOptPackages`,+  `prjSourceRepos`, etc. The semantics of `parseProject` have also been changed+  accordingly, so `Project`s produced by `parseProject` will no longer have+  `prjOtherFields` entries that overlap with other `Project` fields.+- `ParseError` from `Cabal.Parse` now parameterizes the list type used in+  `peErrors`. Most of the time, this will be instantiated to `NonEmpty`.+- Add `NFData` instances+ ## 0.2  Add `repoSecure` field to `Repo` in `Cabal.Config`.
+ bench/Bench.hs view
@@ -0,0 +1,14 @@+module Main (main) where++import Criterion.Main (defaultMain, bench, nf, env)++import qualified Cabal.Project as C+import qualified Data.ByteString as BS++main :: IO ()+main = defaultMain+    [ env (BS.readFile path ) $ \contents ->+        bench "haskell-ci.project" $ nf (C.parseProject path) contents+    ]+  where+    path = "fixtures/haskell-ci.project"
cabal-install-parsers.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.2 name:               cabal-install-parsers-version:            0.2+version:            0.3 synopsis:           Utilities to work with cabal-install files description:   @cabal-install-parsers@ provides parsers for @cabal-install@ files:@@ -20,7 +20,7 @@ maintainer:         hvr@gnu.org, oleg.grenrus@iki.fi category:           Development build-type:         Simple-tested-with:        GHC ==8.2.2 || ==8.4.4 || ==8.6.5 || ==8.8.1+tested-with:        GHC ==8.2.2 || ==8.4.4 || ==8.6.5 || ==8.8.3 || ==8.10.1 extra-source-files:   Changelog.md   fixtures/*.project@@ -49,11 +49,12 @@    -- GHC-boot libraries   build-depends:-    , base          >=4.10     && <4.14+    , base          >=4.10     && <4.15     , binary        ^>=0.8.5     , bytestring    ^>=0.10.8.1-    , Cabal         ^>=3.0.0.0+    , Cabal         ^>=3.2.0.0     , containers    ^>=0.5.7.1 || ^>=0.6.0.1+    , deepseq       ^>=1.4.2.0     , directory     ^>=1.3.0.0     , filepath      ^>=1.4.1.1     , parsec        ^>=3.1.13.0@@ -108,6 +109,7 @@     , containers     , directory     , filepath+    , pretty    -- dependencies needing explicit constraints   build-depends:@@ -115,3 +117,23 @@     , tasty          ^>=1.2.3     , tasty-golden   ^>=2.3.1.1     , tree-diff      ^>=0.1++benchmark cabal-parsers-bench+  default-language: Haskell2010+  type:             exitcode-stdio-1.0+  main-is:          Bench.hs+  hs-source-dirs:   bench++  -- inherited constraints+  build-depends:+    , base+    , bytestring+    , Cabal+    , cabal-install-parsers+    , containers+    , directory+    , filepath++  -- dependencies needing explicit constraints+  build-depends:+    , criterion ^>=1.5.6.1
fixtures/haskell-ci.golden view
@@ -2,9 +2,15 @@   {prjAllowNewer = [],    prjConstraints = [],    prjMaxBackjumps = Nothing,-   prjOptPackages = [],+   prjOptPackages = ["cabal-parsers"],    prjOptimization = OptimizationOn,-   prjPackages = [".", "cabal-parsers"],+   prjOtherFields = [PrettyField "tests" "true",+                     PrettySection+                       "package"+                       ["haskell-ci"]+                       [PrettyField "ghc-options" "-Wall",+                        PrettyField "ghc-options" "-Werror"]],+   prjPackages = ["."],    prjReorderGoals = False,    prjSourceRepos = [],    prjUriPackages = []}
fixtures/haskell-ci.project view
@@ -2,7 +2,7 @@ -- Consult http://cabal.readthedocs.io/en/latest/nix-local-build.html for more information  packages: .-packages: cabal-parsers+optional-packages: cabal-parsers  tests: true 
src/Cabal/Config.hs view
@@ -17,11 +17,13 @@     hackageHaskellOrg,     ) where +import Control.DeepSeq          (NFData (..)) import Control.Exception        (throwIO) import Data.ByteString          (ByteString) import Data.Function            ((&)) import Data.Functor.Identity    (Identity (..)) import Data.List                (foldl')+import Data.List.NonEmpty       (NonEmpty) import Data.Map                 (Map) import Data.Maybe               (fromMaybe) import Distribution.Compat.Lens (LensLike', over)@@ -91,6 +93,9 @@  deriving instance Show (f FilePath) => Show (Config f) +-- | @since 0.2.1+instance NFData (f FilePath) => NFData (Config f)+ -- | Repository. -- -- missing @root-keys@, @key-threshold@ which we don't need now.@@ -99,11 +104,14 @@     { repoURL    :: URI     , repoSecure :: Bool -- ^ @since 0.2     }-  deriving (Show)+  deriving (Show, Generic)  -- | Repository name, bare 'String'. type RepoName = String +-- | @since 0.2.1+instance NFData Repo+ ------------------------------------------------------------------------------- -- Finding index -------------------------------------------------------------------------------@@ -127,7 +135,7 @@ -------------------------------------------------------------------------------  -- | Parse @~\/.cabal\/config@ file.-parseConfig :: FilePath -> ByteString -> Either ParseError (Config Maybe)+parseConfig :: FilePath -> ByteString -> Either (ParseError NonEmpty) (Config Maybe) parseConfig = parseWith $ \fields0 -> do     let (fields1, sections) = C.partitionFields fields0     let fields2 = M.filterWithKey (\k _ -> k `elem` knownFields) fields1
src/Cabal/Optimization.hs view
@@ -7,6 +7,7 @@     ) where  import Control.Applicative (Alternative (..))+import Control.DeepSeq     (NFData (..)) import GHC.Generics        (Generic)  import qualified Distribution.Compat.CharParsing as C@@ -34,3 +35,6 @@     pretty OptimizationOn        = C.pretty True     pretty OptimizationOff       = C.pretty False     pretty (OptimizationLevel l) = PP.int l++-- | @since 0.2.1+instance NFData Optimization
src/Cabal/Package.hs view
@@ -5,6 +5,7 @@  import Control.Exception            (throwIO) import Data.ByteString              (ByteString)+import Data.List.NonEmpty           (NonEmpty)  import qualified Data.ByteString                        as BS import qualified Distribution.Fields                    as C@@ -23,7 +24,7 @@     either throwIO return (parsePackage fp contents)  -- | Parse @.cabal@ file.-parsePackage :: FilePath -> ByteString -> Either ParseError C.GenericPackageDescription+parsePackage :: FilePath -> ByteString -> Either (ParseError NonEmpty) C.GenericPackageDescription parsePackage fp contents = case C.runParseResult $ C.parseGenericPackageDescription contents of     (ws, Left (_mv, errs)) -> Left $ ParseError fp contents errs ws     (_, Right gpd)         -> Right gpd
src/Cabal/Parse.hs view
@@ -1,3 +1,6 @@+{-# LANGUAGE DeriveGeneric        #-}+{-# LANGUAGE StandaloneDeriving   #-}+{-# LANGUAGE UndecidableInstances #-} -- | License: GPL-3.0-or-later AND BSD-3-Clause -- -- @.cabal@ and a like file parsing helpers.@@ -7,10 +10,14 @@     renderParseError,     ) where +import Control.DeepSeq           (NFData (..)) import Control.Exception         (Exception (..)) import Data.ByteString           (ByteString) import Data.Foldable             (for_)+import Data.List.NonEmpty        (NonEmpty)+import Data.Typeable             (Typeable) import Distribution.Simple.Utils (fromUTF8BS)+import GHC.Generics              (Generic) import System.FilePath           (normalise)  import qualified Data.ByteString.Char8          as BS8@@ -28,7 +35,7 @@     :: ([C.Field C.Position] -> C.ParseResult a)  -- ^ parse     -> FilePath                                   -- ^ filename     -> ByteString                                 -- ^ contents-    -> Either ParseError a+    -> Either (ParseError NonEmpty) a parseWith parser fp bs = case C.runParseResult result of     (_, Right x)       -> return x     (ws, Left (_, es)) -> Left $ ParseError fp bs es ws@@ -44,19 +51,24 @@             parser fields  -- | Parse error.-data ParseError = ParseError+data ParseError f = ParseError     { peFilename :: FilePath     , peContents :: ByteString-    , peErrors   :: [C.PError]+    , peErrors   :: f C.PError     , peWarnings :: [C.PWarning]     }-  deriving (Show)+  deriving (Generic) -instance Exception ParseError where+deriving instance (Show (f C.PError)) => Show (ParseError f)++instance (Foldable f, Show (f C.PError), Typeable f) => Exception (ParseError f) where     displayException = renderParseError +-- | @since 0.2.1+instance (NFData (f C.PError)) => NFData (ParseError f)+ -- | Render parse error highlighting the part of the input file.-renderParseError :: ParseError -> String+renderParseError :: Foldable f => ParseError f -> String renderParseError (ParseError filepath contents errors warnings)     | null errors && null warnings = ""     | null errors = unlines $
src/Cabal/Project.hs view
@@ -22,6 +22,7 @@     readPackagesOfProject     ) where +import Control.DeepSeq              (NFData (..)) import Control.Exception            (Exception (..), throwIO) import Control.Monad.IO.Class       (liftIO) import Control.Monad.Trans.Except   (ExceptT, runExceptT, throwE)@@ -34,6 +35,7 @@ import Data.Function                ((&)) import Data.Functor                 (void) import Data.List                    (foldl')+import Data.List.NonEmpty           (NonEmpty) import Data.Traversable             (for) import Data.Void                    (Void) import Distribution.Compat.Lens     (LensLike', over)@@ -77,11 +79,11 @@     , prjMaxBackjumps :: Maybe Int     , prjOptimization :: Optimization     , prjSourceRepos  :: [SourceRepositoryPackage Maybe]-    , prjOrigFields   :: [C.PrettyField ()] -- ^ original fields+    , prjOtherFields  :: [C.PrettyField ()] -- ^ other fields     }   deriving (Functor, Foldable, Traversable, Generic) --- | Doesn't compare prjOrigFields+-- | Doesn't compare prjOtherFields instance (Eq uri, Eq opt, Eq pkg) => Eq (Project uri opt pkg) where     x == y = and         [ eqOn prjPackages@@ -120,6 +122,24 @@ emptyProject :: Project c b a emptyProject = Project [] [] [] [] [] False Nothing OptimizationOn [] [] +-- | @since 0.2.1+instance (NFData c, NFData b, NFData a) => NFData (Project c b a) where+    rnf (Project x1 x2 x3 x4 x5 x6 x7 x8 x9 x10) =+        rnf x1 `seq` rnf x2 `seq` rnf x3 `seq`+        rnf x4 `seq` rnf x5 `seq` rnf x6 `seq`+        rnf x7 `seq` rnf x8 `seq` rnf x9 `seq`+        rnfList rnfPrettyField x10+      where+        rnfList :: (a -> ()) -> [a] -> ()+        rnfList _ []     = ()+        rnfList f (x:xs) = f x `seq` rnfList f xs++        rnfPrettyField :: NFData x => C.PrettyField x -> ()+        rnfPrettyField (C.PrettyField ann fn d) =+            rnf ann `seq` rnf fn `seq` rnf d+        rnfPrettyField (C.PrettySection ann fn ds fs) =+            rnf ann `seq` rnf fn `seq` rnf ds `seq` rnfList rnfPrettyField fs+ ------------------------------------------------------------------------------- -- Initial  parsing -------------------------------------------------------------------------------@@ -141,7 +161,7 @@ -- >>> fmap prjPackages $ parseProject "cabal.project" "packages: foo bar/*.cabal" -- Right ["foo","bar/*.cabal"] ---parseProject :: FilePath -> ByteString -> Either ParseError (Project Void String String)+parseProject :: FilePath -> ByteString -> Either (ParseError NonEmpty) (Project Void String String) parseProject = parseWith $ \fields0 -> do     let (fields1, sections) = C.partitionFields fields0     let fields2  = M.filterWithKey (\k _ -> k `elem` knownFields) fields1@@ -149,9 +169,9 @@   where     knownFields = C.fieldGrammarKnownFieldList $ grammar [] -    parse origFields fields sections = do-        let prettyOrigFields = map void $ C.fromParsecFields $ filter notPackages origFields-        prj <- C.parseFieldGrammar C.cabalSpecLatest fields $ grammar prettyOrigFields+    parse otherFields fields sections = do+        let prettyOtherFields = map void $ C.fromParsecFields $ filter otherFieldName otherFields+        prj <- C.parseFieldGrammar C.cabalSpecLatest fields $ grammar prettyOtherFields         foldl' (&) prj <$> traverse parseSec (concat sections)      parseSec :: C.Section C.Position -> C.ParseResult (Project Void String String -> Project Void String String)@@ -162,12 +182,12 @@      parseSec _ = return id -notPackages :: C.Field ann -> Bool-notPackages (C.Field (C.Name _ "packages") _) = False-notPackages _                                 = True+otherFieldName :: C.Field ann -> Bool+otherFieldName (C.Field (C.Name _ fn) _) = fn `notElem` C.fieldGrammarKnownFieldList (grammar [])+otherFieldName _                         = True  grammar :: [C.PrettyField ()] -> C.ParsecFieldGrammar (Project Void String String) (Project Void String String)-grammar origFields = Project+grammar otherFields = Project     <$> C.monoidalFieldAla "packages"          (C.alaList' C.FSep PackageLocation) prjPackagesL     <*> C.monoidalFieldAla "optional-packages" (C.alaList' C.FSep PackageLocation) prjOptPackagesL     <*> pure []@@ -177,7 +197,7 @@     <*> C.optionalFieldAla "max-backjumps"     Int'                                prjMaxBackjumpsL     <*> C.optionalFieldDef "optimization"                                          prjOptimizationL OptimizationOn     <*> pure []-    <*> pure origFields+    <*> pure otherFields  ------------------------------------------------------------------------------- -- Lenses@@ -293,7 +313,7 @@ -- -- May throw 'IOException'. ---readPackagesOfProject :: Project uri opt FilePath -> IO (Either ParseError (Project uri opt (FilePath, C.GenericPackageDescription)))+readPackagesOfProject :: Project uri opt FilePath -> IO (Either (ParseError NonEmpty) (Project uri opt (FilePath, C.GenericPackageDescription))) readPackagesOfProject prj = runExceptT $ for prj $ \fp -> do     contents <- liftIO $ BS.readFile fp     either throwE (\gpd -> return (fp, gpd)) (parsePackage fp contents)
src/Cabal/SourceRepo.hs view
@@ -20,6 +20,7 @@     sourceRepositoryPackageGrammar,     ) where +import Control.DeepSeq    (NFData (..)) import Data.List.NonEmpty (NonEmpty (..)) import Data.Proxy         (Proxy (..)) import GHC.Generics       (Generic)@@ -43,6 +44,9 @@ deriving instance (Eq (f FilePath)) => Eq (SourceRepositoryPackage f) deriving instance (Ord (f FilePath)) => Ord (SourceRepositoryPackage f) deriving instance (Show (f FilePath)) => Show (SourceRepositoryPackage f)++-- | @since 0.2.1+instance NFData (f FilePath) => NFData (SourceRepositoryPackage f)  -- | Read from @cabal.project@ type SourceRepoList  = SourceRepositoryPackage []
test/Golden.hs view
@@ -6,10 +6,12 @@ import System.FilePath            ((-<.>), (</>)) import Test.Tasty                 (TestName, TestTree, defaultMain, testGroup) import Test.Tasty.Golden.Advanced (goldenTest)+import Text.PrettyPrint           (Doc, render)  import qualified Data.ByteString as BS import qualified Data.Map.Strict as Map +import Distribution.Fields (PrettyField(..)) import Distribution.Types.SourceRepo (RepoKind, RepoType, SourceRepo)  import Cabal.Optimization@@ -33,7 +35,6 @@ -- orphans ------------------------------------------------------------------------------- --- skip orig fields instance (ToExpr uri, ToExpr opt, ToExpr pkg) => ToExpr (Project uri opt pkg) where     toExpr prj = Rec "Project" $ Map.fromList         [ field "prjPackages"     prjPackages@@ -45,6 +46,7 @@         , field "prjMaxBackjumps" prjMaxBackjumps         , field "prjOptimization" prjOptimization         , field "prjSourceRepos"  prjSourceRepos+        , field "prjOtherFields"  prjOtherFields         ]       where         field name f = (name, toExpr (f prj))@@ -55,3 +57,10 @@ instance ToExpr RepoKind instance ToExpr RepoType instance ToExpr (f FilePath) => ToExpr (SourceRepositoryPackage f)++instance ToExpr Doc where+  toExpr = toExpr . render++instance ToExpr (PrettyField ann) where+  toExpr (PrettyField _ fn d)       = App "PrettyField"   [toExpr fn, toExpr d]+  toExpr (PrettySection _ fn ds ps) = App "PrettySection" [toExpr fn, toExpr ds, toExpr ps]