module Codec.Archive.Pack.Common ( mkEntry ) where

import           Codec.Archive.Types
import qualified Data.ByteString          as BS
import           System.PosixCompat.Files (FileStatus, fileGroup, fileMode, fileOwner, getFileStatus, isDirectory, isRegularFile, isSymbolicLink, linkCount,
                                           readSymbolicLink)

mkContent :: FilePath -> FileStatus -> IO EntryContent
mkContent :: FilePath -> FileStatus -> IO EntryContent
mkContent FilePath
fp FileStatus
status =
    let res :: (Bool, Bool, Bool, LinkCount)
res = (FileStatus -> Bool
isRegularFile FileStatus
status, FileStatus -> Bool
isDirectory FileStatus
status, FileStatus -> Bool
isSymbolicLink FileStatus
status, FileStatus -> LinkCount
linkCount FileStatus
status)
    in

    case (Bool, Bool, Bool, LinkCount)
res of
        (Bool
True, Bool
False, Bool
False, LinkCount
1) -> ByteString -> EntryContent
NormalFile (ByteString -> EntryContent) -> IO ByteString -> IO EntryContent
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO ByteString
BS.readFile FilePath
fp
        (Bool
True, Bool
False, Bool
False, LinkCount
_) -> EntryContent -> IO EntryContent
forall (f :: * -> *) a. Applicative f => a -> f a
pure (EntryContent -> IO EntryContent)
-> EntryContent -> IO EntryContent
forall a b. (a -> b) -> a -> b
$ FilePath -> EntryContent
Hardlink FilePath
fp
        (Bool
False, Bool
True, Bool
False, LinkCount
_) -> EntryContent -> IO EntryContent
forall (f :: * -> *) a. Applicative f => a -> f a
pure EntryContent
Directory
        (Bool
False, Bool
False, Bool
True, LinkCount
_) -> FilePath -> Symlink -> EntryContent
Symlink (FilePath -> Symlink -> EntryContent)
-> IO FilePath -> IO (Symlink -> EntryContent)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO FilePath
readSymbolicLink FilePath
fp IO (Symlink -> EntryContent) -> IO Symlink -> IO EntryContent
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Symlink -> IO Symlink
forall (f :: * -> *) a. Applicative f => a -> f a
pure Symlink
SymlinkUndefined
        (Bool
_, Bool
_, Bool
_, LinkCount
_)            -> FilePath -> IO EntryContent
forall a. HasCallStack => FilePath -> a
error FilePath
"inconsistent read result"

mkEntry :: FilePath -> IO Entry
mkEntry :: FilePath -> IO Entry
mkEntry FilePath
fp = do
    FileStatus
status <- FilePath -> IO FileStatus
getFileStatus FilePath
fp
    EntryContent
content' <- FilePath -> FileStatus -> IO EntryContent
mkContent FilePath
fp FileStatus
status
    Entry -> IO Entry
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Entry -> IO Entry) -> Entry -> IO Entry
forall a b. (a -> b) -> a -> b
$ FilePath
-> EntryContent
-> Permissions
-> Ownership
-> Maybe ModTime
-> Entry
Entry FilePath
fp EntryContent
content' (FileStatus -> Permissions
fileMode FileStatus
status) (Maybe FilePath -> Maybe FilePath -> Id -> Id -> Ownership
Ownership Maybe FilePath
forall a. Maybe a
Nothing Maybe FilePath
forall a. Maybe a
Nothing (UserID -> Id
forall a b. (Integral a, Num b) => a -> b
fromIntegral (UserID -> Id) -> UserID -> Id
forall a b. (a -> b) -> a -> b
$ FileStatus -> UserID
fileOwner FileStatus
status) (GroupID -> Id
forall a b. (Integral a, Num b) => a -> b
fromIntegral (GroupID -> Id) -> GroupID -> Id
forall a b. (a -> b) -> a -> b
$ FileStatus -> GroupID
fileGroup FileStatus
status)) Maybe ModTime
forall a. Maybe a
Nothing