hpack 0.5.1 → 0.5.2
raw patch · 7 files changed
+407/−112 lines, 7 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Hpack.Run: renderPackage :: Int -> [String] -> Package -> String
+ Hpack.Run: renderPackage :: RenderSettings -> Int -> [String] -> Package -> String
- Hpack.Run: renderSourceRepository :: SourceRepository -> String
+ Hpack.Run: renderSourceRepository :: SourceRepository -> Stanza
Files
- driver/Main.hs +5/−1
- hpack.cabal +14/−7
- src/Hpack/Config.hs +2/−3
- src/Hpack/Render.hs +118/−0
- src/Hpack/Run.hs +68/−83
- test/Hpack/RenderSpec.hs +167/−0
- test/Hpack/RunSpec.hs +33/−18
driver/Main.hs view
@@ -35,7 +35,11 @@ (warnings, name, new) <- run forM_ warnings $ \warning -> hPutStrLn stderr ("WARNING: " ++ warning) old <- force . either (const Nothing) (Just . stripHeader) <$> tryJust (guard . isDoesNotExistError) (readFile name)- unless (old == Just (lines new)) (writeFile name $ header ++ new)+ if (old == Just (lines new)) then do+ putStrLn (name ++ " is up-to-date")+ else do+ (writeFile name $ header ++ new)+ putStrLn ("generated " ++ name) where stripHeader :: String -> [String] stripHeader = dropWhile null . dropWhile ("--" `isPrefixOf`) . lines
hpack.cabal view
@@ -3,7 +3,7 @@ -- see: https://github.com/sol/hpack name: hpack-version: 0.5.1+version: 0.5.2 synopsis: An alternative format for Haskell packages homepage: https://github.com/sol/hpack#readme bug-reports: https://github.com/sol/hpack/issues@@ -18,7 +18,9 @@ location: https://github.com/sol/hpack library- hs-source-dirs: src+ hs-source-dirs:+ src+ ghc-options: -Wall build-depends: aeson >= 0.8 , base >= 4.7 && < 5@@ -30,17 +32,19 @@ , text , unordered-containers , yaml- ghc-options: -Wall exposed-modules: Hpack.Config Hpack.Run other-modules:+ Hpack.Render Hpack.Util default-language: Haskell2010 executable hpack main-is: Main.hs- hs-source-dirs: driver+ hs-source-dirs:+ driver+ ghc-options: -Wall build-depends: aeson >= 0.8 , base >= 4.7 && < 5@@ -53,13 +57,15 @@ , unordered-containers , yaml , hpack- ghc-options: -Wall default-language: Haskell2010 test-suite spec type: exitcode-stdio-1.0 main-is: Spec.hs- hs-source-dirs: test, src+ hs-source-dirs:+ test+ , src+ ghc-options: -Wall build-depends: aeson >= 0.8 , base >= 4.7 && < 5@@ -75,13 +81,14 @@ , mockery >= 0.3 , interpolate , aeson-qq- ghc-options: -Wall other-modules: Helper Hpack.ConfigSpec+ Hpack.RenderSpec Hpack.RunSpec Hpack.UtilSpec Hpack.Config+ Hpack.Render Hpack.Run Hpack.Util default-language: Haskell2010
src/Hpack/Config.hs view
@@ -258,7 +258,7 @@ } deriving (Eq, Show, Functor, Foldable, Traversable, Data, Typeable) instance HasFieldNames a => HasFieldNames (Section a) where- fieldNames section = (fieldNames (sectionData section) ++ fieldNames proxy) \\ ["config"] -- FIXME : test for removing "config"+ fieldNames section = (fieldNames (sectionData section) ++ fieldNames proxy) where proxy :: CommonOptions proxy = CommonOptions Nothing Nothing Nothing Nothing Nothing@@ -420,8 +420,7 @@ defaultExtensions = sectionDefaultExtensions globalOptions ++ sectionDefaultExtensions options ghcOptions = sectionGhcOptions globalOptions ++ sectionGhcOptions options cppOptions = sectionCppOptions globalOptions ++ sectionCppOptions options- getDependencies = sectionDependencies- dependencies = getDependencies globalOptions ++ getDependencies options+ dependencies = sectionDependencies globalOptions ++ sectionDependencies options toSection :: a -> CommonOptions -> Section a toSection a CommonOptions{..}
+ src/Hpack/Render.hs view
@@ -0,0 +1,118 @@+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ViewPatterns #-}+module Hpack.Render where++import Prelude ()+import Prelude.Compat++import Control.Applicative+import Data.Char+import Data.List.Compat+import Data.Maybe+import Data.String++data Value =+ Literal String+ | CommaSeparatedList [String]+ | LineSeparatedList [String]+ | WordList [String]+ deriving (Eq, Show)++data Field = Field String Value+ deriving (Eq, Show)++data Stanza = Stanza String [Field] | Fields [Field]+ deriving (Eq, Show)++data Lines = SingleLine String | MultipleLines [String]+ deriving (Eq, Show)++data CommaStyle = LeadingCommas | TrailingCommas+ deriving (Eq, Show)++data RenderSettings = RenderSettings {+ renderSettingsIndentation :: Int+, renderSettingsCommaStyle :: CommaStyle+} deriving (Eq, Show)++defaultRenderSettings :: RenderSettings+defaultRenderSettings = RenderSettings 2 LeadingCommas++class Render a where+ render :: RenderSettings -> Int -> a -> [String]++instance Render Stanza where+ render settings nesting (Fields fields) = concatMap (render settings nesting) fields+ render settings nesting (Stanza name fields) = name : renderFields fields+ where+ renderFields :: [Field] -> [String]+ renderFields = concatMap (render settings $ succ nesting)++instance Render Field where+ render settings nesting (Field name v) = case renderValue settings v of+ SingleLine "" -> []+ SingleLine x -> [indent settings nesting (name ++ ": " ++ x)]+ MultipleLines [] -> []+ MultipleLines xs -> (indent settings nesting name ++ ":") : map (indent settings $ succ nesting) xs++renderValue :: RenderSettings -> Value -> Lines+renderValue RenderSettings{..} v = case v of+ Literal s -> SingleLine s+ WordList ws -> SingleLine $ unwords ws+ LineSeparatedList xs -> renderLineSeparatedList renderSettingsCommaStyle xs+ CommaSeparatedList xs -> renderCommaSeparatedList renderSettingsCommaStyle xs++renderLineSeparatedList :: CommaStyle -> [String] -> Lines+renderLineSeparatedList style = MultipleLines . map (padding ++)+ where+ padding = case style of+ LeadingCommas -> " "+ TrailingCommas -> ""++renderCommaSeparatedList :: CommaStyle -> [String] -> Lines+renderCommaSeparatedList style = MultipleLines . case style of+ LeadingCommas -> map renderLeadingComma . zip (True : repeat False)+ TrailingCommas -> map renderTrailingComma . reverse . zip (True : repeat False) . reverse+ where+ renderLeadingComma :: (Bool, String) -> String+ renderLeadingComma (isFirst, x)+ | isFirst = " " ++ x+ | otherwise = ", " ++ x++ renderTrailingComma :: (Bool, String) -> String+ renderTrailingComma (isLast, x)+ | isLast = x+ | otherwise = x ++ ","++instance IsString Value where+ fromString = Literal++indent :: RenderSettings -> Int -> String -> String+indent RenderSettings{..} nesting s = replicate (nesting * renderSettingsIndentation) ' ' ++ s++sniffIndentation :: String -> Maybe Int+sniffIndentation input = sniffFrom "library" <|> sniffFrom "executable"+ where+ sniffFrom :: String -> Maybe Int+ sniffFrom section = case findSection . removeEmptyLines $ lines input of+ _ : x : _ -> Just . length $ takeWhile isSpace x+ _ -> Nothing+ where+ findSection = dropWhile (not . isPrefixOf section)++ removeEmptyLines :: [String] -> [String]+ removeEmptyLines = filter $ any (not . isSpace)++sniffCommaStyle :: String -> Maybe CommaStyle+sniffCommaStyle (lines -> input)+ | any startsWithComma input = Just LeadingCommas+ | any (startsWithComma . reverse) input = Just TrailingCommas+ | otherwise = Nothing+ where+ startsWithComma = isPrefixOf "," . dropWhile isSpace++sniffRenderSettings :: String -> RenderSettings+sniffRenderSettings input = RenderSettings indentation trailingCommas+ where+ indentation = fromMaybe (renderSettingsIndentation defaultRenderSettings) (sniffIndentation input)+ trailingCommas = fromMaybe (renderSettingsCommaStyle defaultRenderSettings) (sniffCommaStyle input)
src/Hpack/Run.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ViewPatterns #-}@@ -20,6 +21,7 @@ import Hpack.Util import Hpack.Config+import Hpack.Render run :: IO ([String], FilePath, String) run = do@@ -31,31 +33,32 @@ old <- tryReadFile cabalFile let alignment = fromMaybe 16 (old >>= sniffAlignment)- output = renderPackage alignment (maybe [] extractFieldOrderHint old) package+ settings = maybe defaultRenderSettings sniffRenderSettings old+ output = renderPackage settings alignment (maybe [] extractFieldOrderHint old) package return (warnings, cabalFile, output) Left err -> die err -renderPackage :: Int -> [String] -> Package -> String-renderPackage alignment existingFieldOrder Package{..} = intercalate "\n" sections+renderPackage :: RenderSettings -> Int -> [String] -> Package -> String+renderPackage settings alignment existingFieldOrder Package{..} = intercalate "\n" (header : chunks) where- sections :: [String]- sections = catMaybes [- header- , extraSourceFiles- , dataFiles- , sourceRepository- , library- ] ++ renderExecutables packageExecutables ++ renderTests packageTests+ chunks :: [String]+ chunks = map unlines . filter (not . null) . map (render settings 0) $ stanzas - header = Just (unlines $ map formatField sortedFields)+ header = unlines $ map formatField sortedFields - extraSourceFiles = guard (not . null $ packageExtraSourceFiles) >> Just (unlines $ "extra-source-files:" : map (" " ++) packageExtraSourceFiles)- dataFiles = guard (not . null $ packageDataFiles) >> Just (unlines $ "data-files:" : map (" " ++) packageDataFiles)+ extraSourceFiles :: Field+ extraSourceFiles = Field "extra-source-files" (LineSeparatedList packageExtraSourceFiles) - sourceRepository = renderSourceRepository <$> packageSourceRepository+ dataFiles :: Field+ dataFiles = Field "data-files" (LineSeparatedList packageDataFiles) - library = renderLibrary <$> packageLibrary+ sourceRepository = maybe [] (return . renderSourceRepository) packageSourceRepository + library = maybe [] (return . renderLibrary) packageLibrary++ stanzas :: [Stanza]+ stanzas = Fields [extraSourceFiles] : Fields [dataFiles] : sourceRepository ++ library ++ renderExecutables packageExecutables ++ renderTests packageTests+ padding name = replicate (alignment - length name - 2) ' ' formatField :: (String, String) -> String@@ -112,7 +115,7 @@ x : xs -> intercalate "\n" (x : map (indentation ++) xs) [] -> "" where- n = max alignment (length "description: ")+ n = max alignment (length ("description: " :: String)) indentation = replicate n ' ' emptyLineToDot xs@@ -121,90 +124,72 @@ isEmptyLine = all isSpace -renderSourceRepository :: SourceRepository -> String-renderSourceRepository SourceRepository{..} = concat [- "source-repository head\n"- , " type: git\n"- , " location: " ++ sourceRepositoryUrl ++ "\n"- , maybe "" ((" subdir: " ++) . (++ "\n")) sourceRepositorySubdir+renderSourceRepository :: SourceRepository -> Stanza+renderSourceRepository SourceRepository{..} = Stanza "source-repository head" [+ Field "type" "git"+ , Field "location" (Literal sourceRepositoryUrl)+ , Field "subdir" (maybe "" Literal sourceRepositorySubdir) ] -renderExecutables :: [Section Executable] -> [String]+renderExecutables :: [Section Executable] -> [Stanza] renderExecutables = map renderExecutable -renderExecutable :: Section Executable -> String+renderExecutable :: Section Executable -> Stanza renderExecutable section@(sectionData -> Executable{..}) =- "executable "- ++ executableName ++ "\n"- ++ renderExecutableSection section+ Stanza ("executable " ++ executableName) (renderExecutableSection section) -renderTests :: [Section Executable] -> [String]+renderTests :: [Section Executable] -> [Stanza] renderTests = map renderTest -renderTest :: Section Executable -> String+renderTest :: Section Executable -> Stanza renderTest section@(sectionData -> Executable{..}) =- "test-suite " ++ executableName ++ "\n"- ++ " type: exitcode-stdio-1.0\n"- ++ renderExecutableSection section+ Stanza ("test-suite " ++ executableName)+ (Field "type" "exitcode-stdio-1.0" : renderExecutableSection section) -renderExecutableSection :: Section Executable -> String+renderExecutableSection :: Section Executable -> [Field] renderExecutableSection section@(sectionData -> Executable{..}) =- " main-is: " ++ executableMain ++ "\n"- ++ renderSection section- ++ renderOtherModules executableOtherModules- ++ " default-language: Haskell2010\n"+ mainIs : renderSection section ++ [otherModules, defaultLanguage]+ where+ mainIs = Field "main-is" (Literal executableMain)+ otherModules = renderOtherModules executableOtherModules -renderLibrary :: Section Library -> String-renderLibrary section@(sectionData -> Library{..}) =- "library\n"- ++ renderSection section- ++ renderExposedModules libraryExposedModules- ++ renderOtherModules libraryOtherModules- ++ " default-language: Haskell2010\n"+renderLibrary :: Section Library -> Stanza+renderLibrary section@(sectionData -> Library{..}) = Stanza "library" $+ renderSection section ++ [+ renderExposedModules libraryExposedModules+ , renderOtherModules libraryOtherModules+ , defaultLanguage+ ] -renderSection :: Section a -> String-renderSection Section{..} =- renderSourceDirs sectionSourceDirs- ++ unlines (renderDependencies sectionDependencies)- ++ renderDefaultExtensions sectionDefaultExtensions- ++ renderGhcOptions sectionGhcOptions- ++ renderCppOptions sectionCppOptions+renderSection :: Section a -> [Field]+renderSection Section{..} = [+ renderSourceDirs sectionSourceDirs+ , renderDefaultExtensions sectionDefaultExtensions+ , renderGhcOptions sectionGhcOptions+ , renderCppOptions sectionCppOptions+ , renderDependencies sectionDependencies+ ] -renderSourceDirs :: [String] -> String-renderSourceDirs dirs- | null dirs = ""- | otherwise = " hs-source-dirs: " ++ intercalate ", " dirs ++ "\n"+defaultLanguage :: Field+defaultLanguage = Field "default-language" "Haskell2010" -renderExposedModules :: [String] -> String-renderExposedModules modules- | null modules = ""- | otherwise = " exposed-modules:\n" ++ (unlines $ map (" " ++) modules)+renderSourceDirs :: [String] -> Field+renderSourceDirs dirs = Field "hs-source-dirs" (CommaSeparatedList dirs) -renderOtherModules :: [String] -> String-renderOtherModules modules- | null modules = ""- | otherwise = " other-modules:\n" ++ (unlines $ map (" " ++) modules)+renderExposedModules :: [String] -> Field+renderExposedModules modules = Field "exposed-modules" (LineSeparatedList modules) -renderDependencies :: [Dependency] -> [String]-renderDependencies dependencies- | null dependencies = []- | otherwise = " build-depends:" : map render (zip (True : repeat False) dependencies)- where- render :: (Bool, Dependency) -> String- render (isFirst, dependency)- | isFirst = " " ++ dependencyName dependency- | otherwise = " , " ++ dependencyName dependency+renderOtherModules :: [String] -> Field+renderOtherModules modules = Field "other-modules" (LineSeparatedList modules) -renderGhcOptions :: [GhcOption] -> String-renderGhcOptions = renderOptions "ghc-options"+renderDependencies :: [Dependency] -> Field+renderDependencies dependencies = Field "build-depends" (CommaSeparatedList $ map dependencyName dependencies) -renderCppOptions :: [GhcOption] -> String-renderCppOptions = renderOptions "cpp-options"+renderGhcOptions :: [GhcOption] -> Field+renderGhcOptions = Field "ghc-options" . WordList -renderDefaultExtensions :: [String] -> String-renderDefaultExtensions = renderOptions "default-extensions"+renderCppOptions :: [GhcOption] -> Field+renderCppOptions = Field "cpp-options" . WordList -renderOptions :: String -> [String] -> String-renderOptions field options- | null options = ""- | otherwise = " " ++ field ++ ": " ++ unwords options ++ "\n"+renderDefaultExtensions :: [String] -> Field+renderDefaultExtensions = Field "default-extensions" . WordList
+ test/Hpack/RenderSpec.hs view
@@ -0,0 +1,167 @@+{-# LANGUAGE OverloadedStrings #-}++module Hpack.RenderSpec where++import Test.Hspec++import Hpack.Render++spec :: Spec+spec = do+ describe "render" $ do+ context "when rendering a Stanza" $ do+ it "renders stanza" $ do+ let stanza = Stanza "foo" [+ Field "bar" "23"+ , Field "baz" "42"+ ]+ render defaultRenderSettings 0 stanza `shouldBe` [+ "foo"+ , " bar: 23"+ , " baz: 42"+ ]++ it "omits empty fields" $ do+ let stanza = Stanza "foo" [+ Field "bar" "23"+ , Field "baz" (WordList [])+ ]+ render defaultRenderSettings 0 stanza `shouldBe` [+ "foo"+ , " bar: 23"+ ]++ it "allows to customize indentation" $ do+ let stanza = Stanza "foo" [+ Field "bar" "23"+ , Field "baz" "42"+ ]+ render defaultRenderSettings{renderSettingsIndentation = 4} 0 stanza `shouldBe` [+ "foo"+ , " bar: 23"+ , " baz: 42"+ ]++ context "when rendering a Field" $ do+ context "when rendering a MultipleLines value" $ do+ it "takes nesting into account" $ do+ let field = Field "foo" (CommaSeparatedList ["bar", "baz"])+ render defaultRenderSettings 1 field `shouldBe` [+ " foo:"+ , " bar"+ , " , baz"+ ]++ context "when value is empty" $ do+ it "returns an empty list" $ do+ let field = Field "foo" (CommaSeparatedList [])+ render defaultRenderSettings 0 field `shouldBe` []++ context "when rendering a SingleLine value" $ do+ it "returns a single line" $ do+ let field = Field "foo" (Literal "bar")+ render defaultRenderSettings 0 field `shouldBe` ["foo: bar"]++ it "takes nesting into account" $ do+ let field = Field "foo" (Literal "bar")+ render defaultRenderSettings 2 field `shouldBe` [" foo: bar"]++ context "when value is empty" $ do+ it "returns an empty list" $ do+ let field = Field "foo" (Literal "")+ render defaultRenderSettings 0 field `shouldBe` []++ describe "renderValue" $ do+ it "renders WordList" $ do+ renderValue defaultRenderSettings (WordList ["foo", "bar", "baz"]) `shouldBe` SingleLine "foo bar baz"++ it "renders CommaSeparatedList" $ do+ renderValue defaultRenderSettings (CommaSeparatedList ["foo", "bar", "baz"]) `shouldBe` MultipleLines [+ " foo"+ , ", bar"+ , ", baz"+ ]++ it "renders LineSeparatedList" $ do+ renderValue defaultRenderSettings (LineSeparatedList ["foo", "bar", "baz"]) `shouldBe` MultipleLines [+ " foo"+ , " bar"+ , " baz"+ ]++ context "when renderSettingsCommaStyle is TrailingCommas" $ do+ let settings = defaultRenderSettings{renderSettingsCommaStyle = TrailingCommas}++ it "renders CommaSeparatedList with trailing commas" $ do+ renderValue settings (CommaSeparatedList ["foo", "bar", "baz"]) `shouldBe` MultipleLines [+ "foo,"+ , "bar,"+ , "baz"+ ]++ it "renders LineSeparatedList without padding" $ do+ renderValue settings (LineSeparatedList ["foo", "bar", "baz"]) `shouldBe` MultipleLines [+ "foo"+ , "bar"+ , "baz"+ ]++ describe "sniffIndentation" $ do+ it "sniff alignment from executable section" $ do+ let input = unlines [+ "name: foo"+ , "version: 0.0.0"+ , ""+ , "executable foo"+ , " build-depends: bar"+ ]+ sniffIndentation input `shouldBe` Just 4++ it "sniff alignment from library section" $ do+ let input = unlines [+ "name: foo"+ , "version: 0.0.0"+ , ""+ , "library"+ , " build-depends: bar"+ ]+ sniffIndentation input `shouldBe` Just 4++ it "ignores empty lines" $ do+ let input = unlines [+ "executable foo"+ , ""+ , " build-depends: bar"+ ]+ sniffIndentation input `shouldBe` Just 4++ it "ignores whitespace lines" $ do+ let input = unlines [+ "executable foo"+ , " "+ , " build-depends: bar"+ ]+ sniffIndentation input `shouldBe` Just 4++ describe "sniffCommaStyle" $ do+ it "detects leading commas" $ do+ let input = unlines [+ "executable foo"+ , " build-depends:"+ , " bar"+ , " , baz"+ ]+ sniffCommaStyle input `shouldBe` Just LeadingCommas++ it "detects trailing commas" $ do+ let input = unlines [+ "executable foo"+ , " build-depends:"+ , " bar, "+ , " baz"+ ]+ sniffCommaStyle input `shouldBe` Just TrailingCommas++ context "when detection fails" $ do+ it "returns Nothing" $ do+ sniffCommaStyle "" `shouldBe` Nothing
test/Hpack/RunSpec.hs view
@@ -6,13 +6,15 @@ import Hpack.ConfigSpec hiding (spec) import Hpack.Config+import Hpack.Render import Hpack.Run spec :: Spec spec = do describe "renderPackage" $ do+ let renderPackage_ = renderPackage defaultRenderSettings it "renders a package" $ do- renderPackage 0 [] package `shouldBe` unlines [+ renderPackage_ 0 [] package `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "build-type: Simple"@@ -20,7 +22,7 @@ ] it "aligns fields" $ do- renderPackage 16 [] package `shouldBe` unlines [+ renderPackage_ 16 [] package `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "build-type: Simple"@@ -28,7 +30,7 @@ ] it "includes description" $ do- renderPackage 0 [] package {packageDescription = Just "foo\n\nbar\n"} `shouldBe` unlines [+ renderPackage_ 0 [] package {packageDescription = Just "foo\n\nbar\n"} `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "description: foo"@@ -39,7 +41,7 @@ ] it "aligns description" $ do- renderPackage 16 [] package {packageDescription = Just "foo\n\nbar\n"} `shouldBe` unlines [+ renderPackage_ 16 [] package {packageDescription = Just "foo\n\nbar\n"} `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "description: foo"@@ -50,7 +52,7 @@ ] it "includes stability" $ do- renderPackage 0 [] package {packageStability = Just "experimental"} `shouldBe` unlines [+ renderPackage_ 0 [] package {packageStability = Just "experimental"} `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "stability: experimental"@@ -59,7 +61,7 @@ ] it "includes copyright holder" $ do- renderPackage 0 [] package {packageCopyright = ["(c) 2015 Simon Hengel"]} `shouldBe` unlines [+ renderPackage_ 0 [] package {packageCopyright = ["(c) 2015 Simon Hengel"]} `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "copyright: (c) 2015 Simon Hengel"@@ -68,7 +70,7 @@ ] it "aligns copyright holders" $ do- renderPackage 16 [] package {packageCopyright = ["(c) 2015 Foo", "(c) 2015 Bar"]} `shouldBe` unlines [+ renderPackage_ 16 [] package {packageCopyright = ["(c) 2015 Foo", "(c) 2015 Bar"]} `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "copyright: (c) 2015 Foo,"@@ -78,20 +80,31 @@ ] it "includes extra-source-files" $ do- renderPackage 0 [] package {packageExtraSourceFiles = ["foo", "bar"]} `shouldBe` unlines [+ renderPackage_ 0 [] package {packageExtraSourceFiles = ["foo", "bar"]} `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "build-type: Simple" , "cabal-version: >= 1.10" , "" , "extra-source-files:"- , " foo"- , " bar"+ , " foo"+ , " bar" ] + it "renders libray section" $ do+ renderPackage_ 0 [] package {packageLibrary = Just $ section library} `shouldBe` unlines [+ "name: foo"+ , "version: 0.0.0"+ , "build-type: Simple"+ , "cabal-version: >= 1.10"+ , ""+ , "library"+ , " default-language: Haskell2010"+ ]+ context "when given list of existing fields" $ do it "retains field order" $ do- renderPackage 16 ["cabal-version", "version", "name", "build-type"] package `shouldBe` unlines [+ renderPackage_ 16 ["cabal-version", "version", "name", "build-type"] package `shouldBe` unlines [ "cabal-version: >= 1.10" , "version: 0.0.0" , "name: foo"@@ -99,7 +112,7 @@ ] it "uses default field order for new fields" $ do- renderPackage 16 ["name", "version", "cabal-version"] package `shouldBe` unlines [+ renderPackage_ 16 ["name", "version", "cabal-version"] package `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "build-type: Simple"@@ -108,7 +121,7 @@ context "when rendering executable section" $ do it "includes dependencies" $ do- renderPackage 0 [] package {packageExecutables = [(section $ executable "foo" "Main.hs") {sectionDependencies = ["foo", "bar", "foo", "baz"]}]} `shouldBe` unlines [+ renderPackage_ 0 [] package {packageExecutables = [(section $ executable "foo" "Main.hs") {sectionDependencies = ["foo", "bar", "foo", "baz"]}]} `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "build-type: Simple"@@ -125,7 +138,7 @@ ] it "includes GHC options" $ do- renderPackage 0 [] package {packageExecutables = [(section $ executable "foo" "Main.hs") {sectionGhcOptions = ["-Wall", "-Werror"]}]} `shouldBe` unlines [+ renderPackage_ 0 [] package {packageExecutables = [(section $ executable "foo" "Main.hs") {sectionGhcOptions = ["-Wall", "-Werror"]}]} `shouldBe` unlines [ "name: foo" , "version: 0.0.0" , "build-type: Simple"@@ -174,16 +187,18 @@ describe "renderSourceRepository" $ do it "renders source-repository without subdir correctly" $ do- renderSourceRepository (SourceRepository "https://github.com/hspec/hspec" Nothing)- `shouldBe` unlines [+ let repository = SourceRepository "https://github.com/hspec/hspec" Nothing+ (render defaultRenderSettings 0 $ renderSourceRepository repository)+ `shouldBe` [ "source-repository head" , " type: git" , " location: https://github.com/hspec/hspec" ] it "renders source-repository with subdir" $ do- renderSourceRepository (SourceRepository "https://github.com/hspec/hspec" (Just "hspec-core"))- `shouldBe` unlines [+ let repository = SourceRepository "https://github.com/hspec/hspec" (Just "hspec-core")+ (render defaultRenderSettings 0 $ renderSourceRepository repository)+ `shouldBe` [ "source-repository head" , " type: git" , " location: https://github.com/hspec/hspec"