@@ -11,18 +11,21 @@ module Stack.SDist
1111 ( getSDistTarball
1212 , checkSDistTarball
1313 , checkSDistTarball'
14+ , SDistOpts (.. )
1415 ) where
1516
1617import qualified Codec.Archive.Tar as Tar
1718import qualified Codec.Archive.Tar.Entry as Tar
1819import qualified Codec.Compression.GZip as GZip
1920import Control.Applicative
2021import Control.Concurrent.Execute (ActionContext (.. ))
21- import Control.Monad (unless , void , liftM )
22+ import Control.Monad (unless , void , liftM , filterM , foldM , when )
2223import Control.Monad.Catch
2324import Control.Monad.IO.Class
2425import Control.Monad.Logger
26+ import Control.Monad.Reader.Class (local )
2527import Control.Monad.Trans.Control (liftBaseWith )
28+ import Control.Monad.Trans.Unlift (MonadBaseUnlift )
2629import qualified Data.ByteString as S
2730import qualified Data.ByteString.Char8 as S8
2831import qualified Data.ByteString.Lazy as L
@@ -35,7 +38,7 @@ import Data.List.Extra (nubOrd)
3538import Data.List.NonEmpty (NonEmpty )
3639import qualified Data.List.NonEmpty as NE
3740import qualified Data.Map.Strict as Map
38- import Data.Maybe (fromMaybe )
41+ import Data.Maybe (fromMaybe , catMaybes )
3942import Data.Monoid ((<>) )
4043import qualified Data.Set as Set
4144import qualified Data.Text as T
@@ -50,14 +53,16 @@ import Distribution.PackageDescription.PrettyPrint (showGenericPackage
5053import Distribution.Text (display )
5154import Distribution.Version (simplifyVersionRange , orLaterVersion , earlierVersion )
5255import Distribution.Version.Extra
56+ import Lens.Micro (set )
5357import Path
5458import Path.IO hiding (getModificationTime , getPermissions )
5559import Prelude -- Fix redundant import warnings
56- import Stack.Build (mkBaseConfigOpts )
60+ import Stack.Build (mkBaseConfigOpts , build )
5761import Stack.Build.Execute
5862import Stack.Build.Installed
5963import Stack.Build.Source (loadSourceMap , getDefaultPackageConfig )
6064import Stack.Build.Target
65+ import Stack.Config (resolvePackageEntry , removePathFromPackageEntry )
6166import Stack.Constants
6267import Stack.Package
6368import Stack.Types.Build
@@ -74,6 +79,21 @@ import qualified System.FilePath as FP
7479-- | Special exception to throw when you want to fail because of bad results
7580-- of package check.
7681
82+ data SDistOpts = SDistOpts
83+ { sdoptsDirsToWorkWith :: [String ]
84+ -- ^ Directories to package
85+ , sdoptsPvpBounds :: Maybe PvpBounds
86+ -- ^ PVP Bounds overrides
87+ , sdoptsIgnoreCheck :: Bool
88+ -- ^ Whether to ignore check of the package for common errors
89+ , sdoptsSign :: Bool
90+ -- ^ Whether to sign the package
91+ , sdoptsSignServerUrl :: String
92+ -- ^ The URL of the signature server
93+ , sdoptsBuildTarball :: Bool
94+ -- ^ Whether to build the tarball
95+ }
96+
7797newtype CheckException
7898 = CheckException (NonEmpty Check. PackageCheck )
7999 deriving (Typeable )
@@ -317,13 +337,21 @@ dirsFromFiles dirs = Set.toAscList (Set.delete "." results)
317337-- and will throw an exception in case of critical errors.
318338--
319339-- Note that we temporarily decompress the archive to analyze it.
320- checkSDistTarball :: (StackM env m , HasEnvConfig env )
321- => Path Abs File -- ^ Absolute path to tarball
340+ checkSDistTarball :: (StackM env m , HasEnvConfig env , MonadBaseUnlift IO m )
341+ => SDistOpts -- ^ The configuration of what to check
342+ -> Path Abs File -- ^ Absolute path to tarball
322343 -> m ()
323- checkSDistTarball tarball = withTempTarGzContents tarball $ \ pkgDir' -> do
344+ checkSDistTarball opts tarball = withTempTarGzContents tarball $ \ pkgDir' -> do
324345 pkgDir <- (pkgDir' </> ) `liftM`
325346 (parseRelDir . FP. takeBaseName . FP. takeBaseName . toFilePath $ tarball)
326347 -- ^ drop ".tar" ^ drop ".gz"
348+ when (sdoptsBuildTarball opts) (buildExtractedTarball pkgDir)
349+ unless (sdoptsIgnoreCheck opts) (checkPackageInExtractedTarball pkgDir)
350+
351+ checkPackageInExtractedTarball :: (StackM env m , HasEnvConfig env , MonadBaseUnlift IO m )
352+ => Path Abs Dir -- ^ Absolute path to tarball
353+ -> m ()
354+ checkPackageInExtractedTarball pkgDir = do
327355 cabalfp <- findOrGenerateCabalFile pkgDir
328356 name <- parsePackageNameFromFilePath cabalfp
329357 config <- getDefaultPackageConfig
@@ -345,16 +373,56 @@ checkSDistTarball tarball = withTempTarGzContents tarball $ \pkgDir' -> do
345373 Nothing -> return ()
346374 Just ne -> throwM $ CheckException ne
347375
376+ buildExtractedTarball :: (StackM env m , HasEnvConfig env , MonadBaseUnlift IO m ) => Path Abs Dir -> m ()
377+ buildExtractedTarball pkgDir = do
378+ projectRoot <- view projectRootL
379+ envConfig <- view envConfigL
380+ menv <- getMinimalEnvOverride
381+ localPackageToBuild <- readLocalPackage pkgDir
382+ let packageEntries = bcPackageEntries (envConfigBuildConfig envConfig)
383+ getPaths entry = do
384+ resolvedEntry <- resolvePackageEntry menv projectRoot entry
385+ return $ fmap fst resolvedEntry
386+ allPackagePaths <- fmap mconcat (mapM getPaths packageEntries)
387+ -- We remove the path based on the name of the package
388+ let isPathToRemove path = do
389+ localPackage <- readLocalPackage path
390+ return $ packageName (lpPackage localPackage) == packageName (lpPackage localPackageToBuild)
391+ pathsToRemove <- filterM isPathToRemove allPackagePaths
392+ let adjustPackageEntries entries path = do
393+ adjustedPackageEntries <- mapM (removePathFromPackageEntry menv projectRoot path) entries
394+ return (catMaybes adjustedPackageEntries)
395+ entriesWithoutBuiltPackage <- foldM adjustPackageEntries packageEntries pathsToRemove
396+ let newEntry = PackageEntry Nothing (PLFilePath (toFilePath pkgDir)) []
397+ newPackagesRef <- liftIO (newIORef Nothing )
398+ let adjustEnvForBuild env =
399+ let updatedEnvConfig = envConfig
400+ {envConfigPackagesRef = newPackagesRef
401+ ,envConfigBuildConfig = updatePackageInBuildConfig (envConfigBuildConfig envConfig)
402+ }
403+ in set envConfigL updatedEnvConfig env
404+ updatePackageInBuildConfig buildConfig = buildConfig
405+ { bcPackageEntries = newEntry : entriesWithoutBuiltPackage
406+ , bcConfig = (bcConfig buildConfig)
407+ { configBuild = defaultBuildOpts
408+ { boptsTests = True
409+ }
410+ }
411+ }
412+ local adjustEnvForBuild $
413+ build (const (return () )) Nothing defaultBuildOptsCLI
414+
348415-- | Version of 'checkSDistTarball' that first saves lazy bytestring to
349416-- temporary directory and then calls 'checkSDistTarball' on it.
350- checkSDistTarball' :: (StackM env m , HasEnvConfig env )
351- => String -- ^ Tarball name
417+ checkSDistTarball' :: (StackM env m , HasEnvConfig env , MonadBaseUnlift IO m )
418+ => SDistOpts
419+ -> String -- ^ Tarball name
352420 -> L. ByteString -- ^ Tarball contents as a byte string
353421 -> m ()
354- checkSDistTarball' name bytes = withSystemTempDir " stack" $ \ tpath -> do
422+ checkSDistTarball' opts name bytes = withSystemTempDir " stack" $ \ tpath -> do
355423 npath <- (tpath </> ) `liftM` parseRelFile name
356424 liftIO $ L. writeFile (toFilePath npath) bytes
357- checkSDistTarball npath
425+ checkSDistTarball opts npath
358426
359427withTempTarGzContents :: (MonadIO m , MonadMask m )
360428 => Path Abs File -- ^ Location of tarball
0 commit comments