2018-08-22 18:41:09 +00:00
|
|
|
{- git-annex pointer files
|
|
|
|
-
|
|
|
|
- Copyright 2010-2018 Joey Hess <id@joeyh.name>
|
|
|
|
-
|
2019-03-13 19:48:14 +00:00
|
|
|
- Licensed under the GNU AGPL version 3 or higher.
|
2018-08-22 18:41:09 +00:00
|
|
|
-}
|
|
|
|
|
|
|
|
{-# 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
|
2019-10-08 18:01:12 +00:00
|
|
|
import Utility.InodeCache
|
2020-11-24 16:38:12 +00:00
|
|
|
import qualified Utility.RawFilePath as R
|
2020-01-01 18:40:00 +00:00
|
|
|
#if ! defined(mingw32_HOST_OS)
|
2019-10-08 18:01:12 +00:00
|
|
|
import Utility.Touch
|
2021-10-18 20:25:28 +00:00
|
|
|
import qualified System.Posix.Files as Posix
|
2020-01-01 18:40:00 +00:00
|
|
|
#endif
|
2018-08-22 18:41:09 +00:00
|
|
|
|
2023-03-01 19:55:58 +00:00
|
|
|
import System.PosixCompat.Files (fileMode)
|
|
|
|
|
2018-08-22 19:22:52 +00:00
|
|
|
{- 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.
|
|
|
|
-}
|
2019-11-26 19:27:22 +00:00
|
|
|
populatePointerFile :: Restage -> Key -> RawFilePath -> RawFilePath -> Annex (Maybe InodeCache)
|
2018-08-22 18:41:09 +00:00
|
|
|
populatePointerFile restage k obj f = go =<< liftIO (isPointerFile f)
|
|
|
|
where
|
|
|
|
go (Just k') | k == k' = do
|
2019-11-26 19:27:22 +00:00
|
|
|
let f' = fromRawFilePath f
|
2020-10-29 14:33:12 +00:00
|
|
|
destmode <- liftIO $ catchMaybeIO $ fileMode <$> R.getFileStatus f
|
|
|
|
liftIO $ removeWhenExistsWith R.removeLink f
|
2020-03-06 15:31:01 +00:00
|
|
|
(ic, populated) <- replaceWorkTreeFile f' $ \tmp -> do
|
2023-10-26 17:36:49 +00:00
|
|
|
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)
|
2018-08-22 19:22:52 +00:00
|
|
|
return (ic, ok)
|
2018-08-22 18:41:09 +00:00
|
|
|
maybe noop (restagePointerFile restage f) ic
|
2018-08-22 19:22:52 +00:00
|
|
|
if populated
|
|
|
|
then return ic
|
|
|
|
else return Nothing
|
|
|
|
go _ = return Nothing
|
2018-08-22 18:41:09 +00:00
|
|
|
|
|
|
|
{- Removes the content from a pointer file, replacing it with a pointer.
|
|
|
|
-
|
|
|
|
- Does not check if the pointer file is modified. -}
|
2019-11-26 19:27:22 +00:00
|
|
|
depopulatePointerFile :: Key -> RawFilePath -> Annex ()
|
2018-08-22 18:41:09 +00:00
|
|
|
depopulatePointerFile key file = do
|
2023-03-01 19:55:58 +00:00
|
|
|
st <- liftIO $ catchMaybeIO $ R.getFileStatus file
|
2019-10-08 18:01:12 +00:00
|
|
|
let mode = fmap fileMode st
|
2020-10-29 18:20:57 +00:00
|
|
|
secureErase file
|
2020-10-29 14:33:12 +00:00
|
|
|
liftIO $ removeWhenExistsWith R.removeLink file
|
2023-03-01 19:55:58 +00:00
|
|
|
ic <- replaceWorkTreeFile (fromRawFilePath file) $ \tmp -> do
|
2023-10-26 17:36:49 +00:00
|
|
|
liftIO $ writePointerFile tmp key mode
|
2019-10-08 18:01:12 +00:00
|
|
|
#if ! defined(mingw32_HOST_OS)
|
2022-08-19 21:45:04 +00:00
|
|
|
-- Don't advance mtime; this avoids unnecessary re-smudging
|
2019-10-08 18:01:12 +00:00
|
|
|
-- by git in some cases.
|
|
|
|
liftIO $ maybe noop
|
2023-10-26 17:36:49 +00:00
|
|
|
(\t -> touch tmp t False)
|
2021-10-18 20:25:28 +00:00
|
|
|
(fmap Posix.modificationTimeHiRes st)
|
2019-10-08 18:01:12 +00:00
|
|
|
#endif
|
2023-10-26 17:36:49 +00:00
|
|
|
withTSDelta (liftIO . genInodeCache tmp)
|
2018-08-22 18:41:09 +00:00
|
|
|
maybe noop (restagePointerFile (Restage True) file) ic
|