{-# LANGUAGE CPP #-} module Development.Shake.Internal.History.Symlink( copyFileLink ) where import Control.Monad.Extra import General.Extra import System.Directory import System.FilePath #ifdef mingw32_HOST_OS import Foreign.Ptr import Foreign.C.String #else import System.Posix.Files(createLink) #endif createLinkBool :: FilePath -> FilePath -> IO (Maybe String) #ifdef mingw32_HOST_OS #ifdef x86_64_HOST_ARCH #define CALLCONV ccall #else #define CALLCONV stdcall #endif foreign import CALLCONV unsafe "Windows.h CreateHardLinkW " c_CreateHardLinkW :: CWString -> CWString -> Ptr () -> IO Bool createLinkBool from to = withCWString from $ \cfrom -> withCWString to $ \cto -> do res <- c_CreateHardLinkW cto cfrom nullPtr return $ if res then Nothing else Just "CreateHardLink failed." #else createLinkBool from to = handleIO (return . Just . show) $ createLink from to >> return Nothing #endif copyFileLink :: FilePath -> FilePath -> IO () copyFileLink from to = do createDirectoryRecursive $ takeDirectory to removeFile_ to b <- createLinkBool from to whenJust b $ \_ -> copyFile from to -- making files read only stops them from inadvertantly mutating the cache forM_ [from, to] $ \x -> do perm <- getPermissions x setPermissions x perm{writable=False}