packages feed

hpack 0.16.0 → 0.17.0

raw patch · 7 files changed

+167/−206 lines, 7 filesnew-uploaderPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Hpack.Config: CustomSetup :: [Dependency] -> CustomSetup
+ Hpack.Config: [customSetupDependencies] :: CustomSetup -> [Dependency]
+ Hpack.Config: [packageCustomSetup] :: Package -> Maybe CustomSetup
+ Hpack.Config: data CustomSetup
+ Hpack.Config: instance Data.Aeson.Types.FromJSON.FromJSON (Hpack.Config.CaptureUnknownFields Hpack.Config.CustomSetupSection)
+ Hpack.Config: instance Data.Aeson.Types.FromJSON.FromJSON Hpack.Config.CustomSetupSection
+ Hpack.Config: instance GHC.Classes.Eq Hpack.Config.CustomSetup
+ Hpack.Config: instance GHC.Classes.Eq Hpack.Config.CustomSetupSection
+ Hpack.Config: instance GHC.Generics.Generic Hpack.Config.CustomSetupSection
+ Hpack.Config: instance GHC.Show.Show Hpack.Config.CustomSetup
+ Hpack.Config: instance GHC.Show.Show Hpack.Config.CustomSetupSection
+ Hpack.Config: instance Hpack.Config.HasFieldNames Hpack.Config.CustomSetupSection
- Hpack.Config: Package :: String -> String -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> [String] -> [String] -> [String] -> BuildType -> Maybe String -> Maybe FilePath -> Maybe String -> [Flag] -> [FilePath] -> [FilePath] -> Maybe SourceRepository -> Maybe (Section Library) -> [Section Executable] -> [Section Executable] -> [Section Executable] -> Package
+ Hpack.Config: Package :: String -> String -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> [String] -> [String] -> [String] -> BuildType -> Maybe String -> Maybe FilePath -> Maybe String -> [Flag] -> [FilePath] -> [FilePath] -> Maybe SourceRepository -> Maybe CustomSetup -> Maybe (Section Library) -> [Section Executable] -> [Section Executable] -> [Section Executable] -> Package

Files

