summaryrefslogtreecommitdiff
path: root/Annex
diff options
context:
space:
mode:
authorGravatar Joey Hess <joeyh@joeyh.name>2015-02-09 18:34:48 -0400
committerGravatar Joey Hess <joeyh@joeyh.name>2015-02-09 18:34:48 -0400
commit02a3743f37eb417b90da0109a09c9f1e2f773f21 (patch)
tree4b9a70a201e401d2319a5825c6176dfc1e1586b4 /Annex
parent553e56253613b7bfa5b7f1b2aa579358567da28f (diff)
Improve race recovery code when committing to git-annex branch.
Diffstat (limited to 'Annex')
-rw-r--r--Annex/Branch.hs39
1 files changed, 24 insertions, 15 deletions
diff --git a/Annex/Branch.hs b/Annex/Branch.hs
index c67270312..6ce711996 100644
--- a/Annex/Branch.hs
+++ b/Annex/Branch.hs
@@ -29,6 +29,7 @@ import qualified Data.ByteString.Lazy as L
import qualified Data.Set as S
import qualified Data.Map as M
import Data.Bits.Utils
+import Control.Concurrent (threadDelay)
import Common.Annex
import Annex.BranchState
@@ -232,28 +233,32 @@ forceCommit message = lockJournal $ \jl -> do
{- Commits the staged changes in the index to the branch.
-
- - Ensures that the branch's index file is first updated to the state
+ - Ensures that the branch's index file is first updated to merge the state
- of the branch at branchref, before running the commit action. This
- is needed because the branch may have had changes pushed to it, that
- are not yet reflected in the index.
- -
- - Also safely handles a race that can occur if a change is being pushed
- - into the branch at the same time. When the race happens, the commit will
- - be made on top of the newly pushed change, but without the index file
- - being updated to include it. The result is that the newly pushed
- - change is reverted. This race is detected and another commit made
- - to fix it.
-
- The branchref value can have been obtained using getBranch at any
- previous point, though getting it a long time ago makes the race
- more likely to occur.
+ -
+ - Note that changes may be pushed to the branch at any point in time!
+ - So, there's a race. If the commit is made using the newly pushed tip of
+ - the branch as its parent, and that ref has not yet been merged into the
+ - index, then the result is that the commit will revert the pushed
+ - changes, since they have not been merged into the index. This race
+ - is detected and another commit made to fix it.
+ -
+ - (It's also possible for the branch to be overwritten,
+ - losing the commit made here. But that's ok; the data is still in the
+ - index and will get committed again later.)
-}
commitIndex :: JournalLocked -> Git.Ref -> String -> [Git.Ref] -> Annex ()
commitIndex jl branchref message parents = do
showStoringStateAction
- commitIndex' jl branchref message parents
-commitIndex' :: JournalLocked -> Git.Ref -> String -> [Git.Ref] -> Annex ()
-commitIndex' jl branchref message parents = do
+ commitIndex' jl branchref message message 0 parents
+commitIndex' :: JournalLocked -> Git.Ref -> String -> String -> Integer -> [Git.Ref] -> Annex ()
+commitIndex' jl branchref message basemessage retrynum parents = do
updateIndex jl branchref
committedref <- inRepo $ Git.Branch.commitAlways Git.Branch.AutomaticCommit message fullname parents
setIndexSha committedref
@@ -276,12 +281,16 @@ commitIndex' jl branchref message parents = do
| otherwise = True -- race!
{- To recover from the race, union merge the lost refs
- - into the index, and recommit on top of the bad commit. -}
+ - into the index. -}
fixrace committedref lostrefs = do
+ showSideAction "recovering from race"
+ let retrynum' = retrynum+1
+ -- small sleep to let any activity that caused
+ -- the race settle down
+ liftIO $ threadDelay (100000 + fromInteger retrynum')
mergeIndex jl lostrefs
- commitIndex jl committedref racemessage [committedref]
-
- racemessage = message ++ " (recovery from race)"
+ let racemessage = basemessage ++ " (recovery from race #" ++ show retrynum' ++ "; expected commit parent " ++ show branchref ++ " but found " ++ show lostrefs ++ " )"
+ commitIndex' jl committedref racemessage basemessage retrynum' [committedref]
{- Lists all files on the branch. There may be duplicates in the list. -}
files :: Annex [FilePath]