2012-03-04 20:00:24 +00:00
|
|
|
{- Adds hooks to remotes.
|
|
|
|
-
|
2015-01-21 16:50:09 +00:00
|
|
|
- Copyright 2012 Joey Hess <id@joeyh.name>
|
2012-03-04 20:00:24 +00:00
|
|
|
-
|
2019-03-13 19:48:14 +00:00
|
|
|
- Licensed under the GNU AGPL version 3 or higher.
|
2012-03-04 20:00:24 +00:00
|
|
|
-}
|
|
|
|
|
2020-10-28 21:25:59 +00:00
|
|
|
{-# LANGUAGE OverloadedStrings #-}
|
2013-05-11 20:03:00 +00:00
|
|
|
{-# LANGUAGE CPP #-}
|
|
|
|
|
2012-03-04 20:00:24 +00:00
|
|
|
module Remote.Helper.Hooks (addHooks) where
|
|
|
|
|
|
|
|
import qualified Data.Map as M
|
2020-10-28 21:25:59 +00:00
|
|
|
import qualified System.FilePath.ByteString as P
|
2012-03-04 20:00:24 +00:00
|
|
|
|
2016-01-20 20:36:33 +00:00
|
|
|
import Annex.Common
|
2012-03-04 20:00:24 +00:00
|
|
|
import Types.Remote
|
2014-03-13 23:06:26 +00:00
|
|
|
import Types.CleanupActions
|
2012-03-04 20:00:24 +00:00
|
|
|
import qualified Annex
|
2014-07-10 04:32:23 +00:00
|
|
|
import Annex.LockFile
|
2015-11-12 22:05:45 +00:00
|
|
|
import Annex.LockPool
|
2012-04-21 20:59:49 +00:00
|
|
|
import Annex.Perms
|
2012-03-04 20:00:24 +00:00
|
|
|
|
|
|
|
{- Modifies a remote's access functions to first run the
|
|
|
|
- annex-start-command hook, and trigger annex-stop-command on shutdown.
|
|
|
|
- This way, the hooks are only run when a remote is actively being used.
|
|
|
|
-}
|
2013-01-01 17:52:47 +00:00
|
|
|
addHooks :: Remote -> Remote
|
|
|
|
addHooks r = addHooks' r
|
|
|
|
(remoteAnnexStartCommand $ gitconfig r)
|
|
|
|
(remoteAnnexStopCommand $ gitconfig r)
|
2012-03-04 20:00:24 +00:00
|
|
|
addHooks' :: Remote -> Maybe String -> Maybe String -> Remote
|
|
|
|
addHooks' r Nothing Nothing = r
|
|
|
|
addHooks' r starthook stophook = r'
|
2012-11-11 04:51:07 +00:00
|
|
|
where
|
|
|
|
r' = r
|
|
|
|
{ storeKey = \k f p -> wrapper $ storeKey r k f p
|
2013-04-11 21:15:45 +00:00
|
|
|
, retrieveKeyFile = \k f d p -> wrapper $ retrieveKeyFile r k f d p
|
2020-05-13 21:05:56 +00:00
|
|
|
, retrieveKeyFileCheap = case retrieveKeyFileCheap r of
|
|
|
|
Just a -> Just $ \k af f -> wrapper $ a k af f
|
|
|
|
Nothing -> Nothing
|
2013-09-26 03:19:01 +00:00
|
|
|
, removeKey = wrapper . removeKey r
|
2014-08-06 17:45:19 +00:00
|
|
|
, checkPresent = wrapper . checkPresent r
|
2012-11-11 04:51:07 +00:00
|
|
|
}
|
|
|
|
where
|
|
|
|
wrapper = runHooks r' starthook stophook
|
2012-03-04 20:00:24 +00:00
|
|
|
|
|
|
|
runHooks :: Remote -> Maybe String -> Maybe String -> Annex a -> Annex a
|
|
|
|
runHooks r starthook stophook a = do
|
|
|
|
dir <- fromRepo gitAnnexRemotesDir
|
2020-10-28 21:25:59 +00:00
|
|
|
let lck = dir P.</> remoteid <> ".lck"
|
2015-05-18 20:23:07 +00:00
|
|
|
whenM (notElem lck . M.keys <$> getLockCache) $ do
|
2020-03-05 18:56:47 +00:00
|
|
|
createAnnexDirectory dir
|
2012-03-04 20:00:24 +00:00
|
|
|
firstrun lck
|
|
|
|
a
|
2012-11-11 04:51:07 +00:00
|
|
|
where
|
2020-10-29 14:53:01 +00:00
|
|
|
remoteid = fromUUID (uuid r)
|
2012-11-11 04:51:07 +00:00
|
|
|
run Nothing = noop
|
|
|
|
run (Just command) = void $ liftIO $
|
|
|
|
boolSystem "sh" [Param "-c", Param command]
|
|
|
|
firstrun lck = do
|
|
|
|
-- Take a shared lock; This indicates that git-annex
|
|
|
|
-- is using the remote, and prevents other instances
|
|
|
|
-- of it from running the stophook. If another
|
|
|
|
-- instance is shutting down right now, this
|
|
|
|
-- will block waiting for its exclusive lock to clear.
|
2015-05-18 20:23:07 +00:00
|
|
|
lockFileCached lck
|
2012-03-04 20:00:24 +00:00
|
|
|
|
2012-11-11 04:51:07 +00:00
|
|
|
-- The starthook is run even if some other git-annex
|
|
|
|
-- is already running, and ran it before.
|
|
|
|
-- It would be difficult to use locking to ensure
|
|
|
|
-- it's only run once, and it's also possible for
|
|
|
|
-- git-annex to be interrupted before it can run the
|
|
|
|
-- stophook, in which case the starthook
|
|
|
|
-- would be run again by the next git-annex.
|
|
|
|
-- So, requiring idempotency is the right approach.
|
|
|
|
run starthook
|
2012-03-04 20:00:24 +00:00
|
|
|
|
2020-12-11 19:28:58 +00:00
|
|
|
Annex.addCleanupAction (StopHook $ uuid r) $ runstop lck
|
2013-08-04 17:54:09 +00:00
|
|
|
runstop lck = do
|
2012-11-11 04:51:07 +00:00
|
|
|
-- Drop any shared lock we have, and take an
|
|
|
|
-- exclusive lock, without blocking. If the lock
|
|
|
|
-- succeeds, we're the only process using this remote,
|
|
|
|
-- so can stop it.
|
|
|
|
unlockFile lck
|
2014-01-28 18:17:14 +00:00
|
|
|
#ifndef mingw32_HOST_OS
|
2012-11-11 04:51:07 +00:00
|
|
|
mode <- annexFileMode
|
2015-11-12 22:05:45 +00:00
|
|
|
v <- noUmask mode $ tryLockExclusive (Just mode) lck
|
2013-05-11 20:03:00 +00:00
|
|
|
#else
|
2014-01-28 18:17:14 +00:00
|
|
|
v <- liftIO $ lockExclusive lck
|
2014-08-20 22:56:25 +00:00
|
|
|
#endif
|
2014-01-28 18:17:14 +00:00
|
|
|
case v of
|
|
|
|
Nothing -> noop
|
|
|
|
Just lockhandle -> do
|
|
|
|
run stophook
|
|
|
|
liftIO $ dropLock lockhandle
|