self-extract 0.1.0.0 → 0.2.0.0
raw patch · 6 files changed
+109/−54 lines, 6 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG.md +11/−0
- README.md +2/−34
- self-extract.cabal +1/−1
- src/Codec/SelfExtract.hs +26/−2
- src/Codec/SelfExtract/Distribution.hs +57/−14
- src/Codec/SelfExtract/Tar.hs +12/−3
CHANGELOG.md view
@@ -1,3 +1,14 @@+## self-extract 0.2.0.0++Fixed bug due to stripping the exes after bundling, which is only a problem when bundling multiple+executables in a package.++Major fixes:+* Packages should use `bundle` in the `postCopy` hook, rather than the `postBuild` hook.++Other fixes:+* Updated documentation+ ## self-extract 0.1.0.0 * Initial implementation
README.md view
@@ -23,37 +23,19 @@ ### Setup.hs -Basic:- ``` import Codec.SelfExtract.Distribution (bundle) import Distribution.Simple main = defaultMainWithHooks simpleUserHooks- { postBuild = \args bf pd lbi -> do- postBuild simpleUserHooks args bf pd lbi+ { postCopy = \args cf pd lbi -> do+ postCopy simpleUserHooks args cf pd lbi bundle "name-of-executable" "dir-to-bundle" lbi } ``` -Using the [Path](https://hackage.haskell.org/package/path-0.6.1) library:--```-import Codec.SelfExtract.Distribution (bundle')-import Distribution.Simple-import Path (reldir)--main = defaultMainWithHooks simpleUserHooks- { postBuild = \args bf pd lbi -> do- postBuild simpleUserHooks args bf pd lbi- bundle' "name-of-executable" [reldir|dir-to-bundle|] lbi- }-```- ### Executable file -Basic:- ``` import Codec.SelfExtract (extractTo) @@ -71,20 +53,6 @@ main = do withExtractToTemp $ \tmp -> do- ...-```--Using the [Path](https://hackage.haskell.org/package/path-0.6.1) library:--```-import Codec.SelfExtract (extractTo', withExtractToTemp')-import Path (absdir, reldir)-import Path.IO (removeDir)--main = do- extractTo' $ [reldir|dir|] -- will extract to $CWD/dir- extractTo' $ [absdir|/usr/local/lib|]- withExtractToTemp' $ \tmp -> do ... ```
self-extract.cabal view
@@ -1,5 +1,5 @@ name: self-extract-version: 0.1.0.0+version: 0.2.0.0 license: BSD3 license-file: LICENSE.md author: Brandon Chinn <brandon@leapyear.io>
src/Codec/SelfExtract.hs view
@@ -1,3 +1,12 @@+{-|+Module : Codec.SelfExtract+Maintainer : Brandon Chinn <brandon@leapyear.io>+Stability : experimental+Portability : portable++Defines functions that should be used in a self-extractable executable.+-}+ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-} @@ -21,14 +30,29 @@ import Codec.SelfExtract.Tar (untar) -- | Extract the self-bundled executable to the given path.+--+-- @+-- extractTo "dir" -- will extract to $CWD/dir+-- extractTo "\/usr\/local\/lib"+-- @ extractTo :: FilePath -> IO () extractTo = resolveDir' >=> extractTo' -- | Extract the self-bundled executable to a temporary path.+--+-- @+-- withExtractToTemp $ \tmp -> do+-- ...+-- @ withExtractToTemp :: (FilePath -> IO ()) -> IO () withExtractToTemp action = withExtractToTemp' (action . fromAbsDir) --- | Extract the self-bundled executable to the given path.+-- | Same as 'extractTo', except using the 'Path' library.+--+-- @+-- extractTo' [reldir|dir|] -- will extract to $CWD/dir+-- extractTo' [absdir|\/usr\/local\/lib|]+-- @ extractTo' :: Path b Dir -> IO () extractTo' dir = do self <- getExecutablePath >>= parseAbsFile@@ -40,7 +64,7 @@ hClose hTemp untar archive dir --- | Extract the self-bundled executable to a temporary path.+-- | Same as 'withExtractToTemp', except using the 'Path' library. withExtractToTemp' :: (Path Abs Dir -> IO ()) -> IO () withExtractToTemp' action = withSystemTempDir "" $ \dir -> extractTo' dir >> action dir
src/Codec/SelfExtract/Distribution.hs view
@@ -1,3 +1,12 @@+{-|+Module : Codec.SelfExtract.Distribution+Maintainer : Brandon Chinn <brandon@leapyear.io>+Stability : experimental+Portability : portable++Defines functions that should be used in the @Setup.hs@ file.+-}+ {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-}@@ -12,31 +21,53 @@ import Data.ByteString as BS import Data.ByteString.Lazy as LBS import Data.FileEmbed (injectFileWith)-import Distribution.Simple.LocalBuildInfo (LocalBuildInfo(..))-import Path (Dir, File, Path, fromAbsFile, parseRelDir, parseRelFile, relfile, toFilePath, (</>))+import Distribution.Simple.LocalBuildInfo (InstallDirs(..), LocalBuildInfo(..), fromPathTemplate)+import Distribution.Simple.Setup (ConfigFlags(..), fromFlag)+import Path+ ( Abs+ , Dir+ , File+ , Path+ , fromAbsFile+ , parseAbsDir+ , parseRelFile+ , relfile+ , toFilePath+ , (</>)+ ) import Path.IO (doesFileExist, renameFile, resolveDir', withSystemTempDir)-import System.PosixCompat.Files (fileSize, getFileStatus)+import qualified System.PosixCompat.Files as Posix import Codec.SelfExtract.Tar (tar) -- | Bundle the given directory into the executable with the given name. ----- To be used as part of the Setup.hs file.+-- For example, to bundle the @static/@ directory in the executable named @install-files@:+--+-- @+-- main = defaultMainWithHooks simpleUserHooks+-- { postCopy = \args cf pd lbi -> do+-- postCopy simpleUserHooks args cf pd lbi+-- bundle "install-files" ".\/static\/" lbi+-- }+-- @ bundle :: String -> FilePath -> LocalBuildInfo -> IO () bundle exe dir lbi = do dir' <- resolveDir' dir bundle' exe dir' lbi --- | Bundle the given directory into the executable with the given name.+-- | Same as 'bundle', except using the 'Path' library. ----- To be used as part of the Setup.hs file.+-- @+-- main = defaultMainWithHooks simpleUserHooks+-- { postCopy = \args cf pd lbi -> do+-- postCopy simpleUserHooks args cf pd lbi+-- bundle' "install-files" [reldir|.\/static\/|] lbi+-- }+-- @ bundle' :: String -> Path b Dir -> LocalBuildInfo -> IO ()-bundle' exeName dir LocalBuildInfo{buildDir} = do- exeDir <- resolveDir' buildDir- exeNameDir <- parseRelDir exeName- exeNameFile <- parseRelFile exeName-- let exe = exeDir </> exeNameDir </> exeNameFile+bundle' exeName dir lbi = do+ exe <- getExe lbi exeName unlessM (doesFileExist exe) $ error $ "Executable does not exist: " ++ exeName size <- getFileSize exe@@ -56,11 +87,23 @@ renameFile combined exe + Posix.setFileMode (fromAbsFile exe) executeMode+ where+ -- 755 permissions+ executeMode = Posix.unionFileModes Posix.stdFileMode Posix.ownerExecuteMode++-- | Get the executable to be made self-extracting.+getExe :: LocalBuildInfo -> String -> IO (Path Abs File)+getExe LocalBuildInfo{configFlags} exeName = do+ binDir <- parseAbsDir $ fromPathTemplate $ fromFlag $ bindir $ configInstallDirs configFlags+ exe <- parseRelFile exeName+ return $ binDir </> exe+ -- | Get the size of the given file. getFileSize :: Path b File -> IO Word32-getFileSize = fmap getSize . getFileStatus . toFilePath+getFileSize = fmap getSize . Posix.getFileStatus . toFilePath where- getSize = fromIntegral . fileSize+ getSize = fromIntegral . Posix.fileSize -- | Concatenate the given files and write to the given file. cat :: [Path b File] -> Path b File -> IO ()
src/Codec/SelfExtract/Tar.hs view
@@ -1,3 +1,15 @@+{-|+Module : Codec.SelfExtract.Tar+Maintainer : Brandon Chinn <brandon@leapyear.io>+Stability : experimental+Portability : portable++Defines utilities for creating/extracting TAR archives.++These functions shell out to the 'tar' process because Haskell packages that implement Tar would+need some C header files, which we don't want to require on the user end.+-}+ module Codec.SelfExtract.Tar ( tar , untar@@ -8,9 +20,6 @@ import System.Process (callProcess) -- | Zip the given directory into the given archive.------ Shelling out to `tar` because Haskell Tar packages would need the C header files, which we don't--- require on the client end. tar :: Path b0 Dir -> Path b1 File -> IO () tar src archive = callProcess "tar" ["-czf", toFilePath archive, "-C", toFilePath src, "."]