merge conflict resolution now working

Avoid MVar deadlock issue, which I don't understand.
Have not taken the time to debug it fully, because it turns out I don't
need to resolve merge conflicts when a new branch ref is written... I
think.

Ensure the git-annex branch is merged when doing a manual pull.
Otherwise it can get out of sync, since git-annex normally only merges it
once per run.
This commit is contained in:
Joey Hess 2012-06-27 20:50:50 -04:00
parent 59b5266ad1
commit fb51d99951

View file

@ -11,6 +11,7 @@ import Common.Annex
import Assistant.ThreadedMonad import Assistant.ThreadedMonad
import Utility.DirWatcher import Utility.DirWatcher
import Utility.Types.DirWatcher import Utility.Types.DirWatcher
import qualified Annex.Branch
import qualified Git import qualified Git
import qualified Git.Command import qualified Git.Command
import qualified Git.Merge import qualified Git.Merge
@ -26,7 +27,10 @@ mergeThread st = do
g <- runThreadState st $ fromRepo id g <- runThreadState st $ fromRepo id
let dir = Git.localGitDir g </> "refs" </> "heads" </> "synced" let dir = Git.localGitDir g </> "refs" </> "heads" </> "synced"
createDirectoryIfMissing True dir createDirectoryIfMissing True dir
let hook a = Just $ runHandler st g a let hook a = Just $ runHandler g a
-- XXX: For reasons currently unknown, using the ThreadState
-- inside the watch hooks leads to a MVar deadlock.
-- Luckily, we don't currently need to do that.
let hooks = mkWatchHooks let hooks = mkWatchHooks
{ addHook = hook onAdd { addHook = hook onAdd
, errHook = hook onErr , errHook = hook onErr
@ -34,21 +38,21 @@ mergeThread st = do
watchDir dir (const False) hooks id watchDir dir (const False) hooks id
where where
type Handler = ThreadState -> Git.Repo -> FilePath -> Maybe FileStatus -> IO () type Handler = Git.Repo -> FilePath -> Maybe FileStatus -> IO ()
{- Runs an action handler. {- Runs an action handler.
- -
- Exceptions are ignored, otherwise a whole thread could be crashed. - Exceptions are ignored, otherwise a whole thread could be crashed.
-} -}
runHandler :: ThreadState -> Git.Repo -> Handler -> FilePath -> Maybe FileStatus -> IO () runHandler :: Git.Repo -> Handler -> FilePath -> Maybe FileStatus -> IO ()
runHandler st g handler file filestatus = void $ do runHandler g handler file filestatus = void $ do
either print (const noop) =<< tryIO go either print (const noop) =<< tryIO go
where where
go = handler st g file filestatus go = handler g file filestatus
{- Called when there's an error with inotify. -} {- Called when there's an error with inotify. -}
onErr :: Handler onErr :: Handler
onErr _ _ msg _ = error msg onErr _ msg _ = error msg
{- Called when a new branch ref is written. {- Called when a new branch ref is written.
- -
@ -62,27 +66,26 @@ onErr _ _ msg _ = error msg
- ran are merged in. - ran are merged in.
-} -}
onAdd :: Handler onAdd :: Handler
onAdd st g file _ onAdd g file _
| ".lock" `isSuffixOf` file = noop | ".lock" `isSuffixOf` file = noop
| otherwise = do | otherwise = do
let changedbranch = Git.Ref $ let changedbranch = Git.Ref $
"refs" </> "heads" </> takeFileName file "refs" </> "heads" </> takeFileName file
current <- Git.Branch.current g current <- Git.Branch.current g
when (Just changedbranch == current) $ when (Just changedbranch == current) $
void $ mergeBranch st changedbranch g void $ mergeBranch changedbranch g
mergeBranch :: ThreadState -> Git.Ref -> Git.Repo -> IO Bool mergeBranch :: Git.Ref -> Git.Repo -> IO Bool
mergeBranch st branch repo = do mergeBranch = Git.Merge.mergeNonInteractive . Command.Sync.syncBranch
ok <- Git.Merge.mergeNonInteractive (Command.Sync.syncBranch branch) repo
if ok
then return ok
else runThreadState st Command.Sync.resolveMerge
{- Manually pull from remotes and merge their branches. Called by the pusher {- Manually pull from remotes and merge their branches. Called by the pusher
- when a push fails, which can happen due to a remote not having pushed - when a push fails, which can happen due to a remote not having pushed
- changes to us. That could be because it doesn't have us as a remote, or - changes to us. That could be because it doesn't have us as a remote, or
- because the assistant is not running there, or other reasons. -} - because the assistant is not running there, or other reasons. -}
manualPull :: Git.Ref -> [Remote] -> Annex () manualPull :: Git.Ref -> [Remote] -> Annex ()
manualPull currentbranch remotes = forM_ remotes $ \r -> do manualPull currentbranch remotes = do
void $ inRepo $ Git.Command.runBool "fetch" [Param $ Remote.name r] forM_ remotes $ \r ->
Command.Sync.mergeRemote r currentbranch inRepo $ Git.Command.runBool "fetch" [Param $ Remote.name r]
Annex.Branch.forceUpdate
forM_ remotes $ \r ->
Command.Sync.mergeRemote r currentbranch