packages feed

hpack 0.22.0 → 0.23.0

raw patch · 14 files changed

+366/−202 lines, 14 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Hpack: RunOptions :: Maybe FilePath -> FilePath -> (FilePath -> IO (Either String Value)) -> RunOptions
+ Hpack: [runOptionsConfigDir] :: RunOptions -> Maybe FilePath
+ Hpack: [runOptionsConfigFile] :: RunOptions -> FilePath
+ Hpack: [runOptionsDecode] :: RunOptions -> FilePath -> IO (Either String Value)
+ Hpack: data RunOptions
+ Hpack: defaultRunOptions :: RunOptions
+ Hpack: mainWith :: FilePath -> (FilePath -> IO (Either String Value)) -> IO ()
+ Hpack.Config: [executableGeneratedModules] :: Executable -> [String]
+ Hpack.Config: [libraryGeneratedModules] :: Library -> [String]
+ Hpack.Config: readPackageConfigWith :: (FilePath -> IO (Either String Value)) -> FilePath -> FilePath -> IO (Either String (Package, [String]))
+ Hpack.Run: RunOptions :: Maybe FilePath -> FilePath -> (FilePath -> IO (Either String Value)) -> RunOptions
+ Hpack.Run: [runOptionsConfigDir] :: RunOptions -> Maybe FilePath
+ Hpack.Run: [runOptionsConfigFile] :: RunOptions -> FilePath
+ Hpack.Run: [runOptionsDecode] :: RunOptions -> FilePath -> IO (Either String Value)
+ Hpack.Run: data RunOptions
+ Hpack.Run: defaultRunOptions :: RunOptions
- Hpack: hpack :: Maybe FilePath -> Verbose -> Force -> IO ()
+ Hpack: hpack :: RunOptions -> Verbose -> Force -> IO ()
- Hpack: hpackResult :: Maybe FilePath -> Force -> IO Result
+ Hpack: hpackResult :: RunOptions -> Force -> IO Result
- Hpack.Config: Executable :: Maybe FilePath -> [String] -> Executable
+ Hpack.Config: Executable :: Maybe FilePath -> [String] -> [String] -> Executable
- Hpack.Config: Library :: Maybe Bool -> [String] -> [String] -> [String] -> [String] -> Library
+ Hpack.Config: Library :: Maybe Bool -> [String] -> [String] -> [String] -> [String] -> [String] -> Library
- Hpack.Run: run :: Maybe FilePath -> FilePath -> IO ([String], FilePath, String)
+ Hpack.Run: run :: RunOptions -> IO ([String], FilePath, String)

Files

