migrate and rekey v6 unlocked file support
This commit is contained in:
parent
0b59fb423e
commit
3b960d1422
3 changed files with 76 additions and 26 deletions
|
@ -30,6 +30,8 @@ module Annex.Content (
|
||||||
LinkAnnexResult(..),
|
LinkAnnexResult(..),
|
||||||
unlinkAnnex,
|
unlinkAnnex,
|
||||||
checkedCopyFile,
|
checkedCopyFile,
|
||||||
|
linkOrCopy,
|
||||||
|
linkOrCopy',
|
||||||
sendAnnex,
|
sendAnnex,
|
||||||
prepSendAnnex,
|
prepSendAnnex,
|
||||||
removeAnnex,
|
removeAnnex,
|
||||||
|
@ -582,11 +584,14 @@ linkAnnex fromto key src (Just srcic) dest = do
|
||||||
|
|
||||||
{- Hard links or copies src to dest. Only uses a hard link when annex.thin
|
{- Hard links or copies src to dest. Only uses a hard link when annex.thin
|
||||||
- is enabled and when src is not already hardlinked to elsewhere.
|
- is enabled and when src is not already hardlinked to elsewhere.
|
||||||
- Checks disk reserve before copying, and will fail if not enough space,
|
- Checks disk reserve before copying against the size of the key,
|
||||||
- or if the dest file already exists. -}
|
- and will fail if not enough space, or if the dest file already exists. -}
|
||||||
linkOrCopy :: Key -> FilePath -> FilePath -> Annex Bool
|
linkOrCopy :: Key -> FilePath -> FilePath -> Annex Bool
|
||||||
linkOrCopy key src dest = catchBoolIO $
|
linkOrCopy = linkOrCopy' (annexThin <$> Annex.getGitConfig)
|
||||||
ifM (annexThin <$> Annex.getGitConfig)
|
|
||||||
|
linkOrCopy' :: Annex Bool -> Key -> FilePath -> FilePath -> Annex Bool
|
||||||
|
linkOrCopy' canhardlink key src dest = catchBoolIO $
|
||||||
|
ifM canhardlink
|
||||||
( hardlink
|
( hardlink
|
||||||
, copy =<< getstat
|
, copy =<< getstat
|
||||||
)
|
)
|
||||||
|
|
|
@ -74,9 +74,12 @@ perform file oldkey oldbackend newbackend = go =<< genkey
|
||||||
| knowngoodcontent = finish newkey
|
| knowngoodcontent = finish newkey
|
||||||
| otherwise = stopUnless checkcontent $ finish newkey
|
| otherwise = stopUnless checkcontent $ finish newkey
|
||||||
checkcontent = Command.Fsck.checkBackend oldbackend oldkey Command.Fsck.KeyLocked $ Just file
|
checkcontent = Command.Fsck.checkBackend oldbackend oldkey Command.Fsck.KeyLocked $ Just file
|
||||||
finish newkey = stopUnless (Command.ReKey.linkKey oldkey newkey) $ do
|
finish newkey = ifM (Command.ReKey.linkKey file oldkey newkey)
|
||||||
|
( do
|
||||||
copyMetaData oldkey newkey
|
copyMetaData oldkey newkey
|
||||||
next $ Command.ReKey.cleanup file oldkey newkey
|
next $ Command.ReKey.cleanup file oldkey newkey
|
||||||
|
, error "failed"
|
||||||
|
)
|
||||||
genkey = case maybe Nothing (\fm -> fm oldkey newbackend (Just file)) (fastMigrate oldbackend) of
|
genkey = case maybe Nothing (\fm -> fm oldkey newbackend (Just file)) (fastMigrate oldbackend) of
|
||||||
Just newkey -> return $ Just (newkey, True)
|
Just newkey -> return $ Just (newkey, True)
|
||||||
Nothing -> do
|
Nothing -> do
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{- git-annex command
|
{- git-annex command
|
||||||
-
|
-
|
||||||
- Copyright 2012 Joey Hess <id@joeyh.name>
|
- Copyright 2012-2016 Joey Hess <id@joeyh.name>
|
||||||
-
|
-
|
||||||
- Licensed under the GNU GPL version 3 or higher.
|
- Licensed under the GNU GPL version 3 or higher.
|
||||||
-}
|
-}
|
||||||
|
@ -13,10 +13,16 @@ import qualified Annex
|
||||||
import Types.Key
|
import Types.Key
|
||||||
import Annex.Content
|
import Annex.Content
|
||||||
import Annex.Ingest
|
import Annex.Ingest
|
||||||
|
import Annex.Link
|
||||||
|
import Annex.Perms
|
||||||
|
import Annex.ReplaceFile
|
||||||
import Logs.Web
|
import Logs.Web
|
||||||
import Logs.Location
|
import Logs.Location
|
||||||
import Utility.CopyFile
|
import Git.FilePath
|
||||||
import qualified Remote
|
import qualified Remote
|
||||||
|
import qualified Database.Keys
|
||||||
|
import Annex.InodeSentinal
|
||||||
|
import Utility.InodeCache
|
||||||
|
|
||||||
cmd :: Command
|
cmd :: Command
|
||||||
cmd = notDirect $
|
cmd = notDirect $
|
||||||
|
@ -40,23 +46,49 @@ start (file, keyname) = ifAnnexed file go stop
|
||||||
|
|
||||||
perform :: FilePath -> Key -> Key -> CommandPerform
|
perform :: FilePath -> Key -> Key -> CommandPerform
|
||||||
perform file oldkey newkey = do
|
perform file oldkey newkey = do
|
||||||
present <- inAnnex oldkey
|
ifM (inAnnex oldkey)
|
||||||
_ <- if present
|
( unlessM (linkKey file oldkey newkey) $
|
||||||
then linkKey oldkey newkey
|
error "failed"
|
||||||
else do
|
, unlessM (Annex.getState Annex.force) $
|
||||||
unlessM (Annex.getState Annex.force) $
|
|
||||||
error $ file ++ " is not available (use --force to override)"
|
error $ file ++ " is not available (use --force to override)"
|
||||||
return True
|
)
|
||||||
next $ cleanup file oldkey newkey
|
next $ cleanup file oldkey newkey
|
||||||
|
|
||||||
{- Make a hard link to the old key content (when supported),
|
{- Make a hard link to the old key content (when supported),
|
||||||
- to avoid wasting disk space. -}
|
- to avoid wasting disk space. -}
|
||||||
linkKey :: Key -> Key -> Annex Bool
|
linkKey :: FilePath -> Key -> Key -> Annex Bool
|
||||||
linkKey oldkey newkey = getViaTmp' DefaultVerify newkey $ \tmp -> unVerified $ do
|
linkKey file oldkey newkey = ifM (isJust <$> isAnnexLink file)
|
||||||
src <- calcRepo $ gitAnnexLocation oldkey
|
{- If the object file is already hardlinked to elsewhere, a hard
|
||||||
liftIO $ ifM (doesFileExist tmp)
|
- link won't be made by getViaTmp', but a copy instead.
|
||||||
( return True
|
- This avoids hard linking to content linked to an
|
||||||
, createLinkOrCopy src tmp
|
- unlocked file, which would leave the new key unlocked
|
||||||
|
- and vulnerable to corruption. -}
|
||||||
|
( getViaTmp' DefaultVerify newkey $ \tmp -> unVerified $ do
|
||||||
|
oldobj <- calcRepo (gitAnnexLocation oldkey)
|
||||||
|
linkOrCopy' (return True) newkey oldobj tmp
|
||||||
|
, do
|
||||||
|
ic <- withTSDelta (liftIO . genInodeCache file)
|
||||||
|
{- The file being rekeyed is itself an unlocked file, so if
|
||||||
|
- it's linked to the old key, that link must be broken. -}
|
||||||
|
oldobj <- calcRepo (gitAnnexLocation oldkey)
|
||||||
|
v <- tryNonAsync $ modifyContent oldobj $ do
|
||||||
|
replaceFile oldobj $ \tmp ->
|
||||||
|
unlessM (checkedCopyFile oldkey file tmp) $
|
||||||
|
error "can't lock old key"
|
||||||
|
freezeContent oldobj
|
||||||
|
oldic <- withTSDelta (liftIO . genInodeCache oldobj)
|
||||||
|
whenM (isUnmodified oldkey oldobj) $
|
||||||
|
Database.Keys.addInodeCaches oldkey (catMaybes [oldic])
|
||||||
|
case v of
|
||||||
|
Left e -> do
|
||||||
|
warning (show e)
|
||||||
|
return False
|
||||||
|
Right () -> do
|
||||||
|
r <- linkToAnnex newkey file ic
|
||||||
|
return $ case r of
|
||||||
|
LinkAnnexFailed -> False
|
||||||
|
LinkAnnexOk -> True
|
||||||
|
LinkAnnexNoop -> True
|
||||||
)
|
)
|
||||||
|
|
||||||
cleanup :: FilePath -> Key -> Key -> CommandCleanup
|
cleanup :: FilePath -> Key -> Key -> CommandCleanup
|
||||||
|
@ -68,8 +100,18 @@ cleanup file oldkey newkey = do
|
||||||
r <- Remote.claimingUrl url
|
r <- Remote.claimingUrl url
|
||||||
setUrlPresent (Remote.uuid r) newkey url
|
setUrlPresent (Remote.uuid r) newkey url
|
||||||
|
|
||||||
|
ifM (isJust <$> isAnnexLink file)
|
||||||
|
( do
|
||||||
-- Update symlink to use the new key.
|
-- Update symlink to use the new key.
|
||||||
liftIO $ removeFile file
|
liftIO $ removeFile file
|
||||||
addLink file newkey Nothing
|
addLink file newkey Nothing
|
||||||
|
, do
|
||||||
|
liftIO $ whenM (isJust <$> isPointerFile file) $
|
||||||
|
writeFile file (formatPointer newkey)
|
||||||
|
stagePointerFile file =<< hashPointerFile newkey
|
||||||
|
Database.Keys.removeAssociatedFile oldkey
|
||||||
|
=<< inRepo (toTopFilePath file)
|
||||||
|
)
|
||||||
|
|
||||||
logStatus newkey InfoPresent
|
logStatus newkey InfoPresent
|
||||||
return True
|
return True
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue