avoid failure to lock content of removed file causing drop etc to fail
This was already prevented in other ways, but as seen in commit
c30fd24d91
, those were a bit fragile.
And I'm not sure races were avoided in every case before. At least a
race between two separate git-annex processes, dropping the same
content, seemed possible.
This way, if locking fails, and the content is not present, it will
always do the right thing. Also, it avoids the overhead of an unncessary
inAnnex check for every file.
This commit was sponsored by Denis Dzyubenko on Patreon.
This commit is contained in:
parent
c30fd24d91
commit
2a45b5ae9a
11 changed files with 65 additions and 40 deletions
|
@ -194,13 +194,15 @@ contentLockFile key = Just <$> calcRepo (gitAnnexContentLock key)
|
|||
- rather than running the action.
|
||||
-}
|
||||
lockContentShared :: Key -> (VerifiedCopy -> Annex a) -> Annex a
|
||||
lockContentShared key a = lockContentUsing lock key $ ifM (inAnnex key)
|
||||
( do
|
||||
u <- getUUID
|
||||
withVerifiedCopy LockedCopy u (return True) a
|
||||
, giveup $ "failed to lock content: not present"
|
||||
)
|
||||
lockContentShared key a = lockContentUsing lock key notpresent $
|
||||
ifM (inAnnex key)
|
||||
( do
|
||||
u <- getUUID
|
||||
withVerifiedCopy LockedCopy u (return True) a
|
||||
, notpresent
|
||||
)
|
||||
where
|
||||
notpresent = giveup $ "failed to lock content: not present"
|
||||
#ifndef mingw32_HOST_OS
|
||||
lock contentfile Nothing = tryLockShared Nothing contentfile
|
||||
lock _ (Just lockfile) = posixLocker tryLockShared lockfile
|
||||
|
@ -212,9 +214,12 @@ lockContentShared key a = lockContentUsing lock key $ ifM (inAnnex key)
|
|||
- might remove it.
|
||||
-
|
||||
- If locking fails, throws an exception rather than running the action.
|
||||
-
|
||||
- But, if locking fails because the the content is not present, runs the
|
||||
- fallback action instead.
|
||||
-}
|
||||
lockContentForRemoval :: Key -> (ContentRemovalLock -> Annex a) -> Annex a
|
||||
lockContentForRemoval key a = lockContentUsing lock key $
|
||||
lockContentForRemoval :: Key -> Annex a -> (ContentRemovalLock -> Annex a) -> Annex a
|
||||
lockContentForRemoval key fallback a = lockContentUsing lock key fallback $
|
||||
a (ContentRemovalLock key)
|
||||
where
|
||||
#ifndef mingw32_HOST_OS
|
||||
|
@ -251,22 +256,31 @@ winLocker takelock _ (Just lockfile) = do
|
|||
winLocker _ _ Nothing = return Nothing
|
||||
#endif
|
||||
|
||||
lockContentUsing :: ContentLocker -> Key -> Annex a -> Annex a
|
||||
lockContentUsing locker key a = do
|
||||
{- The fallback action is run if the ContentLocker throws an IO exception
|
||||
- and the content is not present. It's not guaranteed to always run when
|
||||
- the content is not present, because the content file is not always
|
||||
- the file that is locked eg on Windows a different file is locked. -}
|
||||
lockContentUsing :: ContentLocker -> Key -> Annex a -> Annex a -> Annex a
|
||||
lockContentUsing locker key fallback a = do
|
||||
contentfile <- fromRawFilePath <$> calcRepo (gitAnnexLocation key)
|
||||
lockfile <- contentLockFile key
|
||||
bracket
|
||||
(lock contentfile lockfile)
|
||||
(unlock lockfile)
|
||||
(const a)
|
||||
(either (const noop) (unlock lockfile))
|
||||
go
|
||||
where
|
||||
alreadylocked = giveup "content is locked"
|
||||
failedtolock e = giveup $ "failed to lock content: " ++ show e
|
||||
|
||||
lock contentfile lockfile =
|
||||
(maybe alreadylocked return
|
||||
=<< locker contentfile lockfile)
|
||||
`catchIO` failedtolock
|
||||
lock contentfile lockfile = tryIO $
|
||||
maybe alreadylocked return
|
||||
=<< locker contentfile lockfile
|
||||
|
||||
go (Right _) = a
|
||||
go (Left e) = ifM (inAnnex key)
|
||||
( failedtolock e
|
||||
, fallback
|
||||
)
|
||||
|
||||
#ifndef mingw32_HOST_OS
|
||||
unlock mlockfile lck = do
|
||||
|
|
|
@ -17,7 +17,6 @@ import qualified Command.Drop
|
|||
import Command
|
||||
import Annex.Wanted
|
||||
import Annex.SpecialRemote.Config
|
||||
import Annex.Content
|
||||
import qualified Database.Keys
|
||||
import Git.FilePath
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue