Bugfix: Fix bug in inode cache sentinal check, which broke copying to local repos if the repo being copied from had moved to a different filesystem or otherwise changed all its inodes'

This commit is contained in:
Joey Hess 2013-03-12 16:41:54 -04:00
parent e63a983cf1
commit f7de51e8b6
5 changed files with 32 additions and 3 deletions

View file

@ -31,6 +31,7 @@ module Annex (
getGitConfig, getGitConfig,
changeGitConfig, changeGitConfig,
changeGitRepo, changeGitRepo,
withCurrentState,
) where ) where
import "mtl" Control.Monad.State.Strict import "mtl" Control.Monad.State.Strict
@ -216,3 +217,13 @@ changeGitRepo r = changeState $ \s -> s
{ repo = r { repo = r
, gitconfig = extractGitConfig r , gitconfig = extractGitConfig r
} }
{- Converts an Annex action into an IO action, that runs with a copy
- of the current Annex state.
-
- Use with caution; the action should not rely on changing the
- state, as it will be thrown away. -}
withCurrentState :: Annex a -> Annex (IO a)
withCurrentState a = do
s <- getState id
return $ eval s a

View file

@ -276,6 +276,10 @@ replaceFile file a = do
- In direct mode, it's possible for the file to change as it's being sent. - In direct mode, it's possible for the file to change as it's being sent.
- If this happens, runs the rollback action and returns False. The - If this happens, runs the rollback action and returns False. The
- rollback action should remove the data that was transferred. - rollback action should remove the data that was transferred.
-
- Note that the returned action is, in some cases, run in the Annex monad
- of the remote that is receiving the object, rather than the sender.
- So it cannot rely on Annex state, particular
-} -}
sendAnnex :: Key -> Annex () -> (FilePath -> Annex Bool) -> Annex Bool sendAnnex :: Key -> Annex () -> (FilePath -> Annex Bool) -> Annex Bool
sendAnnex key rollback sendobject = go =<< prepSendAnnex key sendAnnex key rollback sendobject = go =<< prepSendAnnex key
@ -303,6 +307,7 @@ prepSendAnnex key = withObjectLoc key indirect direct
direct [] = return Nothing direct [] = return Nothing
direct (f:fs) = do direct (f:fs) = do
cache <- recordedInodeCache key cache <- recordedInodeCache key
liftIO $ print ("prepSendAnnex pre cache", cache)
-- check that we have a good file -- check that we have a good file
ifM (sameInodeCache f cache) ifM (sameInodeCache f cache)
( return $ Just (f, sameInodeCache f cache) ( return $ Just (f, sameInodeCache f cache)

View file

@ -150,8 +150,12 @@ compareInodeCaches :: InodeCache -> InodeCache -> Annex Bool
compareInodeCaches x y compareInodeCaches x y
| compareStrong x y = return True | compareStrong x y = return True
| otherwise = ifM inodesChanged | otherwise = ifM inodesChanged
( return $ compareWeak x y ( do
, return False liftIO $ print ("compareInodeCaches weak")
return $ compareWeak x y
, do
liftIO $ print ("compareInodeCaches no inode change but cache not match")
return False
) )
compareInodeCachesWith :: Annex InodeComparisonType compareInodeCachesWith :: Annex InodeComparisonType
@ -171,9 +175,11 @@ inodesChanged = maybe calc return =<< Annex.getState Annex.inodeschanged
scache <- liftIO . genInodeCache scache <- liftIO . genInodeCache
=<< fromRepo gitAnnexInodeSentinal =<< fromRepo gitAnnexInodeSentinal
scached <- readInodeSentinalFile scached <- readInodeSentinalFile
liftIO $ print (scache, scached)
let changed = case (scache, scached) of let changed = case (scache, scached) of
(Just c1, Just c2) -> not $ compareStrong c1 c2 (Just c1, Just c2) -> not $ compareStrong c1 c2
_ -> True _ -> True
liftIO $ print changed
Annex.changeState $ \s -> s { Annex.inodeschanged = Just changed } Annex.changeState $ \s -> s { Annex.inodeschanged = Just changed }
return changed return changed

View file

@ -351,6 +351,10 @@ copyToRemote r key file p
where where
copylocal Nothing = return False copylocal Nothing = return False
copylocal (Just (object, checksuccess)) = do copylocal (Just (object, checksuccess)) = do
-- The checksuccess action is going to be run in
-- the remote's Annex, but it needs access to the current
-- Annex monad's state.
checksuccessio <- Annex.withCurrentState checksuccess
let params = rsyncParams r let params = rsyncParams r
u <- getUUID u <- getUUID
-- run copy from perspective of remote -- run copy from perspective of remote
@ -360,7 +364,7 @@ copyToRemote r key file p
ensureInitialized ensureInitialized
download u key file noRetry $ download u key file noRetry $
Annex.Content.saveState True `after` Annex.Content.saveState True `after`
Annex.Content.getViaTmpChecked checksuccess key Annex.Content.getViaTmpChecked (liftIO checksuccessio) key
(\d -> rsyncOrCopyFile params object d p) (\d -> rsyncOrCopyFile params object d p)
) )

3
debian/changelog vendored
View file

@ -8,6 +8,9 @@ git-annex (4.20130228) UNRELEASED; urgency=low
* Bugfix: If the UUID of a remote is not known, prevent --from, --to, * Bugfix: If the UUID of a remote is not known, prevent --from, --to,
and other ways of specifying remotes by name from selecting it, and other ways of specifying remotes by name from selecting it,
since it is not possible to sanely use it. since it is not possible to sanely use it.
* Bugfix: Fix bug in inode cache sentinal check, which broke
copying to local repos if the repo being copied from had moved
to a different filesystem or otherwise changed all its inodes'
* Switch from using regex-compat to regex-tdfa, as the C regex library * Switch from using regex-compat to regex-tdfa, as the C regex library
is rather buggy. is rather buggy.