Skip to content

Commit

Permalink
Preserve file permissions when unpacking sources
Browse files Browse the repository at this point in the history
The `tar` package, in name of portability, doesn't preserve file
permissions when creating and unpacking archives. A sample package which
relies on permissions to be kept as they were packed with is
`ghc-parser` which executes a bash script as part of its build process.

Before this patch we'd get

```
    /run/user/1000/stack26234/ghc-parser-0.1.7.0/Setup.hs:2:1: Warning:
        Module ‘System.Cmd’ is deprecated: Use "System.Process" instead
    /bin/sh: ./build-parser.sh: Permission denied
    Configuring ghc-parser-0.1.7.0...
    Warning: 'hs-source-dirs: src-7.8.3' directory does not exist.
```

but now the package builds fine.
  • Loading branch information
Fuuzetsu committed Jul 23, 2015
1 parent 2af3d1b commit ca99db4
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 1 deletion.
14 changes: 13 additions & 1 deletion src/Stack/Fetch.hs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ module Stack.Fetch

import qualified Codec.Archive.Tar as Tar
import qualified Codec.Archive.Tar.Check as Tar
import qualified Codec.Archive.Tar.Entry as Tar
import Codec.Compression.GZip (decompress)
import Control.Applicative
import Control.Concurrent.Async (Concurrently (..))
Expand Down Expand Up @@ -52,7 +53,7 @@ import Data.IORef (newIORef, readIORef,
import Data.List (intercalate, intersperse)
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Maybe (maybeToList)
import Data.Maybe (maybeToList, catMaybes)
import Data.Monoid ((<>))
import Data.Set (Set)
import qualified Data.Set as Set
Expand All @@ -76,6 +77,7 @@ import qualified System.FilePath as FP
import System.IO (IOMode (ReadMode),
SeekMode (AbsoluteSeek), hSeek,
withBinaryFile)
import System.PosixCompat (setFileMode)

data FetchException
= Couldn'tReadIndexTarball FilePath Tar.FormatError
Expand Down Expand Up @@ -456,7 +458,17 @@ fetchPackages' mdistDir toFetchAll = do
wrap :: Exception e => e -> FetchException
wrap = Couldn'tReadPackageTarball fp . toException
identStr = packageIdentifierString ident

getPerms :: Tar.Entry -> (FilePath, Tar.Permissions)
getPerms e = (dest FP.</> Tar.fromTarPath (Tar.entryTarPath e),
Tar.entryPermissions e)

filePerms :: [(FilePath, Tar.Permissions)]
filePerms = catMaybes $ Tar.foldEntries (\e -> (:) (Just $ getPerms e))
[] (const []) entries
Tar.unpack dest entries
-- Reset file permissions as they were in the tarball
mapM_ (\(fp', perm) -> setFileMode fp' perm) filePerms

case mdistDir of
Nothing -> return ()
Expand Down
1 change: 1 addition & 0 deletions stack.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ library
, time >= 1.4.2
, transformers >= 0.3.0.0
, transformers-base >= 0.4.4
, unix-compat
, unordered-containers >= 0.2.5.1
, vector >= 0.10.12.3
, vector-binary-instances
Expand Down

0 comments on commit ca99db4

Please sign in to comment.