@@ -19,6 +19,8 @@ import Distribution.PackageDescription
1919import qualified Distribution.PackageDescription as Cabal
2020import Distribution.Text ( simpleParse, display )
2121import OpenSSL.Digest ( digest, digestByName )
22+import qualified Hpack.Run as Hpack
23+import qualified Hpack.Config as Hpack
2224import System.Directory ( doesDirectoryExist, doesFileExist, createDirectoryIfMissing, getHomeDirectory, getDirectoryContents )
2325import System.Exit ( exitFailure )
2426import System.FilePath ( (</>), (<.>) )
@@ -134,12 +136,28 @@ cabalFromDirectory :: FilePath -> MaybeT IO Cabal.GenericPackageDescription
134136cabalFromDirectory dir = do
135137 cabals <- liftIO $ getDirectoryContents dir >>= filterM doesFileExist . map (dir </>) . filter (".cabal" `isSuffixOf`)
136138 case cabals of
139+ [] -> do
140+ liftIO $ hPutStrLn stderr "*** found zero cabal files. Trying hpack..."
141+ hpackFromDirectory dir
137142 [cabalFile] -> cabalFromFile True cabalFile
138− _ -> liftIO $ hPutStrLn stderr ("*** found zero or more than one cabal file (" ++ show cabals ++ "). Exiting.") >> exitFailure
143+ _ -> liftIO $ hPutStrLn stderr ("*** found more than one cabal file (" ++ show cabals ++ "). Exiting.") >> exitFailure
139144
140145handleIO :: (Exception.IOException -> IO a) -> IO a -> IO a
141146handleIO = Exception.handle
142147
148+hpackFromDirectory :: FilePath -> MaybeT IO Cabal.GenericPackageDescription
149+hpackFromDirectory dir = do
150+ mPackage <- liftIO $ Hpack.readPackageConfig $ dir </> "package.yaml"
151+ case mPackage of
152+ Left err -> liftIO $ hPutStrLn stderr ("*** hpack error: " ++ show err ++ ". Exiting.") >> exitFailure
153+ Right (_, pkg) -> do
154+ let buf = LBS8.pack $ Hpack.renderPackage Hpack.defaultRenderSettings 0 [] [] pkg
155+ hash = printSHA256 (digest (digestByName "sha256") buf)
156+ case parsePackage' buf of
157+ Left msg -> liftIO $ hPutStrLn stderr ("*** cannot parse hpack output: " ++ msg) >> exitFailure
158+ Right pkg -> MaybeT $ return $ Just $ pkg { packageDescription = (packageDescription pkg) {
159+ customFieldsPD = ("X-Cabal-File-Hash", hash) : customFieldsPD (packageDescription pkg) } }
160+
143161cabalFromFile :: Bool -> FilePath -> MaybeT IO Cabal.GenericPackageDescription
144162cabalFromFile failHard file =
145163 -- readFile throws an error if it's used on binary files which contain sequences