diff --git a/Annex/Content.hs b/Annex/Content.hs index 502e9fa274..5d657cac2a 100644 --- a/Annex/Content.hs +++ b/Annex/Content.hs @@ -583,17 +583,15 @@ linkAnnex fromto key src (Just srcic) dest destmode = then Database.Keys.addInodeCaches key [srcic, destic] else Database.Keys.addInodeCaches key [srcic] return LinkAnnexNoop - Nothing -> ifM (linkOrCopy key src dest destmode) - ( do + Nothing -> linkOrCopy key src dest destmode >>= \case + Nothing -> failed + Just r -> do case fromto of From -> thawContent dest - To -> do - s <- liftIO $ getFileStatus dest - unless (linkCount s > 1) $ - freezeContent dest + To -> case r of + Copied -> freezeContent dest + Linked -> noop checksrcunchanged - , failed - ) where failed = do Database.Keys.addInodeCaches key [srcic] diff --git a/Annex/Content/LowLevel.hs b/Annex/Content/LowLevel.hs index 07a5d67a64..54fc0a4ed8 100644 --- a/Annex/Content/LowLevel.hs +++ b/Annex/Content/LowLevel.hs @@ -29,6 +29,8 @@ secureErase file = maybe noop go =<< annexSecureEraseCommand <$> Annex.getGitCon boolSystem "sh" [Param "-c", Param $ gencmd basecmd] gencmd = massReplace [ ("%file", shellEscape file) ] +data LinkedOrCopied = Linked | Copied + {- Hard links or copies src to dest, which must not already exist. - - Only uses a hard link when annex.thin is enabled and when src is @@ -42,13 +44,13 @@ secureErase file = maybe noop go =<< annexSecureEraseCommand <$> Annex.getGitCon - execute bit will be set. The mode is not fully copied over because - git doesn't support file modes beyond execute. -} -linkOrCopy :: Key -> FilePath -> FilePath -> Maybe FileMode -> Annex Bool +linkOrCopy :: Key -> FilePath -> FilePath -> Maybe FileMode -> Annex (Maybe LinkedOrCopied) linkOrCopy = linkOrCopy' (annexThin <$> Annex.getGitConfig) -linkOrCopy' :: Annex Bool -> Key -> FilePath -> FilePath -> Maybe FileMode -> Annex Bool +linkOrCopy' :: Annex Bool -> Key -> FilePath -> FilePath -> Maybe FileMode -> Annex (Maybe LinkedOrCopied) linkOrCopy' canhardlink key src dest destmode | maybe False isExecutable destmode = copy =<< getstat - | otherwise = catchBoolIO $ + | otherwise = catchDefaultIO Nothing $ ifM canhardlink ( hardlink , copy =<< getstat @@ -58,9 +60,12 @@ linkOrCopy' canhardlink key src dest destmode s <- getstat if linkCount s > 1 then copy s - else liftIO (createLink src dest >> preserveGitMode dest destmode >> return True) + else liftIO (createLink src dest >> preserveGitMode dest destmode >> return (Just Linked)) `catchIO` const (copy s) - copy = checkedCopyFile' key src dest destmode + copy s = ifM (checkedCopyFile' key src dest destmode s) + ( return (Just Copied) + , return Nothing + ) getstat = liftIO $ getFileStatus src {- Checks disk space before copying. -} diff --git a/Annex/Content/PointerFile.hs b/Annex/Content/PointerFile.hs index 28b72de93b..1aba305835 100644 --- a/Annex/Content/PointerFile.hs +++ b/Annex/Content/PointerFile.hs @@ -32,10 +32,9 @@ populatePointerFile restage k obj f = go =<< liftIO (isPointerFile f) destmode <- liftIO $ catchMaybeIO $ fileMode <$> getFileStatus f liftIO $ nukeFile f (ic, populated) <- replaceFile f $ \tmp -> do - ok <- linkOrCopy k obj tmp destmode - if ok - then thawContent tmp - else liftIO $ writePointerFile tmp k destmode + 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 diff --git a/Command/ReKey.hs b/Command/ReKey.hs index 4de6e966d1..647f31afe9 100644 --- a/Command/ReKey.hs +++ b/Command/ReKey.hs @@ -85,7 +85,7 @@ linkKey file oldkey newkey = ifM (isJust <$> isAnnexLink file) - and vulnerable to corruption. -} ( getViaTmpFromDisk RetrievalAllKeysSecure DefaultVerify newkey $ \tmp -> unVerified $ do oldobj <- calcRepo (gitAnnexLocation oldkey) - linkOrCopy' (return True) newkey oldobj tmp Nothing + isJust <$> linkOrCopy' (return True) newkey oldobj tmp Nothing , do ic <- withTSDelta (liftIO . genInodeCache file) {- The file being rekeyed is itself an unlocked file, so if