CHANGELOG.md view
@@ -1,4 +1,11 @@-## next+## Changes in 0.23.0+  - Add support for custom decoders to allow for alternate syntax (e.g. Dhall)+  - `generated-exposed-modules` and `generated-other-modules`, for populating+    the `autogen-modules` field (#207).+  - Corrected `cabal-version` setting for `reexported-modules` inside+    a conditional.++## Changes in 0.22.0   - Add support for `defaults`   - Add `--numeric-version`   - Add support for `signatures`
hpack.cabal view
@@ -1,11 +1,11 @@--- This file has been generated from package.yaml by hpack version 0.21.2.+-- This file has been generated from package.yaml by hpack version 0.22.0. -- -- see: https://github.com/sol/hpack ----- hash: ed684f1c6e2ea1bdc1674463da6eeef99a1dd9a3fac6bf2ce309d3d675879539+-- hash: a810403afb86b045741c0bad9d0d0d278cd4582751e39f0912edd62038c29692  name:           hpack-version:        0.22.0+version:        0.23.0 synopsis:       An alternative format for Haskell packages description:    See README at <https://github.com/sol/hpack#readme> category:       Development
src/Hpack.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE CPP #-}+{-# LANGUAGE RecordWildCards #-} module Hpack (   hpack , hpackResult@@ -8,10 +9,12 @@ , Force(..) , version , main+, mainWith+, RunOptions(..)+, defaultRunOptions #ifdef TEST , header , hpackWithVersionResult-, splitDirectory #endif ) where @@ -21,8 +24,7 @@ import           System.Environment import           System.Exit import           System.IO (stderr)-import           System.FilePath-import           System.Directory+import           Data.Aeson (Value)  import           Paths_hpack (version) import           Hpack.Options@@ -31,6 +33,7 @@ import           Hpack.Util import           Hpack.Utf8 as Utf8 import           Hpack.CabalFile+import           Hpack.Yaml  programVersion :: Version -> String programVersion v = "hpack version " ++ Version.showVersion v@@ -46,15 +49,18 @@   ]  main :: IO ()-main = do-  args <- getArgs-  case parseOptions args of+main = mainWith packageConfig decodeYaml++mainWith :: FilePath -> (FilePath -> IO (Either String Value)) -> IO ()+mainWith configFile decode = do+  result <- getArgs >>= parseOptions configFile+  case result of     PrintVersion -> putStrLn (programVersion version)     PrintNumericVersion -> putStrLn (Version.showVersion version)     Help -> printHelp     Run options -> case options of-      Options _verbose _force True dir -> hpackStdOut dir-      Options verbose force False dir -> hpack dir verbose force+      Options _verbose _force True dir file -> hpackStdOut (RunOptions dir file decode)+      Options verbose force False dir file -> hpack (RunOptions dir file decode) verbose force     ParseError -> do       printHelp       exitFailure@@ -67,10 +73,10 @@     , "       hpack --help"     ] -hpack :: Maybe FilePath -> Verbose -> Force -> IO ()+hpack :: RunOptions -> Verbose -> Force -> IO () hpack = hpackWithVersion version -hpackResult :: Maybe FilePath -> Force -> IO Result+hpackResult :: RunOptions -> Force -> IO Result hpackResult = hpackWithVersionResult version  data Result = Result {@@ -86,9 +92,9 @@   | OutputUnchanged   deriving (Eq, Show) -hpackWithVersion :: Version -> Maybe FilePath -> Verbose -> Force -> IO ()-hpackWithVersion v p verbose force = do-    r <- hpackWithVersionResult v p force+hpackWithVersion :: Version -> RunOptions -> Verbose -> Force -> IO ()+hpackWithVersion v options verbose force = do+    r <- hpackWithVersionResult v options force     printWarnings (resultWarnings r)     when (verbose == Verbose) $ putStrLn $       case resultStatus r of@@ -101,17 +107,6 @@ printWarnings warnings = do   forM_ warnings $ \warning -> Utf8.hPutStrLn stderr ("WARNING: " ++ warning) -splitDirectory :: Maybe FilePath -> IO (Maybe FilePath, FilePath)-splitDirectory Nothing = return (Nothing, packageConfig)-splitDirectory (Just p) = do-  isDirectory <- doesDirectoryExist p-  return $ if isDirectory-    then (Just p, packageConfig)-    else let-      file = takeFileName p-      dir = takeDirectory p-      in (guard (p /= file) >> Just dir, if null file then packageConfig else file)- mkStatus :: [String] -> Version -> CabalFile -> Status mkStatus new v (CabalFile mOldVersion mHash old) = case (mOldVersion, mHash) of   (Nothing, _) -> ExistingCabalFileWasModifiedManually@@ -123,10 +118,9 @@     | old == new -> OutputUnchanged     | otherwise -> Generated -hpackWithVersionResult :: Version -> Maybe FilePath -> Force -> IO Result-hpackWithVersionResult v p force = do-  (dir, file) <- splitDirectory p-  (warnings, cabalFile, new) <- run dir file+hpackWithVersionResult :: Version -> RunOptions -> Force -> IO Result+hpackWithVersionResult v options@RunOptions{..} force = do+  (warnings, cabalFile, new) <- run options   oldCabalFile <- readCabalFile cabalFile   let     status = case force of@@ -135,17 +129,16 @@   case status of     Generated -> do       let hash = sha256 new-      Utf8.writeFile cabalFile (header file v hash ++ new)+      Utf8.writeFile cabalFile (header runOptionsConfigFile v hash ++ new)     _ -> return ()-  return Result-    { resultWarnings = warnings+  return Result {+      resultWarnings = warnings     , resultCabalFile = cabalFile     , resultStatus = status     } -hpackStdOut :: Maybe FilePath -> IO ()-hpackStdOut p = do-  (dir, file) <- splitDirectory p-  (warnings, _cabalFile, new) <- run dir file+hpackStdOut :: RunOptions -> IO ()+hpackStdOut options = do+  (warnings, _cabalFile, new) <- run options   Utf8.putStr new   printWarnings warnings
src/Hpack/CabalFile.hs view
@@ -34,9 +34,11 @@ extractHash = extract "-- hash: " Just  extractVersion :: [String] -> Maybe Version-extractVersion = extract prefix (parseVersion . safeInit)+extractVersion = extract prefix (stripFileName >=> parseVersion . safeInit)   where-    prefix = "-- This file has been generated from package.yaml by hpack version "+    prefix = "-- This file has been generated from "+    stripFileName :: String -> Maybe String+    stripFileName = listToMaybe . mapMaybe (stripPrefix " by hpack version ") . tails  extract :: String -> (String -> Maybe a) -> [String] -> Maybe a extract prefix parse = listToMaybe . mapMaybe (stripPrefix prefix >=> parse)
src/Hpack/Config.hs view
@@ -14,6 +14,7 @@ module Hpack.Config (   packageConfig , readPackageConfig+, readPackageConfigWith , renamePackage , packageDependencies , package@@ -37,7 +38,6 @@ , Empty(..) , getModules , pathsModuleFromPackageName-, determineModules , BuildType(..) , Cond(..) @@ -155,17 +155,21 @@ data LibrarySection = LibrarySection {   librarySectionExposed :: Maybe Bool , librarySectionExposedModules :: Maybe (List String)+, librarySectionGeneratedExposedModules :: Maybe (List String) , librarySectionOtherModules :: Maybe (List String)+, librarySectionGeneratedOtherModules :: Maybe (List String) , librarySectionReexportedModules :: Maybe (List String) , librarySectionSignatures :: Maybe (List String) } deriving (Eq, Show, Generic)  instance Monoid LibrarySection where-  mempty = LibrarySection Nothing Nothing Nothing Nothing Nothing+  mempty = LibrarySection Nothing Nothing Nothing Nothing Nothing Nothing Nothing   mappend a b = LibrarySection {       librarySectionExposed = librarySectionExposed b <|> librarySectionExposed a     , librarySectionExposedModules = librarySectionExposedModules a <> librarySectionExposedModules b+    , librarySectionGeneratedExposedModules = librarySectionGeneratedExposedModules a <> librarySectionGeneratedExposedModules b     , librarySectionOtherModules = librarySectionOtherModules a <> librarySectionOtherModules b+    , librarySectionGeneratedOtherModules = librarySectionGeneratedOtherModules a <> librarySectionGeneratedOtherModules b     , librarySectionReexportedModules = librarySectionReexportedModules a <> librarySectionReexportedModules b     , librarySectionSignatures = librarySectionSignatures a <> librarySectionSignatures b     }@@ -178,13 +182,15 @@ data ExecutableSection = ExecutableSection {   executableSectionMain :: Maybe FilePath , executableSectionOtherModules :: Maybe (List String)+, executableSectionGeneratedOtherModules :: Maybe (List String) } deriving (Eq, Show, Generic)  instance Monoid ExecutableSection where-  mempty = ExecutableSection Nothing Nothing+  mempty = ExecutableSection Nothing Nothing Nothing   mappend a b = ExecutableSection {       executableSectionMain = executableSectionMain b <|> executableSectionMain a     , executableSectionOtherModules = executableSectionOtherModules a <> executableSectionOtherModules b+    , executableSectionGeneratedOtherModules = executableSectionGeneratedOtherModules a <> executableSectionGeneratedOtherModules b     }  instance HasFieldNames ExecutableSection@@ -558,8 +564,12 @@ decodeYaml = lift . ExceptT . Yaml.decodeYaml  readPackageConfig :: FilePath -> FilePath -> IO (Either String (Package, [String]))-readPackageConfig userDataDir file = runExceptT $ runWriterT $ do-  config <- decodeYaml file+readPackageConfig = readPackageConfigWith Yaml.decodeYaml++readPackageConfigWith :: (FilePath -> IO (Either String Value)) -> FilePath -> FilePath -> IO (Either String (Package, [String]))+readPackageConfigWith readValue userDataDir file = runExceptT $ runWriterT $ do+  value <- lift . ExceptT $ readValue file+  config <- lift . ExceptT . return $ first ((file ++ ": ") ++) (parseEither parseJSON value)   dir <- liftIO $ takeDirectory <$> canonicalizePath file   toPackage userDataDir dir config @@ -600,6 +610,7 @@   libraryExposed :: Maybe Bool , libraryExposedModules :: [String] , libraryOtherModules :: [String]+, libraryGeneratedModules :: [String] , libraryReexportedModules :: [String] , librarySignatures :: [String] } deriving (Eq, Show)@@ -607,6 +618,7 @@ data Executable = Executable {   executableMain :: Maybe FilePath , executableOtherModules :: [String]+, executableGeneratedModules :: [String] } deriving (Eq, Show)  data Section a = Section {@@ -987,8 +999,8 @@     traverseConditionals = traverse . traverse . traverseSectionAndConditionals fConditionals fConditionals  getMentionedLibraryModules :: LibrarySection -> [String]-getMentionedLibraryModules LibrarySection{..} =-  fromMaybeList librarySectionExposedModules ++ fromMaybeList librarySectionOtherModules+getMentionedLibraryModules (LibrarySection _ exposedModules generatedExposedModules otherModules generatedOtherModules _ _)+  = fromMaybeList (exposedModules <> generatedExposedModules <> otherModules <> generatedOtherModules)  listModules :: FilePath -> Section a -> IO [String] listModules dir Section{..} = concat <$> mapM (getModules dir) sectionSourceDirs@@ -1025,32 +1037,35 @@     getLibraryModules Library{..} = libraryExposedModules ++ libraryOtherModules      fromLibrarySectionTopLevel pathsModule inferableModules LibrarySection{..} =-      Library librarySectionExposed exposedModules otherModules reexportedModules signatures+      Library librarySectionExposed exposedModules otherModules generatedModules reexportedModules signatures       where-        (exposedModules, otherModules) =-          determineModules pathsModule inferableModules librarySectionExposedModules librarySectionOtherModules+        (exposedModules, otherModules, generatedModules) =+          determineModules pathsModule inferableModules librarySectionExposedModules librarySectionGeneratedExposedModules librarySectionOtherModules librarySectionGeneratedOtherModules         reexportedModules = fromMaybeList librarySectionReexportedModules         signatures = fromMaybeList librarySectionSignatures -determineModules :: [String] -> [String] -> Maybe (List String) -> Maybe (List String) -> ([String], [String])-determineModules pathsModule inferableModules mExposedModules mOtherModules = case (mExposedModules, mOtherModules) of-  (Nothing, Nothing) -> (inferableModules, pathsModule)-  _ -> (exposedModules, otherModules)-    where-      exposedModules = maybe (inferableModules \\ otherModules) fromList mExposedModules-      otherModules   = maybe ((inferableModules ++ pathsModule) \\ exposedModules) fromList mOtherModules+determineModules :: [String] -> [String] -> Maybe (List String) -> Maybe (List String) -> Maybe (List String) -> Maybe (List String) -> ([String], [String], [String])+determineModules pathsModule inferable mExposed mGeneratedExposed mOther mGeneratedOther =+  (exposed, others, generated)+  where+    generated = fromMaybeList (mGeneratedExposed <> mGeneratedOther)+    exposed = maybe inferable fromList mExposed ++ fromMaybeList mGeneratedExposed+    others = maybe ((inferable \\ exposed) ++ pathsModule) fromList mOther ++ fromMaybeList mGeneratedOther  fromLibrarySectionInConditional :: [String] -> LibrarySection -> Library-fromLibrarySectionInConditional inferableModules lib@(LibrarySection _ exposedModules otherModules _ _) = do+fromLibrarySectionInConditional inferableModules lib@(LibrarySection _ exposedModules _ otherModules _ _ _) =   case (exposedModules, otherModules) of-    (Nothing, Nothing) -> (fromLibrarySectionPlain lib) {libraryOtherModules = inferableModules}+    (Nothing, Nothing) -> addToOtherModules inferableModules (fromLibrarySectionPlain lib)     _ -> fromLibrarySectionPlain lib+  where+    addToOtherModules xs r = r {libraryOtherModules = xs ++ libraryOtherModules r}  fromLibrarySectionPlain :: LibrarySection -> Library fromLibrarySectionPlain LibrarySection{..} = Library {     libraryExposed = librarySectionExposed-  , libraryExposedModules = fromMaybeList librarySectionExposedModules-  , libraryOtherModules = fromMaybeList librarySectionOtherModules+  , libraryExposedModules = fromMaybeList (librarySectionExposedModules <> librarySectionGeneratedExposedModules)+  , libraryOtherModules = fromMaybeList (librarySectionOtherModules <> librarySectionGeneratedOtherModules)+  , libraryGeneratedModules = fromMaybeList (librarySectionGeneratedOtherModules <> librarySectionGeneratedExposedModules)   , libraryReexportedModules = fromMaybeList librarySectionReexportedModules   , librarySignatures = fromMaybeList librarySectionSignatures   }@@ -1062,8 +1077,8 @@ toExecutables dir packageName_ globalOptions = traverse (toExecutable dir packageName_ globalOptions) . fromMaybe mempty  getMentionedExecutableModules :: ExecutableSection -> [String]-getMentionedExecutableModules ExecutableSection{..} =-  fromMaybeList executableSectionOtherModules ++ maybe [] return (executableSectionMain >>= toModule . splitDirectories)+getMentionedExecutableModules (ExecutableSection main otherModules generatedModules)=+  maybe id (:) (main >>= toModule . splitDirectories) $ fromMaybeList (otherModules <> generatedModules)  toExecutable :: FilePath -> String -> GlobalOptions -> SectionConfig Identity CSources JsSources ExecutableSection -> IO (Section Executable) toExecutable dir packageName_ globalOptions =@@ -1073,9 +1088,10 @@   where     fromExecutableSection :: [String] -> [String] -> ExecutableSection -> Executable     fromExecutableSection pathsModule inferableModules ExecutableSection{..} =-      (Executable executableSectionMain otherModules)+      (Executable executableSectionMain (otherModules ++ generatedModules) generatedModules)       where         otherModules = maybe (inferableModules ++ pathsModule) fromList executableSectionOtherModules+        generatedModules = maybe [] fromList executableSectionGeneratedOtherModules  expandMain :: Section ExecutableSection -> Section ExecutableSection expandMain = flatten . expand@@ -1163,6 +1179,3 @@     removeSetup src       | src == dir = filter (/= "Setup")       | otherwise = id--fromMaybeList :: Maybe (List a) -> [a]-fromMaybeList = maybe [] fromList
src/Hpack/Options.hs view
@@ -1,5 +1,10 @@+{-# LANGUAGE LambdaCase #-} module Hpack.Options where +import           Control.Monad+import           System.FilePath+import           System.Directory+ data ParseResult = Help | PrintVersion | PrintNumericVersion | Run Options | ParseError   deriving (Eq, Show) @@ -13,22 +18,26 @@   optionsVerbose :: Verbose , optionsForce :: Force , optionsToStdout :: Bool-, optionsTarget :: Maybe FilePath+, optionsConfigDir :: Maybe FilePath+, optionsConfigFile :: FilePath } deriving (Eq, Show) -parseOptions :: [String] -> ParseResult-parseOptions xs = case xs of-  ["--version"] -> PrintVersion-  ["--numeric-version"] -> PrintNumericVersion-  ["--help"] -> Help+parseOptions :: FilePath -> [String] -> IO ParseResult+parseOptions defaultConfigFile xs = case xs of+  ["--version"] -> return PrintVersion+  ["--numeric-version"] -> return PrintNumericVersion+  ["--help"] -> return Help   _ -> case targets of-    Just (target, toStdout) -> Run (Options verbose force toStdout target)-    Nothing -> ParseError+    Just (target, toStdout) -> do+      (dir, file) <- splitDirectory defaultConfigFile target+      return $ Run (Options verbose force toStdout dir file)+    Nothing -> return ParseError     where       silentFlag = "--silent"       forceFlags = ["--force", "-f"] -      flags = [silentFlag] ++ forceFlags+      flags = silentFlag : forceFlags+       verbose = if silentFlag `elem` xs then NoVerbose else Verbose       force = if any (`elem` xs) forceFlags then Force else NoForce       ys = filter (`notElem` flags) xs@@ -40,3 +49,15 @@         [dir, "-"] -> Just (Just dir, True)         [] -> Just (Nothing, False)         _ -> Nothing++splitDirectory :: FilePath -> Maybe FilePath -> IO (Maybe FilePath, FilePath)+splitDirectory defaultFileName = \ case+  Nothing -> return (Nothing, defaultFileName)+  (Just p) -> do+    isDirectory <- doesDirectoryExist p+    return $ if isDirectory+      then (Just p, defaultFileName)+      else let+        file = takeFileName p+        dir = takeDirectory p+        in (guard (p /= file) >> Just dir, if null file then defaultFileName else file)
src/Hpack/Run.hs view
@@ -4,7 +4,9 @@ {-# LANGUAGE ViewPatterns #-} {-# LANGUAGE CPP #-} module Hpack.Run (-  run+  RunOptions(..)+, defaultRunOptions+, run , renderPackage , RenderSettings(..) , Alignment(..)@@ -31,17 +33,28 @@ import           Data.Version import           Data.Map.Lazy (Map) import qualified Data.Map.Lazy as Map+import qualified Data.Aeson as Aeson  import           Hpack.Util import           Hpack.Config import           Hpack.Render import           Hpack.FormattingHints+import           Hpack.Yaml -run :: Maybe FilePath -> FilePath -> IO ([String], FilePath, String)-run mDir c = do+data RunOptions = RunOptions {+  runOptionsConfigDir :: Maybe FilePath+, runOptionsConfigFile :: FilePath+, runOptionsDecode :: FilePath -> IO (Either String Aeson.Value)+}++defaultRunOptions :: RunOptions+defaultRunOptions = RunOptions Nothing packageConfig decodeYaml++run :: RunOptions -> IO ([String], FilePath, String)+run (RunOptions mDir c decode) = do   let dir = fromMaybe "" mDir   userDataDir <- getAppUserDataDirectory "hpack"-  mPackage <- readPackageConfig userDataDir (dir </> c)+  mPackage <- readPackageConfigWith decode userDataDir (dir </> c)   case mPackage of     Right (pkg, warnings) -> do       let cabalFile = dir </> (packageName pkg ++ ".cabal")@@ -132,8 +145,11 @@     cabalVersion = (">= " ++) . showVersion <$> maximum [         Just (makeVersion [1,10])       , packageCabalVersion-      , packageLibrary >>= libraryCabalVersion . sectionData+      , packageLibrary >>= libraryCabalVersion       , internalLibsCabalVersion packageInternalLibraries+      , executablesCabalVersion packageExecutables+      , executablesCabalVersion packageTests+      , executablesCabalVersion packageBenchmarks       ]      where       packageCabalVersion :: Maybe Version@@ -143,18 +159,29 @@         , makeVersion [1,18] <$ guard (not (null packageExtraDocFiles))         ] -      libraryCabalVersion :: Library -> Maybe Version-      libraryCabalVersion Library{..} = maximum [+      libraryCabalVersion :: Section Library -> Maybe Version+      libraryCabalVersion sect = maximum [           makeVersion [1,22] <$ guard hasReexportedModules         , makeVersion [2,0]  <$ guard hasSignatures+        , makeVersion [2,0] <$ guard hasGeneratedModules         ]         where-          hasReexportedModules = (not . null) libraryReexportedModules-          hasSignatures = (not . null) librarySignatures+          hasReexportedModules = any (not . null . libraryReexportedModules) sect+          hasSignatures = any (not . null . librarySignatures) sect+          hasGeneratedModules = any (not . null . libraryGeneratedModules) sect        internalLibsCabalVersion :: Map String (Section Library) -> Maybe Version       internalLibsCabalVersion internalLibraries = makeVersion [2,0] <$ guard (not (Map.null internalLibraries)) +      executablesCabalVersion :: Map String (Section Executable) -> Maybe Version+      executablesCabalVersion = foldr max Nothing . map executableCabalVersion . Map.elems++      executableCabalVersion :: Section Executable -> Maybe Version+      executableCabalVersion sect = makeVersion [2,0] <$ guard (executableHasGeneratedModules sect)++      executableHasGeneratedModules :: Section Executable -> Bool+      executableHasGeneratedModules = any (not . null . executableGeneratedModules)+ sortSectionFields :: [(String, [String])] -> [Element] -> [Element] sortSectionFields sectionsFieldOrder = go   where@@ -226,10 +253,11 @@ renderExecutableSection sect = renderSection renderExecutableFields sect ++ [defaultLanguage]  renderExecutableFields :: Executable -> [Element]-renderExecutableFields Executable{..} = mainIs ++ [otherModules]+renderExecutableFields Executable{..} = mainIs ++ [otherModules, generatedModules]   where     mainIs = maybe [] (return . Field "main-is" . Literal) executableMain     otherModules = renderOtherModules executableOtherModules+    generatedModules = renderGeneratedModules executableGeneratedModules  renderCustomSetup :: CustomSetup -> Element renderCustomSetup CustomSetup{..} =@@ -246,6 +274,7 @@   maybe [] (return . renderExposed) libraryExposed ++ [     renderExposedModules libraryExposedModules   , renderOtherModules libraryOtherModules+  , renderGeneratedModules libraryGeneratedModules   , renderReexportedModules libraryReexportedModules   , renderSignatures librarySignatures   ]@@ -303,6 +332,9 @@  renderOtherModules :: [String] -> Element renderOtherModules = Field "other-modules" . LineSeparatedList++renderGeneratedModules :: [String] -> Element+renderGeneratedModules = Field "autogen-modules" . LineSeparatedList  renderReexportedModules :: [String] -> Element renderReexportedModules = Field "reexported-modules" . LineSeparatedList
src/Hpack/Util.hs view
@@ -5,6 +5,7 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} module Hpack.Util (   List(..)+, fromMaybeList , GhcOption , GhcProfOption , GhcjsOption@@ -51,6 +52,9 @@   parseJSON v = List <$> case v of     Array _ -> parseJSON v     _ -> return <$> parseJSON v++fromMaybeList :: Maybe (List a) -> [a]+fromMaybeList = maybe [] fromList  type GhcOption = String type GhcProfOption = String
test/EndToEndSpec.hs view
@@ -27,7 +27,7 @@ spec :: Spec spec = around_ (inTempDirectoryNamed "foo") $ do   describe "hpack" $ do-    context "with defaults" $ do+    describe "defaults" $ do       it "accepts global defaults" $ do         writeFile "defaults/sol/hpack-template/2017/defaults.yaml" [i|         default-extensions:@@ -41,9 +41,7 @@           path: defaults.yaml           ref: "2017"         library: {}-        |] `shouldRenderTo` library [i|-        other-modules:-            Paths_foo+        |] `shouldRenderTo` library_ [i|         default-extensions: RecordWildCards DeriveFunctor         |] @@ -73,9 +71,7 @@           - foo/bar@v1           - foo/bar@v2         library: {}-        |] `shouldRenderTo` library [i|-        other-modules:-            Paths_foo+        |] `shouldRenderTo` library_ [i|         default-extensions: RecordWildCards DeriveFunctor         |] @@ -85,9 +81,7 @@         [i|         defaults: foo/bar@v1         library: {}-        |] `shouldRenderTo` library [i|-        other-modules:-            Paths_foo+        |] `shouldRenderTo` library_ [i|         default-extensions: DeriveFunctor         |] @@ -345,24 +339,11 @@           |] `shouldWarn` pure "Specified pattern \"foo/*.c\" for c-sources does not match any files"        context "with library" $ do-        it "accepts signatures" $ do-          [i|-          library:-            signatures: Foo-          |] `shouldRenderTo` (library [i|-          other-modules:-              Paths_foo-          signatures:-              Foo-          |]) {packageCabalVersion = ">= 2.0"}-         it "accepts global c-sources" $ do           [i|           c-sources: cbits/*.c           library: {}-          |] `shouldRenderTo` library [i|-          other-modules:-              Paths_foo+          |] `shouldRenderTo` library_ [i|           c-sources:               cbits/bar.c               cbits/foo.c@@ -372,9 +353,7 @@           [i|           library:             c-sources: cbits/*.c-          |] `shouldRenderTo` library [i|-          other-modules:-              Paths_foo+          |] `shouldRenderTo` library_ [i|           c-sources:               cbits/bar.c               cbits/foo.c@@ -386,9 +365,7 @@             when:               condition: os(windows)               c-sources: cbits/*.c-          |] `shouldRenderTo` library [i|-          other-modules:-              Paths_foo+          |] `shouldRenderTo` library_ [i|           if os(windows)             c-sources:                 cbits/bar.c@@ -418,7 +395,7 @@               cbits/foo.c           |] -    context "with custom-setup" $ do+    describe "custom-setup" $ do       it "warns on unknown fields" $ do         [i|         name: foo@@ -451,18 +428,39 @@             base         |]) {packageBuildType = "Make"} -    context "with library" $ do+    describe "library" $ do       it "accepts reexported-modules" $ do         [i|         library:           reexported-modules: Baz-        |] `shouldRenderTo` (library [i|-        reexported-modules:-            Baz-        other-modules:-            Paths_foo+        |] `shouldRenderTo` (library_ [i|+          reexported-modules:+              Baz         |]) {packageCabalVersion = ">= 1.22"} +      it "accepts signatures" $ do+        [i|+        library:+          signatures: Foo+        |] `shouldRenderTo` (library_ [i|+          signatures:+              Foo+        |]) {packageCabalVersion = ">= 2.0"}++      context "when package.yaml contains duplicate modules" $ do+        it "generates a cabal file with duplicate modules" $ do+          -- garbage in, garbage out+          [i|+          library:+            exposed-modules: Foo+            other-modules: Foo+          |] `shouldRenderTo` library [i|+          exposed-modules:+              Foo+          other-modules:+              Foo+          |]+       context "when inferring modules" $ do         context "with exposed-modules" $ do           it "infers other-modules" $ do@@ -601,7 +599,70 @@                     unix/               |] -    context "with internal-libraries" $ do+        context "with generated modules" $ do+          it "includes generated modules in autogen-modules" $ do+            [i|+            library:+              generated-exposed-modules: Foo+              generated-other-modules: Bar+            |] `shouldRenderTo` (library [i|+            exposed-modules:+                Foo+            other-modules:+                Paths_foo+                Bar+            autogen-modules:+                Foo+                Bar+            |]) {packageCabalVersion = ">= 2.0"}++          it "does not infer any mentioned generated modules" $ do+            touch "src/Exposed.hs"+            touch "src/Other.hs"+            [i|+            library:+              source-dirs: src+              generated-exposed-modules: Exposed+              generated-other-modules: Other+            |] `shouldRenderTo` (library [i|+            hs-source-dirs:+                src+            exposed-modules:+                Exposed+            other-modules:+                Paths_foo+                Other+            autogen-modules:+                Exposed+                Other+            |]) {packageCabalVersion = ">= 2.0"}++          it "does not infer any generated modules mentioned inside conditionals" $ do+            touch "src/Exposed.hs"+            touch "src/Other.hs"+            [i|+            library:+              source-dirs: src+              when:+                condition: os(windows)+                generated-exposed-modules: Exposed+                generated-other-modules: Other+            |] `shouldRenderTo` (library [i|+            other-modules:+                Paths_foo+            hs-source-dirs:+                src+            if os(windows)+              exposed-modules:+                  Exposed+              other-modules:+                  Other+              autogen-modules:+                  Other+                  Exposed+            |]) {packageCabalVersion = ">= 2.0"}++    describe "internal-libraries" $ do       it "accepts internal-libraries" $ do         touch "src/Foo.hs"         [i|@@ -633,7 +694,7 @@             source-dirs: src         |] `shouldWarn` pure "Specified source-dir \"src\" does not exist" -    context "with executables" $ do+    describe "executables" $ do       it "accepts arbitrary entry points as main" $ do         touch "src/Foo.hs"         touch "src/Bar.hs"@@ -686,6 +747,26 @@             other-modules:                 Baz           |]++        it "does not infer any mentioned generated modules" $ do+          touch "src/Foo.hs"+          [i|+          executables:+            foo:+              main: Main.hs+              source-dirs: src+              generated-other-modules: Foo+          |] `shouldRenderTo` (executable "foo" [i|+            main-is: Main.hs+            hs-source-dirs:+                src+            other-modules:+                Paths_foo+                Foo+            autogen-modules:+                Foo+          |]) {packageCabalVersion = ">= 2.0"}+         context "with conditional" $ do           it "doesn't infer any modules mentioned in that conditional" $ do             touch "src/Foo.hs"@@ -888,6 +969,17 @@     content = [i| custom-setup #{indentBy 2 $ unindent a}+|]++library_ :: String -> Package+library_ l = package content+  where+    content = [i|+library+  other-modules:+      Paths_foo+#{indentBy 2 $ unindent l}+  default-language: Haskell2010 |]  library :: String -> Package
test/Hpack/CabalFileSpec.hs view
@@ -26,6 +26,10 @@       let cabalFile = ["-- This file has been generated from package.yaml by hpack version 0.10.0."]       extractVersion cabalFile `shouldBe` Just (makeVersion [0, 10, 0]) +    it "is agnostic to file name" $ do+      let cabalFile = ["-- This file has been generated from some random file by hpack version 0.10.0."]+      extractVersion cabalFile `shouldBe` Just (makeVersion [0, 10, 0])+     it "is total" $ do       let cabalFile = ["-- This file has been generated from package.yaml by hpack version "]       extractVersion cabalFile `shouldBe` Nothing
test/Hpack/ConfigSpec.hs view
@@ -3,6 +3,7 @@ {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE MultiParamTypeClasses #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Hpack.ConfigSpec (   spec@@ -12,11 +13,10 @@ ) where  import           Helper- import           Data.Aeson.Types import           Data.String.Interpolate.IsString import           Control.Arrow-import           GHC.Exts+import qualified GHC.Exts as Exts import           System.Directory (createDirectory) import           Data.Either import qualified Data.Map.Lazy as Map@@ -26,7 +26,7 @@ import           Hpack.Config hiding (package) import qualified Hpack.Config as Config -instance IsList (Maybe (List a)) where+instance Exts.IsList (Maybe (List a)) where   type Item (Maybe (List a)) = a   fromList = Just . List   toList = undefined@@ -38,10 +38,10 @@ package = Config.package "foo" "0.0.0"  executable :: String -> Executable-executable main_ = Executable (Just main_) ["Paths_foo"]+executable main_ = Executable (Just main_) ["Paths_foo"] []  library :: Library-library = Library Nothing [] ["Paths_foo"] [] []+library = Library Nothing [] ["Paths_foo"] [] [] []  withPackage :: String -> IO () -> ((Package, [String]) -> Expectation) -> Expectation withPackage content beforeAction expectation = withTempDirectory $ \dir_ -> do@@ -70,23 +70,14 @@     it "replaces dashes with underscores in package name" $ do       pathsModuleFromPackageName "foo-bar" `shouldBe` "Paths_foo_bar" -  describe "determineModules" $ do-    it "adds the Paths_* module to the other-modules" $ do-      determineModules ["Paths_foo"] [] ["Foo"] Nothing `shouldBe` (["Foo"], ["Paths_foo"])--    it "adds the Paths_* module to the other-modules when no modules are specified" $ do-      determineModules ["Paths_foo"] [] Nothing Nothing `shouldBe` ([], ["Paths_foo"])--    context "when the Paths_* module is part of the exposed-modules" $ do-      it "does not add the Paths_* module to the other-modules" $ do-        determineModules ["Paths_foo"] [] ["Foo", "Paths_foo"] Nothing `shouldBe` (["Foo", "Paths_foo"], [])-   describe "fromLibrarySectionInConditional" $ do     let       sect = LibrarySection {         librarySectionExposed = Nothing       , librarySectionExposedModules = Nothing+      , librarySectionGeneratedExposedModules = Nothing       , librarySectionOtherModules = Nothing+      , librarySectionGeneratedOtherModules = Nothing       , librarySectionReexportedModules = Nothing       , librarySectionSignatures = Nothing       }@@ -94,6 +85,7 @@         libraryExposed = Nothing       , libraryExposedModules = []       , libraryOtherModules = []+      , libraryGeneratedModules = []       , libraryReexportedModules = []       , librarySignatures = []       }
test/Hpack/OptionsSpec.hs view
@@ -7,40 +7,80 @@ spec :: Spec spec = do   describe "parseOptions" $ do+    let configFile = "package.yaml"     context "with --help" $ do       it "returns Help" $ do-        parseOptions ["--help"] `shouldBe` Help+        parseOptions configFile ["--help"] `shouldReturn` Help      context "with --version" $ do       it "returns PrintVersion" $ do-        parseOptions ["--version"] `shouldBe` PrintVersion+        parseOptions configFile ["--version"] `shouldReturn` PrintVersion      context "by default" $ do       it "returns Run" $ do-        parseOptions [] `shouldBe` Run (Options Verbose NoForce False Nothing)+        parseOptions configFile [] `shouldReturn` Run (Options Verbose NoForce False Nothing configFile)        it "includes target" $ do-        parseOptions ["foo"] `shouldBe` Run (Options Verbose NoForce False (Just "foo"))+        parseOptions configFile ["foo.yaml"] `shouldReturn` Run (Options Verbose NoForce False Nothing "foo.yaml")        context "with superfluous arguments" $ do         it "returns ParseError" $ do-          parseOptions ["foo", "bar"] `shouldBe` ParseError+          parseOptions configFile ["foo", "bar"] `shouldReturn` ParseError        context "with --silent" $ do         it "sets optionsVerbose to NoVerbose" $ do-          parseOptions ["--silent"] `shouldBe` Run (Options NoVerbose NoForce False Nothing)+          parseOptions configFile ["--silent"] `shouldReturn` Run (Options NoVerbose NoForce False Nothing configFile)        context "with --force" $ do         it "sets optionsForce to Force" $ do-          parseOptions ["--force"] `shouldBe` Run (Options Verbose Force False Nothing)+          parseOptions configFile ["--force"] `shouldReturn` Run (Options Verbose Force False Nothing configFile)        context "with -f" $ do         it "sets optionsForce to Force" $ do-          parseOptions ["-f"] `shouldBe` Run (Options Verbose Force False Nothing)+          parseOptions configFile ["-f"] `shouldReturn` Run (Options Verbose Force False Nothing configFile)        context "with -" $ do         it "sets optionsToStdout to True" $ do-          parseOptions ["-"] `shouldBe` Run (Options Verbose NoForce True Nothing)+          parseOptions configFile ["-"] `shouldReturn` Run (Options Verbose NoForce True Nothing configFile)          it "rejects - for target" $ do-          parseOptions ["-", "-"] `shouldBe` ParseError+          parseOptions configFile ["-", "-"] `shouldReturn` ParseError++  describe "splitDirectory" $ do+    let packageConfig = "package.yaml"+    context "when given Nothing" $ do+      it "defaults file name to package.yaml" $ do+        splitDirectory packageConfig Nothing `shouldReturn` (Nothing, "package.yaml")++    context "when given a directory" $ do+      it "defaults file name to package.yaml" $ do+        withTempDirectory $ \dir -> do+          splitDirectory packageConfig (Just dir) `shouldReturn` (Just dir, "package.yaml")++    context "when given a file name" $ do+      it "defaults directory to Nothing" $ do+        inTempDirectory $ do+          touch "foo.yaml"+          splitDirectory packageConfig (Just "foo.yaml") `shouldReturn` (Nothing, "foo.yaml")++    context "when given a path to a file" $ do+      it "splits directory from file name" $ do+        withTempDirectory $ \dir -> do+          let file = dir </> "foo.yaml"+          touch file+          splitDirectory packageConfig (Just file) `shouldReturn` (Just dir, "foo.yaml")++    context "when path does not exist" $ do+      it "splits path into directory and file name" $ do+        inTempDirectory $ do+          splitDirectory packageConfig (Just "test/foo.yaml") `shouldReturn` (Just "test", "foo.yaml")++    context "when file does not exist" $ do+      it "defaults directory to Nothing" $ do+        inTempDirectory $ do+          splitDirectory packageConfig (Just "test") `shouldReturn` (Nothing, "test")++    context "when directory does not exist" $ do+      it "defaults file name to package.yaml" $ do+        inTempDirectory $ do+          splitDirectory packageConfig (Just "test/") `shouldReturn` (Just "test", "package.yaml")
test/Hpack/RunSpec.hs view
@@ -1,9 +1,9 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE OverloadedLists #-} module Hpack.RunSpec (spec) where  import           Helper import           Data.List-import qualified Data.Map.Lazy as Map  import           Hpack.ConfigSpec hiding (spec) import           Hpack.Config hiding (package)@@ -11,8 +11,11 @@ import           Hpack.Run  library :: Library-library = Library Nothing [] [] [] []+library = Library Nothing [] [] [] [] [] +executable :: Section Executable+executable = section (Executable (Just "Main.hs") [] [])+ renderEmptySection :: Empty -> [Element] renderEmptySection Empty = [] @@ -159,7 +162,7 @@           ]        it "retains section field order" $ do-        renderPackage defaultRenderSettings 0 [] [("executable foo", ["default-language", "main-is", "ghc-options"])] package {packageExecutables = Map.fromList [("foo", (section $ Executable (Just "Main.hs") []) {sectionGhcOptions = ["-Wall", "-Werror"]})]} `shouldBe` unlines [+        renderPackage defaultRenderSettings 0 [] [("executable foo", ["default-language", "main-is", "ghc-options"])] package {packageExecutables = [("foo", executable {sectionGhcOptions = ["-Wall", "-Werror"]})]} `shouldBe` unlines [             "name: foo"           , "version: 0.0.0"           , "build-type: Simple"@@ -171,10 +174,9 @@           , "  ghc-options: -Wall -Werror"           ] -     context "when rendering executable section" $ do       it "includes dependencies" $ do-        renderPackage_ package {packageExecutables = Map.fromList [("foo", (section $ Executable (Just "Main.hs") []) {sectionDependencies = Dependencies $ Map.fromList+        renderPackage_ package {packageExecutables = [("foo", executable {sectionDependencies = Dependencies         [("foo", VersionRange "== 0.1.0"), ("bar", AnyVersion)]})]} `shouldBe` unlines [             "name: foo"           , "version: 0.0.0"@@ -190,7 +192,7 @@           ]        it "includes GHC options" $ do-        renderPackage_ package {packageExecutables = Map.fromList [("foo", (section $ Executable (Just "Main.hs") []) {sectionGhcOptions = ["-Wall", "-Werror"]})]} `shouldBe` unlines [+        renderPackage_ package {packageExecutables = [("foo", executable {sectionGhcOptions = ["-Wall", "-Werror"]})]} `shouldBe` unlines [             "name: foo"           , "version: 0.0.0"           , "build-type: Simple"@@ -203,7 +205,7 @@           ]        it "includes frameworks" $ do-        renderPackage_ package {packageExecutables = Map.fromList [("foo", (section $ Executable (Just "Main.hs") []) {sectionFrameworks = ["foo", "bar"]})]} `shouldBe` unlines [+        renderPackage_ package {packageExecutables = [("foo", executable {sectionFrameworks = ["foo", "bar"]})]} `shouldBe` unlines [             "name: foo"           , "version: 0.0.0"           , "build-type: Simple"@@ -218,7 +220,7 @@           ]        it "includes extra-framework-dirs" $ do-        renderPackage_ package {packageExecutables = Map.fromList [("foo", (section $ Executable (Just "Main.hs") []) {sectionExtraFrameworksDirs = ["foo", "bar"]})]} `shouldBe` unlines [+        renderPackage_ package {packageExecutables = [("foo", executable {sectionExtraFrameworksDirs = ["foo", "bar"]})]} `shouldBe` unlines [             "name: foo"           , "version: 0.0.0"           , "build-type: Simple"@@ -233,7 +235,7 @@           ]        it "includes GHC profiling options" $ do-        renderPackage_ package {packageExecutables = Map.fromList [("foo", (section $ Executable (Just "Main.hs") []) {sectionGhcProfOptions = ["-fprof-auto", "-rtsopts"]})]} `shouldBe` unlines [+        renderPackage_ package {packageExecutables = [("foo", executable {sectionGhcProfOptions = ["-fprof-auto", "-rtsopts"]})]} `shouldBe` unlines [             "name: foo"           , "version: 0.0.0"           , "build-type: Simple"
test/HpackSpec.hs view
@@ -21,9 +21,9 @@       let         file = "foo.cabal" -        hpackWithVersion v = hpackWithVersionResult v Nothing NoForce-        hpack = hpackWithVersionResult version Nothing NoForce-        hpackForce = hpackWithVersionResult version Nothing Force+        hpackWithVersion v = hpackWithVersionResult v defaultRunOptions NoForce+        hpack = hpackWithVersionResult version defaultRunOptions NoForce+        hpackForce = hpackWithVersionResult version defaultRunOptions Force          generated = Result [] file Generated         modifiedManually = Result [] file ExistingCabalFileWasModifiedManually@@ -94,41 +94,3 @@               old <- readFile file               hpack `shouldReturn` outputUnchanged               readFile file `shouldReturn` old--  describe "splitDirectory" $ do-    context "when given Nothing" $ do-      it "defaults file name to package.yaml" $ do-        splitDirectory Nothing `shouldReturn` (Nothing, "package.yaml")--    context "when given a directory" $ do-      it "defaults file name to package.yaml" $ do-        withTempDirectory $ \dir -> do-          splitDirectory (Just dir) `shouldReturn` (Just dir, "package.yaml")--    context "when given a file name" $ do-      it "defaults directory to Nothing" $ do-        inTempDirectory $ do-          touch "foo.yaml"-          splitDirectory (Just "foo.yaml") `shouldReturn` (Nothing, "foo.yaml")--    context "when given a path to a file" $ do-      it "splits directory from file name" $ do-        withTempDirectory $ \dir -> do-          let file = dir </> "foo.yaml"-          touch file-          splitDirectory (Just file) `shouldReturn` (Just dir, "foo.yaml")--    context "when path does not exist" $ do-      it "defaults directory to Nothing" $ do-        inTempDirectory $ do-          splitDirectory (Just "test/foo.yaml") `shouldReturn` (Just "test", "foo.yaml")--    context "when file does not exist" $ do-      it "defaults directory to Nothing" $ do-        inTempDirectory $ do-          splitDirectory (Just "test") `shouldReturn` (Nothing, "test")--    context "when directory does not exist" $ do-      it "defaults directory to Nothing" $ do-        inTempDirectory $ do-          splitDirectory (Just "test/") `shouldReturn` (Just "test", "package.yaml")