Hello community, here is the log from the commit of package hpack for openSUSE:Factory checked in at 2020-09-30 19:53:49 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/hpack (Old) and /work/SRC/openSUSE:Factory/.hpack.new.4249 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "hpack" Wed Sep 30 19:53:49 2020 rev:19 rq:838500 version:0.34.2 Changes: -------- --- /work/SRC/openSUSE:Factory/hpack/hpack.changes 2020-08-28 21:42:18.736907905 +0200 +++ /work/SRC/openSUSE:Factory/.hpack.new.4249/hpack.changes 2020-09-30 19:53:53.868758234 +0200 @@ -1,0 +2,27 @@ +Tue Sep 29 09:33:30 UTC 2020 - psimons@suse.com + +- Update hpack to version 0.34.2. + ## Changes in 0.34.2 + - Accept subcomponents as dependencies (close #382) + + ## Changes in 0.34.1 + - Fix a bug in `github: ...` introduced with `0.34.0` + (f63eb19b956517b4dd8e28dc5785be5889a99298) + + ## Changes in 0.34.0 (deprecated) + - Use `PreferNoHash` as default `GenerateHashStrategy` + - Add support for library `visibility` (see #382) + - Reject URLs for `github` + + ## Changes in 0.33.1 + - Add `GenerateHashStrategy`. The default is `PreferHash` for `0.33.0` and + will change to `PreferNoHash` with `0.34.0`. See + https://github.com/sol/hpack/pull/390) for details. + + - Add command-line options `--hash` and `--no-hash` + + ## Changes in 0.33.0.1 + - Silently ignore missing hash when the cabal file content didn't change at + all (for forward compatibility with #390) + +------------------------------------------------------------------- Old: ---- _constraints hpack-0.33.0.tar.gz New: ---- hpack-0.34.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ hpack.spec ++++++ --- /var/tmp/diff_new_pack.kSuTYw/_old 2020-09-30 19:53:54.452758756 +0200 +++ /var/tmp/diff_new_pack.kSuTYw/_new 2020-09-30 19:53:54.456758761 +0200 @@ -19,7 +19,7 @@ %global pkg_name hpack %bcond_with tests Name: %{pkg_name} -Version: 0.33.0 +Version: 0.34.2 Release: 0 Summary: A modern format for Haskell packages License: MIT @@ -78,7 +78,7 @@ This package provides the Haskell %{name} library development files. %prep -%setup -q +%autosetup %build %ghc_lib_build ++++++ hpack-0.33.0.tar.gz -> hpack-0.34.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hpack-0.33.0/CHANGELOG.md new/hpack-0.34.2/CHANGELOG.md --- old/hpack-0.33.0/CHANGELOG.md 2019-10-11 15:27:22.000000000 +0200 +++ new/hpack-0.34.2/CHANGELOG.md 2020-06-02 13:30:52.000000000 +0200 @@ -1,3 +1,26 @@ +## Changes in 0.34.2 + - Accept subcomponents as dependencies (close #382) + +## Changes in 0.34.1 + - Fix a bug in `github: ...` introduced with `0.34.0` + (f63eb19b956517b4dd8e28dc5785be5889a99298) + +## Changes in 0.34.0 (deprecated) + - Use `PreferNoHash` as default `GenerateHashStrategy` + - Add support for library `visibility` (see #382) + - Reject URLs for `github` + +## Changes in 0.33.1 + - Add `GenerateHashStrategy`. The default is `PreferHash` for `0.33.0` and + will change to `PreferNoHash` with `0.34.0`. See + https://github.com/sol/hpack/pull/390) for details. + + - Add command-line options `--hash` and `--no-hash` + +## Changes in 0.33.0.1 + - Silently ignore missing hash when the cabal file content didn't change at + all (for forward compatibility with #390) + ## Changes in 0.33.0 - Support GHC 8.8.1: `fail` is no longer a part of `Monad`. Instead, it lives in the `MonadFail` class. Adapting our code to this change meant changing diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hpack-0.33.0/hpack.cabal new/hpack-0.34.2/hpack.cabal --- old/hpack-0.33.0/hpack.cabal 2019-10-11 15:27:22.000000000 +0200 +++ new/hpack-0.34.2/hpack.cabal 2020-06-02 13:30:52.000000000 +0200 @@ -1,13 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.32.0. +-- This file has been generated from package.yaml by hpack version 0.34.2. -- -- see: https://github.com/sol/hpack --- --- hash: dc706425edd9fa60b9662cefde8da5d890fb9cf19c8f0f9e01733b763bfcd06a name: hpack -version: 0.33.0 +version: 0.34.2 synopsis: A modern format for Haskell packages description: See README at <https://github.com/sol/hpack#readme> category: Development @@ -29,7 +27,7 @@ src ghc-options: -Wall build-depends: - Cabal >=2.2 + Cabal >=3.0.0.0 , Glob >=0.9.0 , aeson >=1.4.3.0 , base >=4.9 && <5 @@ -85,7 +83,7 @@ driver ghc-options: -Wall build-depends: - Cabal >=2.2 + Cabal >=3.0.0.0 , Glob >=0.9.0 , aeson >=1.4.3.0 , base >=4.9 && <5 @@ -121,7 +119,7 @@ ghc-options: -Wall cpp-options: -DTEST build-depends: - Cabal >=2.2 + Cabal >=3.0.0.0 , Glob >=0.9.0 , HUnit >=1.6.0.0 , QuickCheck diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hpack-0.33.0/src/Hpack/CabalFile.hs new/hpack-0.34.2/src/Hpack/CabalFile.hs --- old/hpack-0.33.0/src/Hpack/CabalFile.hs 2019-10-11 15:27:22.000000000 +0200 +++ new/hpack-0.34.2/src/Hpack/CabalFile.hs 2020-06-02 13:30:52.000000000 +0200 @@ -16,7 +16,8 @@ makeVersion v = Version v [] data CabalFile = CabalFile { - cabalFileHpackVersion :: Maybe Version + cabalFileCabalVersion :: [String] +, cabalFileHpackVersion :: Maybe Version , cabalFileHash :: Maybe Hash , cabalFileContents :: [String] } deriving (Eq, Show) @@ -25,13 +26,13 @@ readCabalFile cabalFile = fmap parse <$> tryReadFile cabalFile where parse :: String -> CabalFile - parse (splitHeader -> (h, c)) = CabalFile (extractVersion h) (extractHash h) c + parse (splitHeader -> (cabalVersion, h, c)) = CabalFile cabalVersion (extractVersion h) (extractHash h) c - splitHeader :: String -> ([String], [String]) + splitHeader :: String -> ([String], [String], [String]) splitHeader (removeGitConflictMarkers . lines -> c) = case span (not . isComment) c of (cabalVersion, xs) -> case span isComment xs of - (header, body) -> (header, cabalVersion ++ dropWhile null body) + (header, body) -> (cabalVersion, header, dropWhile null body) isComment = ("--" `isPrefixOf`) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hpack-0.33.0/src/Hpack/Config.hs new/hpack-0.34.2/src/Hpack/Config.hs --- old/hpack-0.33.0/src/Hpack/Config.hs 2019-10-11 15:27:22.000000000 +0200 +++ new/hpack-0.34.2/src/Hpack/Config.hs 2020-06-02 13:30:52.000000000 +0200 @@ -39,6 +39,7 @@ , section , Package(..) , Dependencies(..) +, DependencyInfo(..) , VersionConstraint(..) , DependencyVersion(..) , SourceDependency(..) @@ -195,6 +196,7 @@ data LibrarySection = LibrarySection { librarySectionExposed :: Maybe Bool +, librarySectionVisibility :: Maybe String , librarySectionExposedModules :: Maybe (List String) , librarySectionGeneratedExposedModules :: Maybe (List String) , librarySectionOtherModules :: Maybe (List String) @@ -204,12 +206,13 @@ } deriving (Eq, Show, Generic, FromValue) instance Monoid LibrarySection where - mempty = LibrarySection Nothing Nothing Nothing Nothing Nothing Nothing Nothing + mempty = LibrarySection Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing mappend = (<>) instance Semigroup LibrarySection where a <> b = LibrarySection { librarySectionExposed = librarySectionExposed b <|> librarySectionExposed a + , librarySectionVisibility = librarySectionVisibility b <|> librarySectionVisibility a , librarySectionExposedModules = librarySectionExposedModules a <> librarySectionExposedModules b , librarySectionGeneratedExposedModules = librarySectionGeneratedExposedModules a <> librarySectionGeneratedExposedModules b , librarySectionOtherModules = librarySectionOtherModules a <> librarySectionOtherModules b @@ -531,7 +534,7 @@ , packageConfigExtraDocFiles :: Maybe (List FilePath) , packageConfigDataFiles :: Maybe (List FilePath) , packageConfigDataDir :: Maybe FilePath -, packageConfigGithub :: Maybe Text +, packageConfigGithub :: Maybe GitHub , packageConfigGit :: Maybe String , packageConfigCustomSetup :: Maybe CustomSetupSection , packageConfigLibrary :: Maybe library @@ -542,6 +545,20 @@ , packageConfigBenchmarks :: Maybe (Map String executable) } deriving Generic +data GitHub = GitHub { + _gitHubOwner :: String +, _gitHubRepo :: String +, _gitHubSubdir :: Maybe String +} + +instance FromValue GitHub where + fromValue v = do + input <- fromValue v + case map T.unpack $ T.splitOn "/" input of + [owner, repo, subdir] -> return $ GitHub owner repo (Just subdir) + [owner, repo] -> return $ GitHub owner repo Nothing + _ -> fail $ "expected owner/repo or owner/repo/subdir, but encountered " ++ show input + data DefaultsConfig = DefaultsConfig { defaultsConfigDefaults :: Maybe (List Defaults) } deriving (Generic, FromValue) @@ -689,15 +706,14 @@ libraryCabalVersion :: Section Library -> Maybe Version libraryCabalVersion sect = maximum [ - makeVersion [1,22] <$ guard hasReexportedModules - , makeVersion [2,0] <$ guard hasSignatures - , makeVersion [2,0] <$ guard hasGeneratedModules + makeVersion [1,22] <$ guard (has libraryReexportedModules) + , makeVersion [2,0] <$ guard (has librarySignatures) + , makeVersion [2,0] <$ guard (has libraryGeneratedModules) + , makeVersion [3,0] <$ guard (has libraryVisibility) , sectionCabalVersion sect ] where - hasReexportedModules = any (not . null . libraryReexportedModules) sect - hasSignatures = any (not . null . librarySignatures) sect - hasGeneratedModules = any (not . null . libraryGeneratedModules) sect + has field = any (not . null . field) sect internalLibsCabalVersion :: Map String (Section Library) -> Maybe Version internalLibsCabalVersion internalLibraries @@ -723,6 +739,7 @@ makeVersion [2,2] <$ guard (sectionSatisfies (not . null . sectionCxxSources) sect) , makeVersion [2,2] <$ guard (sectionSatisfies (not . null . sectionCxxOptions) sect) , makeVersion [2,0] <$ guard (sectionSatisfies (any hasMixins . unDependencies . sectionDependencies) sect) + , makeVersion [3,0] <$ guard (sectionSatisfies (any hasSubcomponents . Map.keys . unDependencies . sectionDependencies) sect) ] ++ map versionFromSystemBuildTool systemBuildTools where versionFromSystemBuildTool name @@ -782,6 +799,9 @@ hasMixins :: DependencyInfo -> Bool hasMixins (DependencyInfo mixins _) = not (null mixins) + hasSubcomponents :: String -> Bool + hasSubcomponents = elem ':' + decodeValue :: FromValue a => ProgramName -> FilePath -> Value -> Warnings (Errors IO) a decodeValue (ProgramName programName) file value = do (r, unknown) <- lift . ExceptT . return $ first (prefix ++) (Config.decodeValue value) @@ -851,6 +871,7 @@ data Library = Library { libraryExposed :: Maybe Bool +, libraryVisibility :: Maybe String , libraryExposedModules :: [String] , libraryOtherModules :: [String] , libraryGeneratedModules :: [String] @@ -1146,13 +1167,10 @@ sourceRepository = github <|> (`SourceRepository` Nothing) <$> packageConfigGit github :: Maybe SourceRepository - github = parseGithub <$> packageConfigGithub + github = toSourceRepository <$> packageConfigGithub where - parseGithub :: Text -> SourceRepository - parseGithub input = case map T.unpack $ T.splitOn "/" input of - [owner, repo, subdir] -> - SourceRepository (githubBaseUrl ++ owner ++ "/" ++ repo) (Just subdir) - _ -> SourceRepository (githubBaseUrl ++ T.unpack input) Nothing + toSourceRepository :: GitHub -> SourceRepository + toSourceRepository (GitHub owner repo subdir) = SourceRepository (githubBaseUrl ++ owner ++ "/" ++ repo) subdir homepage :: Maybe String homepage = case packageConfigHomepage of @@ -1217,7 +1235,7 @@ traverseConditionals = traverse . traverse . traverseSectionAndConditionals fConditionals fConditionals getMentionedLibraryModules :: LibrarySection -> [String] -getMentionedLibraryModules (LibrarySection _ exposedModules generatedExposedModules otherModules generatedOtherModules _ _) +getMentionedLibraryModules (LibrarySection _ _ exposedModules generatedExposedModules otherModules generatedOtherModules _ _) = fromMaybeList (exposedModules <> generatedExposedModules <> otherModules <> generatedOtherModules) listModules :: FilePath -> Section a -> IO [String] @@ -1254,7 +1272,7 @@ getLibraryModules Library{..} = libraryExposedModules ++ libraryOtherModules fromLibrarySectionTopLevel pathsModule inferableModules LibrarySection{..} = - Library librarySectionExposed exposedModules otherModules generatedModules reexportedModules signatures + Library librarySectionExposed librarySectionVisibility exposedModules otherModules generatedModules reexportedModules signatures where (exposedModules, otherModules, generatedModules) = determineModules pathsModule inferableModules librarySectionExposedModules librarySectionGeneratedExposedModules librarySectionOtherModules librarySectionGeneratedOtherModules @@ -1270,7 +1288,7 @@ others = maybe ((inferable \\ exposed) ++ pathsModule) fromList mOther ++ fromMaybeList mGeneratedOther fromLibrarySectionInConditional :: [String] -> LibrarySection -> Library -fromLibrarySectionInConditional inferableModules lib@(LibrarySection _ exposedModules _ otherModules _ _ _) = +fromLibrarySectionInConditional inferableModules lib@(LibrarySection _ _ exposedModules _ otherModules _ _ _) = case (exposedModules, otherModules) of (Nothing, Nothing) -> addToOtherModules inferableModules (fromLibrarySectionPlain lib) _ -> fromLibrarySectionPlain lib @@ -1280,6 +1298,7 @@ fromLibrarySectionPlain :: LibrarySection -> Library fromLibrarySectionPlain LibrarySection{..} = Library { libraryExposed = librarySectionExposed + , libraryVisibility = librarySectionVisibility , libraryExposedModules = fromMaybeList (librarySectionExposedModules <> librarySectionGeneratedExposedModules) , libraryOtherModules = fromMaybeList (librarySectionOtherModules <> librarySectionGeneratedOtherModules) , libraryGeneratedModules = fromMaybeList (librarySectionGeneratedOtherModules <> librarySectionGeneratedExposedModules) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hpack-0.33.0/src/Hpack/License.hs new/hpack-0.34.2/src/Hpack/License.hs --- old/hpack-0.33.0/src/Hpack/License.hs 2019-10-11 15:27:22.000000000 +0200 +++ new/hpack-0.34.2/src/Hpack/License.hs 2020-06-02 13:30:52.000000000 +0200 @@ -10,11 +10,7 @@ import Distribution.Version (mkVersion) import qualified Distribution.License as Cabal import qualified Distribution.SPDX.License as SPDX -#if MIN_VERSION_Cabal(3,0,0) import Distribution.Parsec (eitherParsec) -#else -import Distribution.Parsec.Class (eitherParsec) -#endif import qualified Data.License.Infer as Infer diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hpack-0.33.0/src/Hpack/Options.hs new/hpack-0.34.2/src/Hpack/Options.hs --- old/hpack-0.33.0/src/Hpack/Options.hs 2019-10-11 15:27:22.000000000 +0200 +++ new/hpack-0.34.2/src/Hpack/Options.hs 2020-06-02 13:30:52.000000000 +0200 @@ -1,6 +1,9 @@ {-# LANGUAGE LambdaCase #-} module Hpack.Options where +import Control.Applicative +import Control.Monad +import Data.Maybe import System.FilePath import System.Directory @@ -16,6 +19,7 @@ data ParseOptions = ParseOptions { parseOptionsVerbose :: Verbose , parseOptionsForce :: Force +, parseOptionsHash :: Maybe Bool , parseOptionsToStdout :: Bool , parseOptionsTarget :: FilePath } deriving (Eq, Show) @@ -30,18 +34,30 @@ file <- expandTarget defaultTarget target let options - | toStdout = ParseOptions NoVerbose Force toStdout file - | otherwise = ParseOptions verbose force toStdout file + | toStdout = ParseOptions NoVerbose Force hash toStdout file + | otherwise = ParseOptions verbose force hash toStdout file return (Run options) Left err -> return err where silentFlag = "--silent" forceFlags = ["--force", "-f"] + hashFlag = "--hash" + noHashFlag = "--no-hash" - flags = silentFlag : forceFlags + flags = hashFlag : noHashFlag : silentFlag : forceFlags + verbose :: Verbose verbose = if silentFlag `elem` args then NoVerbose else Verbose + + force :: Force force = if any (`elem` args) forceFlags then Force else NoForce + + hash :: Maybe Bool + hash = listToMaybe . reverse $ mapMaybe parse args + where + parse :: String -> Maybe Bool + parse t = True <$ guard (t == hashFlag) <|> False <$ guard (t == noHashFlag) + ys = filter (`notElem` flags) args targets :: Either ParseResult (Maybe FilePath, Bool) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hpack-0.33.0/src/Hpack/Render.hs new/hpack-0.34.2/src/Hpack/Render.hs --- old/hpack-0.33.0/src/Hpack/Render.hs 2019-10-11 15:27:22.000000000 +0200 +++ new/hpack-0.34.2/src/Hpack/Render.hs 2020-06-02 13:30:52.000000000 +0200 @@ -45,7 +45,6 @@ import Hpack.Config import Hpack.Render.Hints import Hpack.Render.Dsl -import Hpack.Syntax.Dependencies renderPackage :: [String] -> Package -> String renderPackage oldCabalFile = renderPackageWith settings alignment formattingHintsFieldOrder formattingHintsSectionsFieldOrder @@ -207,7 +206,8 @@ renderLibraryFields :: Library -> [Element] renderLibraryFields Library{..} = - maybe [] (return . renderExposed) libraryExposed ++ [ + maybe [] (return . renderExposed) libraryExposed ++ + maybe [] (return . renderVisibility) libraryVisibility ++ [ renderExposedModules libraryExposedModules , renderOtherModules libraryOtherModules , renderGeneratedModules libraryGeneratedModules @@ -218,6 +218,9 @@ renderExposed :: Bool -> Element renderExposed = Field "exposed" . Literal . show +renderVisibility :: String -> Element +renderVisibility = Field "visibility" . Literal + renderSection :: (a -> [Element]) -> [Element] -> [Element] -> Section a -> [Element] renderSection renderSectionData extraFieldsStart extraFieldsEnd Section{..} = addVerbatim sectionVerbatim $ extraFieldsStart diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hpack-0.33.0/src/Hpack/Syntax/Dependencies.hs new/hpack-0.34.2/src/Hpack/Syntax/Dependencies.hs --- old/hpack-0.33.0/src/Hpack/Syntax/Dependencies.hs 2019-10-11 15:27:22.000000000 +0200 +++ new/hpack-0.34.2/src/Hpack/Syntax/Dependencies.hs 2020-06-02 13:30:52.000000000 +0200 @@ -9,9 +9,12 @@ import qualified Control.Monad.Fail as Fail import Data.Text (Text) +import Data.List import qualified Data.Text as T import Data.Semigroup (Semigroup(..)) import qualified Distribution.Package as D +import qualified Distribution.Types.LibraryName as D +import Distribution.Pretty (prettyShow) import Data.Map.Lazy (Map) import qualified Data.Map.Lazy as Map import GHC.Exts @@ -64,4 +67,10 @@ parseDependency subject = fmap fromCabal . cabalParse subject . T.unpack where fromCabal :: D.Dependency -> (String, DependencyVersion) - fromCabal d = (D.unPackageName $ D.depPkgName d, DependencyVersion Nothing . versionConstraintFromCabal $ D.depVerRange d) + fromCabal d = (toName (D.depPkgName d) (toList $ D.depLibraries d), DependencyVersion Nothing . versionConstraintFromCabal $ D.depVerRange d) + + toName :: D.PackageName -> [D.LibraryName] -> String + toName package components = prettyShow package <> case components of + [D.LMainLibName] -> "" + [D.LSubLibName lib] -> ":" <> prettyShow lib + xs -> ":{" <> (intercalate "," $ map prettyShow [name | D.LSubLibName name <- xs]) <> "}" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hpack-0.33.0/src/Hpack/Syntax/DependencyVersion.hs new/hpack-0.34.2/src/Hpack/Syntax/DependencyVersion.hs --- old/hpack-0.33.0/src/Hpack/Syntax/DependencyVersion.hs 2019-10-11 15:27:22.000000000 +0200 +++ new/hpack-0.34.2/src/Hpack/Syntax/DependencyVersion.hs 2020-06-02 13:30:52.000000000 +0200 @@ -36,13 +36,8 @@ import Distribution.Version (VersionRangeF(..)) import qualified Distribution.Version as D -#if MIN_VERSION_Cabal(3,0,0) import qualified Distribution.Parsec as D import qualified Distribution.Pretty as D -#else -import qualified Distribution.Parsec.Class as D -import qualified Distribution.Text as D -#endif import Data.Aeson.Config.FromValue @@ -156,11 +151,7 @@ versionConstraintFromCabal range | D.isAnyVersion range = AnyVersion | otherwise = VersionRange . renderStyle style . -#if MIN_VERSION_Cabal(3,0,0) D.pretty -#else - D.disp -#endif $ toPreCabal2VersionRange range where style = Style OneLineMode 0 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hpack-0.33.0/src/Hpack.hs new/hpack-0.34.2/src/Hpack.hs --- old/hpack-0.33.0/src/Hpack.hs 2019-10-11 15:27:22.000000000 +0200 +++ new/hpack-0.34.2/src/Hpack.hs 2020-06-02 13:30:52.000000000 +0200 @@ -1,4 +1,5 @@ {-# LANGUAGE CPP #-} +{-# LANGUAGE ViewPatterns #-} {-# LANGUAGE RecordWildCards #-} module Hpack ( -- | /__NOTE:__/ This module is exposed to allow integration of Hpack into @@ -32,10 +33,12 @@ , Verbose(..) , Options(..) , Force(..) +, GenerateHashStrategy(..) #ifdef TEST , hpackResultWithVersion , header +, renderCabalFile #endif ) where @@ -47,6 +50,7 @@ import System.Exit import System.IO (stderr) import Data.Aeson (Value) +import Data.Maybe import Paths_hpack (version) import Hpack.Options @@ -56,31 +60,35 @@ import Hpack.Utf8 as Utf8 import Hpack.CabalFile -programVersion :: Version -> String -programVersion v = "hpack version " ++ Version.showVersion v +programVersion :: Maybe Version -> String +programVersion Nothing = "hpack" +programVersion (Just v) = "hpack version " ++ Version.showVersion v -header :: FilePath -> Version -> Hash -> String -header p v hash = unlines [ +header :: FilePath -> Maybe Version -> (Maybe Hash) -> [String] +header p v hash = [ "-- This file has been generated from " ++ takeFileName p ++ " by " ++ programVersion v ++ "." , "--" , "-- see: https://github.com/sol/hpack" - , "--" - , "-- hash: " ++ hash - , "" - ] + ] ++ case hash of + Just h -> ["--" , "-- hash: " ++ h, ""] + Nothing -> [""] data Options = Options { optionsDecodeOptions :: DecodeOptions , optionsForce :: Force +, optionsGenerateHashStrategy :: GenerateHashStrategy , optionsToStdout :: Bool } +data GenerateHashStrategy = ForceHash | ForceNoHash | PreferHash | PreferNoHash + deriving (Eq, Show) + getOptions :: FilePath -> [String] -> IO (Maybe (Verbose, Options)) getOptions defaultPackageConfig args = do result <- parseOptions defaultPackageConfig args case result of PrintVersion -> do - putStrLn (programVersion version) + putStrLn (programVersion $ Just version) return Nothing PrintNumericVersion -> do putStrLn (Version.showVersion version) @@ -88,9 +96,12 @@ Help -> do printHelp return Nothing - Run options -> case options of - ParseOptions verbose force toStdout file -> do - return $ Just (verbose, Options defaultDecodeOptions {decodeOptionsTarget = file} force toStdout) + Run (ParseOptions verbose force hash toStdout file) -> do + let generateHash = case hash of + Just True -> ForceHash + Just False -> ForceNoHash + Nothing -> PreferNoHash + return $ Just (verbose, Options defaultDecodeOptions {decodeOptionsTarget = file} force generateHash toStdout) ParseError -> do printHelp exitFailure @@ -99,7 +110,7 @@ printHelp = do name <- getProgName Utf8.hPutStrLn stderr $ unlines [ - "Usage: " ++ name ++ " [ --silent ] [ --force | -f ] [ PATH ] [ - ]" + "Usage: " ++ name ++ " [ --silent ] [ --force | -f ] [ --[no-]hash ] [ PATH ] [ - ]" , " " ++ name ++ " --version" , " " ++ name ++ " --numeric-version" , " " ++ name ++ " --help" @@ -109,7 +120,7 @@ hpack verbose options = hpackResult options >>= printResult verbose defaultOptions :: Options -defaultOptions = Options defaultDecodeOptions NoForce False +defaultOptions = Options defaultDecodeOptions NoForce PreferNoHash False setTarget :: FilePath -> Options -> Options setTarget target options@Options{..} = @@ -154,41 +165,76 @@ printWarnings :: [String] -> IO () printWarnings = mapM_ $ Utf8.hPutStrLn stderr . ("WARNING: " ++) -mkStatus :: [String] -> Version -> CabalFile -> Status -mkStatus new v (CabalFile mOldVersion mHash old) = case (mOldVersion, mHash) of - (Nothing, _) -> ExistingCabalFileWasModifiedManually - (Just oldVersion, _) | oldVersion < makeVersion [0, 20, 0] -> Generated - (_, Nothing) -> ExistingCabalFileWasModifiedManually - (Just oldVersion, Just hash) - | old == new -> OutputUnchanged - | v < oldVersion -> AlreadyGeneratedByNewerHpack - | sha256 (unlines old) /= hash -> ExistingCabalFileWasModifiedManually - | otherwise -> Generated +mkStatus :: CabalFile -> CabalFile -> Status +mkStatus new@(CabalFile _ mNewVersion mNewHash _) existing@(CabalFile _ mExistingVersion _ _) + | new `hasSameContent` existing = OutputUnchanged + | otherwise = case mExistingVersion of + Nothing -> ExistingCabalFileWasModifiedManually + Just _ + | mNewVersion < mExistingVersion -> AlreadyGeneratedByNewerHpack + | isJust mNewHash && hashMismatch existing -> ExistingCabalFileWasModifiedManually + | otherwise -> Generated + +hasSameContent :: CabalFile -> CabalFile -> Bool +hasSameContent (CabalFile cabalVersionA _ _ a) (CabalFile cabalVersionB _ _ b) = cabalVersionA == cabalVersionB && a == b + +hashMismatch :: CabalFile -> Bool +hashMismatch cabalFile = case cabalFileHash cabalFile of + Nothing -> False + Just hash -> hash /= calculateHash cabalFile + +calculateHash :: CabalFile -> Hash +calculateHash (CabalFile cabalVersion _ _ body) = sha256 (unlines $ cabalVersion ++ body) hpackResult :: Options -> IO Result hpackResult = hpackResultWithVersion version hpackResultWithVersion :: Version -> Options -> IO Result -hpackResultWithVersion v (Options options force toStdout) = do - DecodeResult pkg cabalVersion cabalFile warnings <- readPackageConfig options >>= either die return - oldCabalFile <- readCabalFile cabalFile - let - body = renderPackage (maybe [] cabalFileContents oldCabalFile) pkg - withoutHeader = cabalVersion ++ body +hpackResultWithVersion v (Options options force generateHashStrategy toStdout) = do + DecodeResult pkg (lines -> cabalVersion) cabalFileName warnings <- readPackageConfig options >>= either die return + mExistingCabalFile <- readCabalFile cabalFileName let + newCabalFile = makeCabalFile generateHashStrategy mExistingCabalFile cabalVersion v pkg + status = case force of Force -> Generated - NoForce -> maybe Generated (mkStatus (lines withoutHeader) v) oldCabalFile + NoForce -> maybe Generated (mkStatus newCabalFile) mExistingCabalFile + case status of - Generated -> do - let hash = sha256 withoutHeader - out = cabalVersion ++ header (decodeOptionsTarget options) v hash ++ body - if toStdout - then Utf8.putStr out - else Utf8.writeFile cabalFile out + Generated -> writeCabalFile options toStdout cabalFileName newCabalFile _ -> return () + return Result { - resultWarnings = warnings - , resultCabalFile = cabalFile - , resultStatus = status - } + resultWarnings = warnings + , resultCabalFile = cabalFileName + , resultStatus = status + } + +writeCabalFile :: DecodeOptions -> Bool -> FilePath -> CabalFile -> IO () +writeCabalFile options toStdout name cabalFile = do + write . unlines $ renderCabalFile (decodeOptionsTarget options) cabalFile + where + write = if toStdout then Utf8.putStr else Utf8.writeFile name + +makeCabalFile :: GenerateHashStrategy -> Maybe CabalFile -> [String] -> Version -> Package -> CabalFile +makeCabalFile strategy mExistingCabalFile cabalVersion v pkg = cabalFile + where + cabalFile = CabalFile cabalVersion (Just v) hash body + + hash + | shouldGenerateHash mExistingCabalFile strategy = Just $ calculateHash cabalFile + | otherwise = Nothing + + body = lines $ renderPackage (maybe [] cabalFileContents mExistingCabalFile) pkg + +shouldGenerateHash :: Maybe CabalFile -> GenerateHashStrategy -> Bool +shouldGenerateHash mExistingCabalFile strategy = case (strategy, mExistingCabalFile) of + (ForceHash, _) -> True + (ForceNoHash, _) -> False + (PreferHash, Nothing) -> True + (PreferNoHash, Nothing) -> False + (_, Just CabalFile {cabalFileHash = Nothing}) -> False + (_, Just CabalFile {cabalFileHash = Just _}) -> True + +renderCabalFile :: FilePath -> CabalFile -> [String] +renderCabalFile file (CabalFile cabalVersion hpackVersion hash body) = cabalVersion ++ header file hpackVersion hash ++ body diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hpack-0.33.0/test/EndToEndSpec.hs new/hpack-0.34.2/test/EndToEndSpec.hs --- old/hpack-0.33.0/test/EndToEndSpec.hs 2019-10-11 15:27:22.000000000 +0200 +++ new/hpack-0.34.2/test/EndToEndSpec.hs 2020-06-02 13:30:52.000000000 +0200 @@ -63,7 +63,6 @@ it "fails on unsupported spec-version" $ do [i| spec-version: 25.0 - dependencies: foo == bar |] `shouldFailWith` ("The file package.yaml requires version 25.0 of the Hpack package specification, however this version of hpack only supports versions up to " ++ showVersion Hpack.version ++ ". Upgrading to the latest version of hpack may resolve this issue.") it "fails on unsupported spec-version from defaults" $ do @@ -111,13 +110,13 @@ describe "github" $ do it "accepts owner/repo" $ do [i| - github: hspec/hspec + github: sol/hpack |] `shouldRenderTo` package [i| - homepage: https://github.com/hspec/hspec#readme - bug-reports: https://github.com/hspec/hspec/issues + homepage: https://github.com/sol/hpack#readme + bug-reports: https://github.com/sol/hpack/issues source-repository head type: git - location: https://github.com/hspec/hspec + location: https://github.com/sol/hpack |] it "accepts owner/repo/path" $ do @@ -132,6 +131,11 @@ subdir: hspec-core |] + it "rejects URLs" $ do + [i| + github: https://github.com/sol/hpack/issues/365 + |] `shouldFailWith` "package.yaml: Error while parsing $.github - expected owner/repo or owner/repo/subdir, but encountered \"https://github.com/sol/hpack/issues/365\"" + describe "homepage" $ do it "accepts homepage URL" $ do [i| @@ -606,6 +610,15 @@ base |] + it "accepts dependencies with subcomponents" $ do + [i| + executable: + dependencies: foo:bar + |] `shouldRenderTo` (executable_ "foo" [i| + build-depends: + foo:bar + |]) {packageCabalVersion = "3.0"} + it "accepts list of dependencies" $ do [i| executable: @@ -1134,14 +1147,14 @@ internal-libraries: bar: source-dirs: src - |] `shouldRenderTo` internalLibrary "bar" [i| - exposed-modules: - Foo - other-modules: - Paths_foo - hs-source-dirs: - src - |] + |] `shouldRenderTo` internalLibrary "bar" [i| + exposed-modules: + Foo + other-modules: + Paths_foo + hs-source-dirs: + src + |] it "warns on unknown fields" $ do [i| @@ -1159,6 +1172,17 @@ source-dirs: src |] `shouldWarn` pure "Specified source-dir \"src\" does not exist" + it "accepts visibility" $ do + [i| + internal-libraries: + bar: + visibility: public + |] `shouldRenderTo` (internalLibrary "bar" [i| + visibility: public + other-modules: + Paths_foo + |]) {packageCabalVersion = "3.0"} + describe "executables" $ do it "accepts arbitrary entry points as main" $ do touch "src/Foo.hs" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hpack-0.33.0/test/Hpack/CabalFileSpec.hs new/hpack-0.34.2/test/Hpack/CabalFileSpec.hs --- old/hpack-0.33.0/test/Hpack/CabalFileSpec.hs 2019-10-11 15:27:22.000000000 +0200 +++ new/hpack-0.34.2/test/Hpack/CabalFileSpec.hs 2020-06-02 13:30:52.000000000 +0200 @@ -9,9 +9,15 @@ import Paths_hpack (version) +import Hpack.Util (Hash) +import Data.Version (Version) import Hpack (header) + import Hpack.CabalFile +mkHeader :: FilePath -> Version -> Hash -> String +mkHeader p v hash = unlines $ header p (Just v) (Just hash) + spec :: Spec spec = do describe "readCabalFile" $ do @@ -21,13 +27,13 @@ it "includes hash" $ do inTempDirectory $ do - writeFile file $ header "package.yaml" version hash - readCabalFile file `shouldReturn` Just (CabalFile (Just version) (Just hash) []) + writeFile file $ mkHeader "package.yaml" version hash + readCabalFile file `shouldReturn` Just (CabalFile [] (Just version) (Just hash) []) it "accepts cabal-version at the beginning of the file" $ do inTempDirectory $ do - writeFile file $ ("cabal-version: 2.2\n" ++ header "package.yaml" version hash) - readCabalFile file `shouldReturn` Just (CabalFile (Just version) (Just hash) ["cabal-version: 2.2"]) + writeFile file $ ("cabal-version: 2.2\n" ++ mkHeader "package.yaml" version hash) + readCabalFile file `shouldReturn` Just (CabalFile ["cabal-version: 2.2"] (Just version) (Just hash) []) describe "extractVersion" $ do it "extracts Hpack version from a cabal file" $ do diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hpack-0.33.0/test/Hpack/ConfigSpec.hs new/hpack-0.34.2/test/Hpack/ConfigSpec.hs --- old/hpack-0.33.0/test/Hpack/ConfigSpec.hs 2019-10-11 15:27:22.000000000 +0200 +++ new/hpack-0.34.2/test/Hpack/ConfigSpec.hs 2020-06-02 13:30:52.000000000 +0200 @@ -54,7 +54,7 @@ executable main_ = Executable (Just main_) ["Paths_foo"] [] library :: Library -library = Library Nothing [] ["Paths_foo"] [] [] [] +library = Library Nothing Nothing [] ["Paths_foo"] [] [] [] testDecodeOptions :: FilePath -> DecodeOptions testDecodeOptions file = defaultDecodeOptions {decodeOptionsTarget = file, decodeOptionsUserDataDir = Just undefined} @@ -90,6 +90,7 @@ let sect = LibrarySection { librarySectionExposed = Nothing + , librarySectionVisibility = Nothing , librarySectionExposedModules = Nothing , librarySectionGeneratedExposedModules = Nothing , librarySectionOtherModules = Nothing @@ -99,6 +100,7 @@ } lib = Library { libraryExposed = Nothing + , libraryVisibility = Nothing , libraryExposedModules = [] , libraryOtherModules = [] , libraryGeneratedModules = [] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hpack-0.33.0/test/Hpack/LicenseSpec.hs new/hpack-0.34.2/test/Hpack/LicenseSpec.hs --- old/hpack-0.33.0/test/Hpack/LicenseSpec.hs 2019-10-11 15:27:22.000000000 +0200 +++ new/hpack-0.34.2/test/Hpack/LicenseSpec.hs 2020-06-02 13:30:52.000000000 +0200 @@ -7,11 +7,7 @@ import Data.String.Interpolate import Distribution.Pretty (prettyShow) -#if MIN_VERSION_Cabal(3,0,0) import Distribution.Parsec (simpleParsec) -#else -import Distribution.Parsec.Class (simpleParsec) -#endif import qualified Distribution.License as Cabal import Hpack.License diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hpack-0.33.0/test/Hpack/OptionsSpec.hs new/hpack-0.34.2/test/Hpack/OptionsSpec.hs --- old/hpack-0.33.0/test/Hpack/OptionsSpec.hs 2019-10-11 15:27:22.000000000 +0200 +++ new/hpack-0.34.2/test/Hpack/OptionsSpec.hs 2020-06-02 13:30:52.000000000 +0200 @@ -18,10 +18,10 @@ context "by default" $ do it "returns Run" $ do - parseOptions defaultTarget [] `shouldReturn` Run (ParseOptions Verbose NoForce False defaultTarget) + parseOptions defaultTarget [] `shouldReturn` Run (ParseOptions Verbose NoForce Nothing False defaultTarget) it "includes target" $ do - parseOptions defaultTarget ["foo.yaml"] `shouldReturn` Run (ParseOptions Verbose NoForce False "foo.yaml") + parseOptions defaultTarget ["foo.yaml"] `shouldReturn` Run (ParseOptions Verbose NoForce Nothing False "foo.yaml") context "with superfluous arguments" $ do it "returns ParseError" $ do @@ -29,19 +29,31 @@ context "with --silent" $ do it "sets optionsVerbose to NoVerbose" $ do - parseOptions defaultTarget ["--silent"] `shouldReturn` Run (ParseOptions NoVerbose NoForce False defaultTarget) + parseOptions defaultTarget ["--silent"] `shouldReturn` Run (ParseOptions NoVerbose NoForce Nothing False defaultTarget) context "with --force" $ do it "sets optionsForce to Force" $ do - parseOptions defaultTarget ["--force"] `shouldReturn` Run (ParseOptions Verbose Force False defaultTarget) + parseOptions defaultTarget ["--force"] `shouldReturn` Run (ParseOptions Verbose Force Nothing False defaultTarget) context "with -f" $ do it "sets optionsForce to Force" $ do - parseOptions defaultTarget ["-f"] `shouldReturn` Run (ParseOptions Verbose Force False defaultTarget) + parseOptions defaultTarget ["-f"] `shouldReturn` Run (ParseOptions Verbose Force Nothing False defaultTarget) + + context "when determining parseOptionsHash" $ do + + it "assumes True on --hash" $ do + parseOptions defaultTarget ["--hash"] `shouldReturn` Run (ParseOptions Verbose NoForce (Just True) False defaultTarget) + + it "assumes False on --no-hash" $ do + parseOptions defaultTarget ["--no-hash"] `shouldReturn` Run (ParseOptions Verbose NoForce (Just False) False defaultTarget) + + it "gives last occurrence precedence" $ do + parseOptions defaultTarget ["--no-hash", "--hash"] `shouldReturn` Run (ParseOptions Verbose NoForce (Just True) False defaultTarget) + parseOptions defaultTarget ["--hash", "--no-hash"] `shouldReturn` Run (ParseOptions Verbose NoForce (Just False) False defaultTarget) context "with -" $ do it "sets optionsToStdout to True, implies Force and NoVerbose" $ do - parseOptions defaultTarget ["-"] `shouldReturn` Run (ParseOptions NoVerbose Force True defaultTarget) + parseOptions defaultTarget ["-"] `shouldReturn` Run (ParseOptions NoVerbose Force Nothing True defaultTarget) it "rejects - for target" $ do parseOptions defaultTarget ["-", "-"] `shouldReturn` ParseError diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hpack-0.33.0/test/Hpack/RenderSpec.hs new/hpack-0.34.2/test/Hpack/RenderSpec.hs --- old/hpack-0.33.0/test/Hpack/RenderSpec.hs 2019-10-11 15:27:22.000000000 +0200 +++ new/hpack-0.34.2/test/Hpack/RenderSpec.hs 2020-06-02 13:30:52.000000000 +0200 @@ -10,10 +10,9 @@ import Hpack.Config hiding (package) import Hpack.Render.Dsl import Hpack.Render -import Hpack.Syntax.Dependencies library :: Library -library = Library Nothing [] [] [] [] [] +library = Library Nothing Nothing [] [] [] [] [] executable :: Section Executable executable = section (Executable (Just "Main.hs") [] []) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hpack-0.33.0/test/Hpack/Syntax/DependenciesSpec.hs new/hpack-0.34.2/test/Hpack/Syntax/DependenciesSpec.hs --- old/hpack-0.33.0/test/Hpack/Syntax/DependenciesSpec.hs 2019-10-11 15:27:22.000000000 +0200 +++ new/hpack-0.34.2/test/Hpack/Syntax/DependenciesSpec.hs 2020-06-02 13:30:52.000000000 +0200 @@ -1,5 +1,6 @@ {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE OverloadedLists #-} +{-# LANGUAGE OverloadedStrings #-} module Hpack.Syntax.DependenciesSpec (spec) where import Helper @@ -18,6 +19,16 @@ spec :: Spec spec = do + describe "parseDependency" $ do + it "accepts dependencies" $ do + parseDependency "dependency" "foo" `shouldReturn` ("foo", DependencyVersion Nothing AnyVersion) + + it "accepts dependencies with a subcomponent" $ do + parseDependency "dependency" "foo:bar" `shouldReturn` ("foo:bar", DependencyVersion Nothing AnyVersion) + + it "accepts dependencies with multiple subcomponents" $ do + parseDependency "dependency" "foo:{bar,baz}" `shouldReturn` ("foo:{bar,baz}", DependencyVersion Nothing AnyVersion) + describe "fromValue" $ do context "when parsing Dependencies" $ do context "with a scalar" $ do diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hpack-0.33.0/test/HpackSpec.hs new/hpack-0.34.2/test/HpackSpec.hs --- old/hpack-0.33.0/test/HpackSpec.hs 2019-10-11 15:27:22.000000000 +0200 +++ new/hpack-0.34.2/test/HpackSpec.hs 2020-06-02 13:30:52.000000000 +0200 @@ -16,87 +16,139 @@ spec :: Spec spec = do - describe "hpackResult" $ do - context "with existing cabal file" $ around_ inTempDirectory $ before_ (writeFile packageConfig "name: foo") $ do - let - file = "foo.cabal" - - hpackWithVersion v = hpackResultWithVersion v defaultOptions - hpack = hpackResult defaultOptions - hpackForce = hpackResult defaultOptions {optionsForce = Force} - - generated = Result [] file Generated - modifiedManually = Result [] file ExistingCabalFileWasModifiedManually - outputUnchanged = Result [] file OutputUnchanged - alreadyGeneratedByNewerHpack = Result [] file AlreadyGeneratedByNewerHpack - - context "when cabal file was created manually" $ do - it "does not overwrite existing cabal file" $ do - let existing = "some existing cabal file" - writeFile file existing - hpack `shouldReturn` modifiedManually + describe "header" $ do + it "generates header" $ do + header "foo.yaml" Nothing Nothing `shouldBe` [ + "-- This file has been generated from foo.yaml by hpack." + , "--" + , "-- see: https://github.com/sol/hpack" + , "" + ] + + context "with hpack version" $ do + it "includes hpack version" $ do + header "foo.yaml" (Just $ makeVersion [0,34,0]) Nothing `shouldBe` [ + "-- This file has been generated from foo.yaml by hpack version 0.34.0." + , "--" + , "-- see: https://github.com/sol/hpack" + , "" + ] + + context "with hash" $ do + it "includes hash" $ do + header "foo.yaml" Nothing (Just "some-hash") `shouldBe` [ + "-- This file has been generated from foo.yaml by hpack." + , "--" + , "-- see: https://github.com/sol/hpack" + , "--" + , "-- hash: some-hash" + , "" + ] + + describe "renderCabalFile" $ do + it "is inverse to readCabalFile" $ do + expected <- lines <$> readFile "hpack.cabal" + Just c <- readCabalFile "hpack.cabal" + renderCabalFile "package.yaml" c `shouldBe` expected + + describe "hpackResult" $ around_ inTempDirectory $ before_ (writeFile packageConfig "name: foo") $ do + let + file = "foo.cabal" + + hpackWithVersion v = hpackResultWithVersion (makeVersion v) defaultOptions + hpackWithStrategy strategy = hpackResult defaultOptions { optionsGenerateHashStrategy = strategy } + hpackForce = hpackResult defaultOptions {optionsForce = Force} + + generated = Result [] file Generated + modifiedManually = Result [] file ExistingCabalFileWasModifiedManually + outputUnchanged = Result [] file OutputUnchanged + alreadyGeneratedByNewerHpack = Result [] file AlreadyGeneratedByNewerHpack + + modifyPackageConfig = writeFile packageConfig $ unlines [ + "name: foo" + , "version: 0.1.0" + ] + + modifyCabalFile = do + xs <- readFile file + writeFile file $ xs ++ "foo\n" + + manuallyCreateCabalFile = do + writeFile file "some existing cabal file" + + doesNotGenerateHash :: HasCallStack => GenerateHashStrategy -> Spec + doesNotGenerateHash strategy = do + it "does not generate hash" $ do + hpackWithStrategy strategy `shouldReturn` generated + readFile file >>= (`shouldNotContain` "hash") + + generatesHash :: HasCallStack => GenerateHashStrategy -> Spec + generatesHash strategy = do + it "generates hash" $ do + hpackWithStrategy strategy `shouldReturn` generated + readFile file >>= (`shouldContain` "hash") + + doesNotOverwrite :: HasCallStack => GenerateHashStrategy -> Spec + doesNotOverwrite strategy = do + it "does not overwrite cabal file" $ do + existing <- readFile file + hpackWithStrategy strategy `shouldReturn` modifiedManually readFile file `shouldReturn` existing + with strategy item = context ("with " ++ show strategy) $ item strategy + + context "without an existing cabal file" $ do + with ForceHash generatesHash + with PreferHash generatesHash + with ForceNoHash doesNotGenerateHash + with PreferNoHash doesNotGenerateHash + + context "with an existing cabal file" $ do + context "without a hash" $ before_ (hpackWithStrategy ForceNoHash >> modifyPackageConfig) $ do + with ForceHash generatesHash + with PreferHash doesNotGenerateHash + with ForceNoHash doesNotGenerateHash + with PreferNoHash doesNotGenerateHash + + context "with a hash" $ before_ (hpackWithStrategy ForceHash >> modifyPackageConfig) $ do + with ForceHash generatesHash + with PreferHash generatesHash + with ForceNoHash doesNotGenerateHash + with PreferNoHash generatesHash + + context "with manual modifications" $ before_ modifyCabalFile $ do + with ForceHash doesNotOverwrite + with PreferHash doesNotOverwrite + with ForceNoHash doesNotGenerateHash + with PreferNoHash doesNotOverwrite + + context "when created manually" $ before_ manuallyCreateCabalFile $ do + with ForceHash doesNotOverwrite + with PreferHash doesNotOverwrite + with ForceNoHash doesNotOverwrite + with PreferNoHash doesNotOverwrite + context "with --force" $ do - it "overwrites existing cabal file" $ do - _ <- hpack - expected <- readFile file - writeFile file "some existing cabal file" + it "overwrites cabal file" $ do hpackForce `shouldReturn` generated - readFile file `shouldReturn` expected - context "when cabal file was created with hpack < 0.20.0" $ do - it "overwrites existing cabal file" $ do - _ <- hpack - expected <- readFile file - writeFile file "-- This file has been generated from package.yaml by hpack version 0.19.3." - hpack `shouldReturn` generated - readFile file `shouldReturn` expected - - context "when cabal file was created with hpack >= 0.20.0" $ do - context "when hash is missing" $ do - it "does not overwrite existing cabal file" $ do - let existing = "-- This file has been generated from package.yaml by hpack version 0.20.0." - writeFile file existing - hpack `shouldReturn` modifiedManually - readFile file `shouldReturn` existing - - context "when hash is present" $ do - context "when exsting cabal file was generated with a newer version of hpack" $ do - it "does not overwrite existing cabal file" $ do - writeFile packageConfig $ unlines [ - "name: foo" - , "version: 0.1.0" - ] - _ <- hpackWithVersion (makeVersion [0,22,0]) - old <- readFile file - - writeFile packageConfig $ unlines [ - "name: foo" - , "version: 0.2.0" - ] - - hpackWithVersion (makeVersion [0,20,0]) `shouldReturn` alreadyGeneratedByNewerHpack - readFile file `shouldReturn` old - - context "when cabal file was modified manually" $ do - it "does not overwrite existing cabal file" $ do - _ <- hpack - old <- readFile file - let modified = old ++ "foo\n" - writeFile file modified - _ <- hpack - readFile file `shouldReturn` modified - - context "when only the hpack version in the cabal file header changed" $ do - it "does not overwrite existing cabal file" $ do - _ <- hpackWithVersion (makeVersion [0,20,0]) - old <- readFile file - hpack `shouldReturn` outputUnchanged - readFile file `shouldReturn` old - - it "does not complain if it's newer" $ do - _ <- hpackWithVersion (makeVersion [999,999,0]) - old <- readFile file - hpack `shouldReturn` outputUnchanged - readFile file `shouldReturn` old + context "when generated with a newer version of hpack" $ do + it "does not overwrite cabal file" $ do + _ <- hpackWithVersion [0,22,0] + old <- readFile file + modifyPackageConfig + hpackWithVersion [0,20,0] `shouldReturn` alreadyGeneratedByNewerHpack + readFile file `shouldReturn` old + + context "when only the hpack version in the cabal file header changed" $ do + it "does not overwrite cabal file" $ do + _ <- hpackWithVersion [0,22,0] + old <- readFile file + hpackWithVersion [0,30,0] `shouldReturn` outputUnchanged + readFile file `shouldReturn` old + + it "does not complain if it's newer" $ do + _ <- hpackWithVersion [0,22,0] + old <- readFile file + hpackWithVersion [0,20,0] `shouldReturn` outputUnchanged + readFile file `shouldReturn` old