pull from newly mounted git remotes

This commit is contained in:
Joey Hess 2012-07-22 15:06:18 -04:00
parent 4ec9244f1a
commit e4f714d1be
2 changed files with 68 additions and 10 deletions

View file

@ -60,6 +60,14 @@ modifyDaemonStatus_ handle a = liftIO $ modifyMVar_ handle (return . a)
modifyDaemonStatus :: DaemonStatusHandle -> (DaemonStatus -> (DaemonStatus, b)) -> Annex b modifyDaemonStatus :: DaemonStatusHandle -> (DaemonStatus -> (DaemonStatus, b)) -> Annex b
modifyDaemonStatus handle a = liftIO $ modifyMVar handle (return . a) modifyDaemonStatus handle a = liftIO $ modifyMVar handle (return . a)
{- Updates the cached ordered list of remotes from the list in Annex
- state. -}
updateKnownRemotes :: DaemonStatusHandle -> Annex ()
updateKnownRemotes dstatus = do
remotes <- Command.Sync.syncRemotes []
modifyDaemonStatus_ dstatus $
\s -> s { knownRemotes = remotes }
{- Load any previous daemon status file, and store it in the MVar for this {- Load any previous daemon status file, and store it in the MVar for this
- process to use as its DaemonStatus. Also gets current transfer status. -} - process to use as its DaemonStatus. Also gets current transfer status. -}
startDaemonStatus :: Annex DaemonStatusHandle startDaemonStatus :: Annex DaemonStatusHandle

View file

@ -13,8 +13,16 @@ module Assistant.Threads.MountWatcher where
import Assistant.Common import Assistant.Common
import Assistant.ThreadedMonad import Assistant.ThreadedMonad
import Assistant.DaemonStatus import Assistant.DaemonStatus
import qualified Annex
import qualified Git
import Utility.ThreadScheduler import Utility.ThreadScheduler
import Utility.Mounts import Utility.Mounts
import Remote.List
import qualified Types.Remote as Remote
import qualified Remote.Git
import qualified Command.Sync
import Assistant.Threads.Merger
import Logs.Remote
import Control.Concurrent import Control.Concurrent
import qualified Control.Exception as E import qualified Control.Exception as E
@ -42,7 +50,7 @@ mountWatcherThread st handle =
#if WITH_DBUS #if WITH_DBUS
dbusThread :: ThreadState -> DaemonStatusHandle -> IO () dbusThread :: ThreadState -> DaemonStatusHandle -> IO ()
dbusThread st handle = E.catch (go =<< connectSession) onerr dbusThread st dstatus = E.catch (go =<< connectSession) onerr
where where
go client = ifM (checkMountMonitor client) go client = ifM (checkMountMonitor client)
( do ( do
@ -55,7 +63,7 @@ dbusThread st handle = E.catch (go =<< connectSession) onerr
listen client matcher $ \_event -> do listen client matcher $ \_event -> do
nowmounted <- currentMountPoints nowmounted <- currentMountPoints
wasmounted <- swapMVar mvar nowmounted wasmounted <- swapMVar mvar nowmounted
handleMounts st handle wasmounted nowmounted handleMounts st dstatus wasmounted nowmounted
, do , do
runThreadState st $ runThreadState st $
warning "No known volume monitor available through dbus; falling back to mtab polling" warning "No known volume monitor available through dbus; falling back to mtab polling"
@ -66,7 +74,7 @@ dbusThread st handle = E.catch (go =<< connectSession) onerr
runThreadState st $ runThreadState st $
warning $ "Failed to use dbus; falling back to mtab polling (" ++ show e ++ ")" warning $ "Failed to use dbus; falling back to mtab polling (" ++ show e ++ ")"
pollinstead pollinstead
pollinstead = pollingThread st handle pollinstead = pollingThread st dstatus
type ServiceName = String type ServiceName = String
@ -133,28 +141,70 @@ mountAdded = [gvfs, kde]
#endif #endif
pollingThread :: ThreadState -> DaemonStatusHandle -> IO () pollingThread :: ThreadState -> DaemonStatusHandle -> IO ()
pollingThread st handle = go =<< currentMountPoints pollingThread st dstatus = go =<< currentMountPoints
where where
go wasmounted = do go wasmounted = do
threadDelaySeconds (Seconds 10) threadDelaySeconds (Seconds 10)
nowmounted <- currentMountPoints nowmounted <- currentMountPoints
handleMounts st handle wasmounted nowmounted handleMounts st dstatus wasmounted nowmounted
go nowmounted go nowmounted
handleMounts :: ThreadState -> DaemonStatusHandle -> MountPoints -> MountPoints -> IO () handleMounts :: ThreadState -> DaemonStatusHandle -> MountPoints -> MountPoints -> IO ()
handleMounts st handle wasmounted nowmounted = mapM_ (handleMount st handle) $ handleMounts st dstatus wasmounted nowmounted = mapM_ (handleMount st dstatus) $
S.toList $ newMountPoints wasmounted nowmounted S.toList $ newMountPoints wasmounted nowmounted
handleMount :: ThreadState -> DaemonStatusHandle -> Mntent -> IO () handleMount :: ThreadState -> DaemonStatusHandle -> Mntent -> IO ()
handleMount st handle mntent = do handleMount st dstatus mntent = do
debug thisThread ["detected mount of", mnt_dir mntent] debug thisThread ["detected mount of", mnt_dir mntent]
rs <- remotesUnder st dstatus mntent
unless (null rs) $ do
branch <- runThreadState st $ Command.Sync.currentBranch
debug thisThread ["pulling from", show rs]
runThreadState st $ manualPull branch rs
-- TODO queue transfers for new files in both directions
where
{- Finds remotes located underneath the mount point.
-
- Updates state to include the remotes.
-
- The config of git remotes is re-read, as it may not have been available
- at startup time, or may have changed (it could even be a different
- repository at the same remote location..)
-}
remotesUnder :: ThreadState -> DaemonStatusHandle -> Mntent -> IO [Remote]
remotesUnder st dstatus mntent = runThreadState st $ do
repotop <- fromRepo Git.repoPath
rs <- remoteList
pairs <- mapM (checkremote repotop) rs
let (waschanged, rs') = unzip pairs
when (any id waschanged) $ do
Annex.changeState $ \s -> s { Annex.remotes = rs' }
updateKnownRemotes dstatus
return $ map snd $ filter fst pairs
where
checkremote repotop r = case Remote.path r of
Just p | under mntent (absPathFrom repotop p) ->
(,) <$> pure True <*> updateremote r
_ -> return (False, r)
updateremote r = do
liftIO $ debug thisThread ["updating", show r]
m <- readRemoteLog
repo <- updaterepo $ Remote.repo r
remoteGen m (Remote.remotetype r) repo
updaterepo repo
| Git.repoIsLocal repo || Git.repoIsLocalUnknown repo =
Remote.Git.configRead repo
| otherwise = return repo
type MountPoints = S.Set Mntent type MountPoints = S.Set Mntent
{- Reads mtab, getting the current set of mount points. -}
currentMountPoints :: IO MountPoints currentMountPoints :: IO MountPoints
currentMountPoints = S.fromList <$> getMounts currentMountPoints = S.fromList <$> getMounts
{- Finds new mount points, given an old and a new set. -}
newMountPoints :: MountPoints -> MountPoints -> MountPoints newMountPoints :: MountPoints -> MountPoints -> MountPoints
newMountPoints old new = S.difference new old newMountPoints old new = S.difference new old
{- Checks if a mount point contains a path. The path must be absolute. -}
under :: Mntent -> FilePath -> Bool
under = dirContains . mnt_dir