{-# OPTIONS_GHC -fno-warn-orphans #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE StandaloneDeriving #-} module Language.ATS.Package.Debian ( debRules , Debian (..) ) where import qualified Codec.Compression.GZip as Gzip import qualified Data.ByteString.Lazy as BSL import Data.Dependency (Version (..)) import Data.List (intercalate) import Development.Shake hiding ((*>)) import Development.Shake.FilePath import Dhall hiding (Text) import Quaalude import System.PosixCompat.Files (setFileMode) data Debian = Debian { package :: Text , version :: Version , maintainer :: Text , description :: Text , target :: Text , manpage :: Maybe Text , binaries :: [Text] , libraries :: [Text] , headers :: [Text] , license :: Maybe Text , changelog :: Maybe Text } -- TODO: section https://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections -- TODO: priority https://www.debian.org/doc/debian-policy/ch-archive.html#s-priorities deriving (Generic, Binary, FromDhall) deriving newtype instance FromDhall Version control :: Debian -> String control Debian{..} = intercalate "\n" [ "Package: " ++ unpack package , "Version: " ++ show version , "Architecture: all" , "Maintainer: " ++ unpack maintainer , "Description: " ++ unpack description , mempty ] debianCompress :: BSL.ByteString -> BSL.ByteString debianCompress = Gzip.compressWith Gzip.defaultCompressParams { Gzip.compressLevel = Gzip.bestCompression } gzipRules :: Rules () gzipRules = "//*.gz" %> \out -> do let orig = fromMaybe out $ stripExtension "gz" out need [orig] contents <- liftIO $ BSL.readFile orig let zipped = debianCompress contents liftIO $ BSL.writeFile out zipped -- look at hackage package for debian? debRules :: Debian -> Rules () debRules deb = do gzipRules -- TODO: right place? unpack (target deb) %> \out -> do let binPerms = 0o755 manPerms = 0o0644 let binaries' = unpack <$> binaries deb libraries' = unpack <$> libraries deb headers' = unpack <$> headers deb traverse_ need [ binaries' , libraries' , headers' ] let packDir = unpack (package deb) makeRel = (("target" packDir) ) debianDir = makeRel "DEBIAN" binDir = makeRel "usr/bin" libDir = makeRel "usr/lib" manDir = makeRel "usr/share/man/man1" includeDir = makeRel "usr/include" docDir = makeRel ("usr/share/doc" packDir) traverse_ (\fp -> liftIO $ setFileMode fp binPerms) binaries' let dirs = [ binDir, debianDir, manDir, includeDir, docDir ] traverse_ (liftIO . createDirectoryIfMissing True) dirs let parents = [ "usr", "usr/share/man", "usr/share", "usr/share/doc" ] traverse_ (\fp -> liftIO $ setFileMode fp binPerms) ((makeRel <$> parents) ++ dirs) fold $ do mp <- manpage deb pure $ do let mp' = unpack mp <.> "gz" need [mp'] liftIO (setFileMode mp' manPerms) copyFile' mp' (manDir ++ "/" ++ takeFileName mp') let moveFiles files dir = zipWithM_ copyFile' files ((dir ) . takeFileName <$> files) moveFiles binaries' binDir moveFiles libraries' libDir moveFiles headers' includeDir writeFileChanged (debianDir ++ "/control") (control deb) command [Cwd "target"] "dpkg-deb" ["--build", packDir, dropDirectory1 out]