− README.md
@@ -1,192 +0,0 @@-# hpack: An alternative format for Haskell packages--## Examples-- * Given this [package.yaml](https://github.com/sol/hpack/blob/master/package.yaml) running `hpack` will generate [hpack.cabal](https://github.com/sol/hpack/blob/master/hpack.cabal)- * Given this [package.yaml](https://github.com/zalora/getopt-generics/blob/master/package.yaml) running `hpack` will generate [getopt-generics.cabal](https://github.com/zalora/getopt-generics/blob/master/getopt-generics.cabal)- * Given this [package.yaml](https://github.com/hspec/sensei/blob/master/package.yaml) running `hpack` will generate [sensei.cabal](https://github.com/hspec/sensei/blob/master/sensei.cabal)- * Given this [package.yaml](https://github.com/haskell-compat/base-orphans/blob/master/package.yaml) running `hpack` will generate [base-orphans.cabal](https://github.com/haskell-compat/base-orphans/blob/master/base-orphans.cabal)--## Documentation--### Getting started--One easy way of getting started is to use-[hpack-convert](http://hackage.haskell.org/package/hpack-convert) to convert an-existing cabal file into a `package.yaml`.--### Quick-reference--#### Top-level fields--| Hpack | Cabal | Default | Notes | Example |-| --- | --- | --- | --- | --- |-| `name` | `name` | | | |-| `version` | `version` | `0.0.0` | | |-| `synopsis` | `synopsis` | | | |-| `description` | `description` | | | |-| `category` | `category` | | | |-| `stability` | `stability` | | | |-| `homepage` | `homepage` | If `github` given, `<repo>#readme` | | |-| `bug-reports` | `bug-reports` | If `github` given, `<repo>/issues` | | |-| `author` | `author` | | May be a list | |-| `maintainer` | `maintainer` | | May be a list | |-| `copyright` | `copyright` | | May be a list |-| `license` | `license` | | | |-| `license-file` | `license-file` | `LICENSE` if file exists | | |-| `tested-with` | `tested-with` | | | |-| `build-type` | `build-type` | `Simple` | Must be `Simple`, `Configure`, `Make`, or `Custom` | |-| | `cabal-version` | `>= 1.10` or `>= 1.21` | `>= 1.21` if library component has `reexported-modules` field | |-| `extra-source-files` | `extra-source-files` | | Accepts [glob patterns](#file-globbing) | |-| `data-files` | `data-files` | | Accepts [glob patterns](#file-globbing) | |-| `github` | `source-repository head` | | Accepts `user/repo` or `user/repo/subdir` | `github: foo/bar`-| `git`    | `source-repository head` | | No effect if `github` given | `git: https://my.repo.com/foo` |-| `flags`  | `flag <name>` | | Map from flag name to flag (see [Flags](#flags)) | |-| `library` | `library` | | See [Library fields](#library-fields) | |-| `executables` | `executable <name>` | | Map from executable name to executable (see [Executable fields](#executable-fields)) | |-| `tests` | `test-suite <name>` | | Map from test name to test (see [Test fields](#test-fields)) | |-| `benchmarks` | `benchmark <name>` | | Map from benchmark name to benchmark (see [Benchmark fields](#benchmark-fields)) | |--#### Global top-level fields--These fields are merged with all library, executable, test, and benchmark components.--| Hpack | Cabal | Default | Notes |-| --- | --- | --- | --- |-| `source-dirs` | `hs-source-dirs` | | |-| `default-extensions` | `default-extensions` | | |-| `other-extension` | `other-extensions` | | |-| `ghc-options` | `ghc-options` | | |-| `ghc-prof-options` | `ghc-prof-options` | | |-| `cpp-options` | `cpp-options` | | |-| `cc-options` | `cc-options` | | |-| `c-sources` | `c-sources` | | |-| `extra-lib-dirs` | `extra-lib-dirs` | | |-| `extra-libraries` | `extra-libraries` | | |-| `include-dirs` | `include-dirs` | | |-| `install-includes` | `install-includes` | | |-| `ld-options` | `ld-options` | | |-| `buildable` | `buildable` | | May be overridden by later stanza |-| `dependencies` | `build-depends` | | |-| `build-tools` | `build-tools` | | |-| `when` | | | Accepts a list of conditionals (see [Conditionals](#conditionals)) |--#### <a name="library-fields"></a>Library fields--| Hpack | Cabal | Default | Notes |-| --- | --- | --- | --- |-| `exposed` | `exposed` | | |-| `exposed-modules` | `exposed-modules` | All modules in `source-dirs` less `other-modules` | |-| `other-modules` | `other-modules` | All modules in `source-dirs` less `exposed-modules` | |-| `reexported-modules` | `reexported-modules` | | |-| | `default-language` | `Haskell2010` | |--#### <a name="executable-fields"></a>Executable fields--| Hpack | Cabal | Default | Notes |-| --- | --- | --- | --- |-| `main` | `main-is` | | |-| `other-modules` | `other-modules` | | |-| | `default-language` | `Haskell2010` | |--#### <a name="test-fields"></a>Test fields--| Hpack | Cabal | Default | Notes |-| --- | --- | --- | --- |-| | `type` | `exitcode-stdio-1.0` | |-| `main` | `main-is` | | |-| `other-modules` | `other-modules` | | |-| | `default-language` | `Haskell2010` | |--#### <a name="benchmark-fields"></a>Benchmark fields--| Hpack | Cabal | Default | Notes |-| --- | --- | --- | --- |-| | `type` | `exitcode-stdio-1.0` | |-| `main` | `main-is` | | |-| `other-modules` | `other-modules` | | |-| | `default-language` | `Haskell2010` | |--#### <a name="flags"></a>Flags--| Hpack | Cabal | Default | Notes |-| --- | --- | --- | --- |-| `description` | `description` | | Optional |-| `manual` | `manual` | | Required (unlike Cabal) |-| `default` | `default` | | Required (unlike Cabal) |--#### <a name="conditionals"></a> Conditionals--Conditionals with no else branch:--- Must have a `condition` field-- May have any number of other fields--For example,--    when:-      - condition: os(darwin)-        extra-lib-dirs: lib/darwin--becomes--    if os(darwin)-      extra-lib-dirs:-        lib/darwin--Conditionals with an else branch:--- Must have a `condition` field-- Must have a `then` field, itself an object containing any number of other fields-- Must have a `else` field, itself an object containing any number of other fields-- All other top-level fields are ignored--For example,--    when:-      - condition: flag(fast)-        then:-          ghc-options: -O2-        else:-          ghc-options: -O0--becomes--    if flag(fast)-      ghc-options: -O2-    else-      ghc-options: -O0---### <a name="file-globbing"></a>File globbing--At place where you can specify a list of files you can also use glob patterns.-Glob patters and ordinary file names can be freely mixed, e.g.:--```yaml-extra-source-files:-  - static/*.js-  - static/site.css-```--Glob patterns are expanded according to the following rules:-- - `?` and `*` are expanded according to POSIX (they match arbitrary-   characters, except for directory separators)- - `**` is expanded in a `zsh`-like fashion (matching across directory-   separators)- - `?`, `*` and `**` do not match a `.` at the beginning of a file/directory--### Slides-- - Slides from my talk about `hpack` at the Singapore Haskell meetup:-   http://typeful.net/talks/hpack--## Vim integration--To run `hpack` automatically on modifications to `package.yaml` add the-following to your `~/.vimrc`:--```vim-autocmd BufWritePost package.yaml silent !hpack --silent-```
hpack.cabal view
@@ -3,8 +3,9 @@ -- see: https://github.com/sol/hpack  name:           hpack-version:        0.16.0+version:        0.17.0 synopsis:       An alternative format for Haskell packages+description:    See README at <https://github.com/sol/hpack#readme> category:       Development homepage:       https://github.com/sol/hpack#readme bug-reports:    https://github.com/sol/hpack/issues@@ -14,9 +15,6 @@ build-type:     Simple cabal-version:  >= 1.10 -extra-source-files:-    README.md- source-repository head   type: git   location: https://github.com/sol/hpack@@ -78,7 +76,7 @@   main-is: Spec.hs   hs-source-dirs:       test-      src+    , src   ghc-options: -Wall   cpp-options: -DTEST   build-depends:
src/Hpack/Config.hs view
@@ -24,6 +24,7 @@ , GitUrl , GitRef , GhcOption+, CustomSetup(..) , Section(..) , Library(..) , Executable(..)@@ -48,7 +49,7 @@ import           Data.Map.Lazy (Map) import qualified Data.Map.Lazy as Map import qualified Data.HashMap.Lazy as HashMap-import           Data.List.Compat (nub, (\\), sortBy)+import           Data.List.Compat (nub, (\\), sortBy, isPrefixOf) import           Data.Maybe import           Data.Ord import           Data.String@@ -65,7 +66,32 @@ import           Hpack.Yaml  package :: String -> String -> Package-package name version = Package name version Nothing Nothing Nothing Nothing Nothing Nothing [] [] [] Simple Nothing Nothing Nothing [] [] [] Nothing Nothing [] [] []+package name version = Package {+    packageName = name+  , packageVersion = version+  , packageSynopsis = Nothing+  , packageDescription = Nothing+  , packageHomepage = Nothing+  , packageBugReports = Nothing+  , packageCategory = Nothing+  , packageStability = Nothing+  , packageAuthor = []+  , packageMaintainer = []+  , packageCopyright = []+  , packageBuildType = Simple+  , packageLicense = Nothing+  , packageLicenseFile = Nothing+  , packageTestedWith = Nothing+  , packageFlags = []+  , packageExtraSourceFiles = []+  , packageDataFiles = []+  , packageSourceRepository = Nothing+  , packageCustomSetup = Nothing+  , packageLibrary = Nothing+  , packageExecutables = []+  , packageTests = []+  , packageBenchmarks = []+  }  renamePackage :: String -> Package -> Package renamePackage name p@Package{..} = p {@@ -128,6 +154,9 @@   default fieldNames :: (HasTypeName a, Selectors (Rep a)) => Proxy a -> [String]   fieldNames proxy = map (hyphenize $ typeName proxy) (selectors proxy) +  ignoreUnderscoredUnknownFields :: Proxy a -> Bool+  ignoreUnderscoredUnknownFields _ = False+ data CaptureUnknownFields a = CaptureUnknownFields {   captureUnknownFieldsFields :: [FieldName] , captureUnknownFieldsValue :: a@@ -145,18 +174,33 @@     where       unknownSectionFields = getUnknownFields v (Proxy :: Proxy (Section a)) +instance FromJSON (CaptureUnknownFields CustomSetupSection) where+  parseJSON = captureUnknownFields+ instance FromJSON (CaptureUnknownFields FlagSection) where   parseJSON = captureUnknownFields  getUnknownFields :: forall a. HasFieldNames a => Value -> Proxy a -> [FieldName] getUnknownFields v _ = case v of-  Object o -> unknown+  Object o -> ignoreUnderscored unknown     where       unknown = keys \\ fields       keys = map T.unpack (HashMap.keys o)       fields = fieldNames (Proxy :: Proxy a)+      ignoreUnderscored+        | ignoreUnderscoredUnknownFields (Proxy :: Proxy a) = filter (not . isPrefixOf "_")+        | otherwise = id   _ -> [] +data CustomSetupSection = CustomSetupSection {+  customSetupSectionDependencies :: Maybe (List Dependency)+} deriving (Eq, Show, Generic)++instance HasFieldNames CustomSetupSection++instance FromJSON CustomSetupSection where+  parseJSON = genericParseJSON_+ data LibrarySection = LibrarySection {   librarySectionExposed :: Maybe Bool , librarySectionExposedModules :: Maybe (List String)@@ -285,13 +329,15 @@ , packageConfigDataFiles :: Maybe (List FilePath) , packageConfigGithub :: Maybe Text , packageConfigGit :: Maybe String+, packageConfigCustomSetup :: Maybe (CaptureUnknownFields CustomSetupSection) , packageConfigLibrary :: Maybe (CaptureUnknownFields (Section LibrarySection)) , packageConfigExecutables :: Maybe (Map String (CaptureUnknownFields (Section ExecutableSection))) , packageConfigTests :: Maybe (Map String (CaptureUnknownFields (Section ExecutableSection))) , packageConfigBenchmarks :: Maybe (Map String (CaptureUnknownFields (Section ExecutableSection))) } deriving (Eq, Show, Generic) -instance HasFieldNames PackageConfig+instance HasFieldNames PackageConfig where+  ignoreUnderscoredUnknownFields _ = True  instance FromJSON PackageConfig where   parseJSON value = handleNullValues <$> genericParseJSON_ value@@ -385,12 +431,17 @@ , packageExtraSourceFiles :: [FilePath] , packageDataFiles :: [FilePath] , packageSourceRepository :: Maybe SourceRepository+, packageCustomSetup :: Maybe CustomSetup , packageLibrary :: Maybe (Section Library) , packageExecutables :: [Section Executable] , packageTests :: [Section Executable] , packageBenchmarks :: [Section Executable] } deriving (Eq, Show) +data CustomSetup = CustomSetup {+  customSetupDependencies :: [Dependency]+} deriving (Eq, Show)+ data Library = Library {   libraryExposed :: Maybe Bool , libraryExposedModules :: [String]@@ -433,6 +484,7 @@  instance HasFieldNames a => HasFieldNames (Section a) where   fieldNames Proxy = fieldNames (Proxy :: Proxy a) ++ fieldNames (Proxy :: Proxy CommonOptions)+  ignoreUnderscoredUnknownFields _ = ignoreUnderscoredUnknownFields (Proxy :: Proxy a)  data FlagSection = FlagSection {   _flagSectionDescription :: Maybe String@@ -463,12 +515,20 @@ mkPackage :: FilePath -> (CaptureUnknownFields (Section PackageConfig)) -> IO ([String], Package) mkPackage dir (CaptureUnknownFields unknownFields globalOptions@Section{sectionData = PackageConfig{..}}) = do   let+    nameWarnings :: [String]+    name :: String     (nameWarnings, name) = maybe (["Package name not specified, inferred " ++ show inferredName], inferredName) ((,) []) packageConfigName       where inferredName = takeBaseName dir +    mCustomSetup :: Maybe CustomSetup+    mCustomSetup = toCustomSetup <$> mCustomSetupSection+   libraryResult <- mapM (toLibrary dir name globalOptions) mLibrarySection   let+    mLibrary :: Maybe (Section Library)     mLibrary = fmap snd libraryResult++    libraryWarnings :: [String]     libraryWarnings = maybe [] fst libraryResult    (executablesWarnings, executables) <- toExecutables dir globalOptions (map (fmap captureUnknownFieldsValue) executableSections)@@ -490,7 +550,10 @@   (dataFilesWarnings, dataFiles) <-     expandGlobs "data-files" dir (fromMaybeList packageConfigDataFiles) -  let pkg = Package {+  let defaultBuildType :: BuildType+      defaultBuildType = maybe Simple (const Custom) mCustomSetup++      pkg = Package {         packageName = name       , packageVersion = fromMaybe "0.0.0" packageConfigVersion       , packageSynopsis = packageConfigSynopsis@@ -502,7 +565,7 @@       , packageAuthor = fromMaybeList packageConfigAuthor       , packageMaintainer = fromMaybeList packageConfigMaintainer       , packageCopyright = fromMaybeList packageConfigCopyright-      , packageBuildType = fromMaybe Simple packageConfigBuildType+      , packageBuildType = fromMaybe defaultBuildType packageConfigBuildType       , packageLicense = packageConfigLicense       , packageLicenseFile = packageConfigLicenseFile <|> (guard licenseFileExists >> Just "LICENSE")       , packageTestedWith = packageConfigTestedWith@@ -510,6 +573,7 @@       , packageExtraSourceFiles = extraSourceFiles       , packageDataFiles = dataFiles       , packageSourceRepository = sourceRepository+      , packageCustomSetup = mCustomSetup       , packageLibrary = mLibrary       , packageExecutables = executables       , packageTests = tests@@ -520,6 +584,7 @@            formatUnknownFields "package description" unknownFields         ++ nameWarnings         ++ flagWarnings+        ++ maybe [] (formatUnknownFields "custom-setup section") (captureUnknownFieldsFields <$> packageConfigCustomSetup)         ++ maybe [] (formatUnknownFields "library section") (captureUnknownFieldsFields <$> packageConfigLibrary)         ++ formatUnknownSectionFields "executable" executableSections         ++ formatUnknownSectionFields "test" testsSections@@ -554,6 +619,9 @@     toList :: Maybe (Map String a) -> [(String, a)]     toList = Map.toList . fromMaybe mempty +    mCustomSetupSection :: Maybe CustomSetupSection+    mCustomSetupSection = captureUnknownFieldsValue <$> packageConfigCustomSetup+     mLibrarySection :: Maybe (Section LibrarySection)     mLibrarySection = captureUnknownFieldsValue <$> packageConfigLibrary @@ -602,6 +670,10 @@ expandCSources dir sect@Section{..} = do   (warnings, files) <- expandGlobs "c-sources" dir sectionCSources   return (warnings, sect {sectionCSources = files})++toCustomSetup :: CustomSetupSection -> CustomSetup+toCustomSetup CustomSetupSection{..} = CustomSetup+  { customSetupDependencies = fromMaybeList customSetupSectionDependencies }  toLibrary :: FilePath -> String -> Section global -> Section LibrarySection -> IO ([String], Section Library) toLibrary dir name globalOptions library = traverse fromLibrarySection sect >>= expandCSources dir
src/Hpack/Run.hs view
@@ -68,8 +68,13 @@     dataFiles :: Element     dataFiles = Field "data-files" (LineSeparatedList packageDataFiles) +    sourceRepository :: [Element]     sourceRepository = maybe [] (return . renderSourceRepository) packageSourceRepository +    customSetup :: [Element]+    customSetup = maybe [] (return . renderCustomSetup) packageCustomSetup++    library :: [Element]     library = maybe [] (return . renderLibrary) packageLibrary      stanzas :: [Element]@@ -78,7 +83,8 @@       : dataFiles       : sourceRepository       ++ concat [-        map renderFlag packageFlags+        customSetup+      , map renderFlag packageFlags       , library       , renderExecutables packageExecutables       , renderTests packageTests@@ -189,6 +195,10 @@     mainIs = Field "main-is" (Literal executableMain)     otherModules = renderOtherModules executableOtherModules +renderCustomSetup :: CustomSetup -> Element+renderCustomSetup CustomSetup{..} =+  Stanza "custom-setup" [renderSetupDepends customSetupDependencies]+ renderLibrary :: Section Library -> Element renderLibrary sect@(sectionData -> Library{..}) = Stanza "library" $   renderSection sect ++@@ -279,3 +289,6 @@  renderBuildTools :: [Dependency] -> Element renderBuildTools = Field "build-tools" . CommaSeparatedList . map dependencyName++renderSetupDepends :: [Dependency] -> Element+renderSetupDepends = Field "setup-depends" . CommaSeparatedList . map dependencyName
src/Hpack/Yaml.hs view
@@ -1,7 +1,8 @@ {-# LANGUAGE RecordWildCards #-} module Hpack.Yaml where -import           Data.Yaml+import           Data.Yaml hiding (decodeFile, decodeFileEither)+import           Data.Yaml.Include  decodeYaml :: FromJSON a => FilePath -> IO (Either String a) decodeYaml file = do
test/Hpack/ConfigSpec.hs view
@@ -309,6 +309,7 @@         name: foo         bar: 23         baz: 42+        _qux: 66         |]         (`shouldBe` [           "Ignoring unknown field \"bar\" in package description"@@ -323,9 +324,11 @@           - condition: impl(ghc)             bar: 23             baz: 42+            _qux: 66         |]         (`shouldBe` [-          "Ignoring unknown field \"bar\" in package description"+          "Ignoring unknown field \"_qux\" in package description"+        , "Ignoring unknown field \"bar\" in package description"         , "Ignoring unknown field \"baz\" in package description"         ]         )@@ -641,6 +644,56 @@         , packageExecutables = [(section $ executable "foo" "Main.hs") {sectionBuildable = Just False}]         }         )++    context "when reading custom-setup section" $ do+      it "warns on unknown fields" $ do+        withPackageWarnings_ [i|+          name: foo+          custom-setup:+            foo: 1+            bar: 2+          |]+          (`shouldBe` [+            "Ignoring unknown field \"bar\" in custom-setup section"+          , "Ignoring unknown field \"foo\" in custom-setup section"+          ])++      it "sets build-type: Custom, if missing" $ do+        withPackageConfig_ [i|+          custom-setup:+            dependencies:+              - base+          |]+          (packageBuildType >>> (`shouldBe` Custom))++      it "leaves build-type alone, if it exists" $ do+        withPackageConfig_ [i|+          name: foo+          build-type: Make+          custom-setup:+            dependencies:+              - base+          |]+          (packageBuildType >>> (`shouldBe` Make))++      it "accepts dependencies" $ do+        withPackageConfig_ [i|+          custom-setup:+            dependencies:+              - foo >1.0+              - bar ==2.0+          |]+          (packageCustomSetup >>> fmap customSetupDependencies >>> (`shouldBe` Just ["foo >1.0", "bar ==2.0"]))++    it "allows yaml merging and overriding fields" $ do+      withPackageConfig_ [i|+        _common: &common+          name: n1++        <<: *common+        name: n2+        |]+        (packageName >>> (`shouldBe` "n2"))      context "when reading library section" $ do       it "warns on unknown fields" $ do
test/Hpack/RunSpec.hs view
@@ -103,6 +103,22 @@         , "  default-language: Haskell2010"         ] +    context "when rendering custom-setup section" $ do+      it "includes setup-depends" $ do+        let setup = CustomSetup+              { customSetupDependencies = ["foo >1.0", "bar ==2.0"] }+        renderPackage_ package {packageCustomSetup = Just setup} `shouldBe` unlines [+            "name: foo"+          , "version: 0.0.0"+          , "build-type: Simple"+          , "cabal-version: >= 1.10"+          , ""+          , "custom-setup"+          , "  setup-depends:"+          , "      foo >1.0"+          , "    , bar ==2.0"+          ]+     context "when rendering library section" $ do       it "renders library section" $ do         renderPackage_ package {packageLibrary = Just $ section library} `shouldBe` unlines [