54ad1b4cfb
Works around this bug in unix-compat: https://github.com/jacobstanley/unix-compat/issues/56 getFileStatus and other FilePath using functions in unix-compat do not do UNC conversion on Windows. Made Utility.RawFilePath use convertToWindowsNativeNamespace to do the necessary conversion on windows to support long filenames. Audited all imports of System.PosixCompat.Files to make sure that no functions that operate on FilePath were imported from it. Instead, use the equvilants from Utility.RawFilePath. In particular the re-export of that module in Common had to be removed, which led to lots of other changes throughout the code. The changes to Build.Configure, Build.DesktopFile, and Build.TestConfig make Utility.Directory not be needed to build setup. And so let it use Utility.RawFilePath, which depends on unix, which cannot be in setup-depends. Sponsored-by: Dartmouth College's Datalad project
73 lines
2.3 KiB
Haskell
73 lines
2.3 KiB
Haskell
{- git-annex pointer files
|
|
-
|
|
- Copyright 2010-2018 Joey Hess <id@joeyh.name>
|
|
-
|
|
- Licensed under the GNU AGPL version 3 or higher.
|
|
-}
|
|
|
|
{-# LANGUAGE CPP #-}
|
|
|
|
module Annex.Content.PointerFile where
|
|
|
|
import Annex.Common
|
|
import Annex.Perms
|
|
import Annex.Link
|
|
import Annex.ReplaceFile
|
|
import Annex.InodeSentinal
|
|
import Annex.Content.LowLevel
|
|
import Utility.InodeCache
|
|
import qualified Utility.RawFilePath as R
|
|
#if ! defined(mingw32_HOST_OS)
|
|
import Utility.Touch
|
|
import qualified System.Posix.Files as Posix
|
|
#endif
|
|
|
|
import System.PosixCompat.Files (fileMode)
|
|
|
|
{- Populates a pointer file with the content of a key.
|
|
-
|
|
- If the file already has some other content, it is not modified.
|
|
-
|
|
- Returns an InodeCache if it populated the pointer file.
|
|
-}
|
|
populatePointerFile :: Restage -> Key -> RawFilePath -> RawFilePath -> Annex (Maybe InodeCache)
|
|
populatePointerFile restage k obj f = go =<< liftIO (isPointerFile f)
|
|
where
|
|
go (Just k') | k == k' = do
|
|
let f' = fromRawFilePath f
|
|
destmode <- liftIO $ catchMaybeIO $ fileMode <$> R.getFileStatus f
|
|
liftIO $ removeWhenExistsWith R.removeLink f
|
|
(ic, populated) <- replaceWorkTreeFile f' $ \tmp -> do
|
|
let tmp' = toRawFilePath tmp
|
|
ok <- linkOrCopy k obj tmp' destmode >>= \case
|
|
Just _ -> thawContent tmp' >> return True
|
|
Nothing -> liftIO (writePointerFile tmp' k destmode) >> return False
|
|
ic <- withTSDelta (liftIO . genInodeCache tmp')
|
|
return (ic, ok)
|
|
maybe noop (restagePointerFile restage f) ic
|
|
if populated
|
|
then return ic
|
|
else return Nothing
|
|
go _ = return Nothing
|
|
|
|
{- Removes the content from a pointer file, replacing it with a pointer.
|
|
-
|
|
- Does not check if the pointer file is modified. -}
|
|
depopulatePointerFile :: Key -> RawFilePath -> Annex ()
|
|
depopulatePointerFile key file = do
|
|
st <- liftIO $ catchMaybeIO $ R.getFileStatus file
|
|
let mode = fmap fileMode st
|
|
secureErase file
|
|
liftIO $ removeWhenExistsWith R.removeLink file
|
|
ic <- replaceWorkTreeFile (fromRawFilePath file) $ \tmp -> do
|
|
let tmp' = toRawFilePath tmp
|
|
liftIO $ writePointerFile tmp' key mode
|
|
#if ! defined(mingw32_HOST_OS)
|
|
-- Don't advance mtime; this avoids unnecessary re-smudging
|
|
-- by git in some cases.
|
|
liftIO $ maybe noop
|
|
(\t -> touch tmp' t False)
|
|
(fmap Posix.modificationTimeHiRes st)
|
|
#endif
|
|
withTSDelta (liftIO . genInodeCache tmp')
|
|
maybe noop (restagePointerFile (Restage True) file) ic
|