2012-07-03 14:58:40 +00:00
|
|
|
{- git-annex assistant transfer watching thread
|
|
|
|
-
|
2015-01-21 16:50:09 +00:00
|
|
|
- Copyright 2012 Joey Hess <id@joeyh.name>
|
2012-07-03 14:58:40 +00:00
|
|
|
-
|
2019-03-13 19:48:14 +00:00
|
|
|
- Licensed under the GNU AGPL version 3 or higher.
|
2012-07-03 14:58:40 +00:00
|
|
|
-}
|
|
|
|
|
|
|
|
module Assistant.Threads.TransferWatcher where
|
|
|
|
|
2012-07-20 23:29:59 +00:00
|
|
|
import Assistant.Common
|
2012-07-03 14:58:40 +00:00
|
|
|
import Assistant.DaemonStatus
|
2013-10-26 20:54:49 +00:00
|
|
|
import Assistant.TransferSlots
|
2016-08-03 16:37:12 +00:00
|
|
|
import Types.Transfer
|
2012-07-03 14:58:40 +00:00
|
|
|
import Logs.Transfer
|
|
|
|
import Utility.DirWatcher
|
2013-03-11 02:24:13 +00:00
|
|
|
import Utility.DirWatcher.Types
|
2012-08-27 18:04:06 +00:00
|
|
|
import qualified Remote
|
git style filename quoting controlled by core.quotePath
This is by no means complete, but escaping filenames in actionItemDesc does
cover most commands.
Note that for ActionItemBranchFilePath, the value is branch:file, and I
choose to only quote the file part (if necessary). I considered quoting the
whole thing. But, branch names cannot contain control characters, and while
they can contain unicode, git coes not quote unicode when displaying branch
names. So, it would be surprising for git-annex to quote unicode in a
branch name.
The find command is the most obvious command that still needs to be
dealt with. There are probably other places that filenames also get
displayed, eg embedded in error messages.
Some other commands use ActionItemOther with a filename, I think that
ActionItemOther should either be pre-sanitized, or should explicitly not
be used for filenames, so that needs more work.
When --json is used, unicode does not get escaped, but control
characters were already escaped in json.
(Key escaping may turn out to be needed, but I'm ignoring that for now.)
Sponsored-by: unqueued on Patreon
2023-04-08 18:20:02 +00:00
|
|
|
import qualified Annex
|
2020-03-06 16:52:20 +00:00
|
|
|
import Annex.Perms
|
2012-07-03 14:58:40 +00:00
|
|
|
|
2012-10-19 20:59:18 +00:00
|
|
|
import Control.Concurrent
|
2013-11-23 21:21:04 +00:00
|
|
|
import qualified Data.Map as M
|
2012-10-19 20:59:18 +00:00
|
|
|
|
2012-07-03 14:58:40 +00:00
|
|
|
{- This thread watches for changes to the gitAnnexTransferDir,
|
|
|
|
- and updates the DaemonStatus's map of ongoing transfers. -}
|
2012-10-29 17:09:58 +00:00
|
|
|
transferWatcherThread :: NamedThread
|
2013-01-26 06:09:33 +00:00
|
|
|
transferWatcherThread = namedThread "TransferWatcher" $ do
|
2012-10-29 17:09:58 +00:00
|
|
|
dir <- liftAnnex $ gitAnnexTransferDir <$> gitRepo
|
2020-03-06 16:52:20 +00:00
|
|
|
liftAnnex $ createAnnexDirectory dir
|
2012-10-29 17:09:58 +00:00
|
|
|
let hook a = Just <$> asIO2 (runHandler a)
|
|
|
|
addhook <- hook onAdd
|
|
|
|
delhook <- hook onDel
|
|
|
|
modifyhook <- hook onModify
|
|
|
|
errhook <- hook onErr
|
2012-07-03 14:58:40 +00:00
|
|
|
let hooks = mkWatchHooks
|
2012-10-29 17:09:58 +00:00
|
|
|
{ addHook = addhook
|
|
|
|
, delHook = delhook
|
|
|
|
, modifyHook = modifyhook
|
|
|
|
, errHook = errhook
|
2012-07-03 14:58:40 +00:00
|
|
|
}
|
2020-11-04 18:20:37 +00:00
|
|
|
void $ liftIO $ watchDir (fromRawFilePath dir) (const False) True hooks id
|
2012-10-29 17:09:58 +00:00
|
|
|
debug ["watching for transfers"]
|
2012-07-03 14:58:40 +00:00
|
|
|
|
2012-10-29 17:09:58 +00:00
|
|
|
type Handler = FilePath -> Assistant ()
|
2012-07-03 14:58:40 +00:00
|
|
|
|
|
|
|
{- Runs an action handler.
|
|
|
|
-
|
|
|
|
- Exceptions are ignored, otherwise a whole thread could be crashed.
|
|
|
|
-}
|
2012-10-29 17:09:58 +00:00
|
|
|
runHandler :: Handler -> FilePath -> Maybe FileStatus -> Assistant ()
|
|
|
|
runHandler handler file _filestatus =
|
2012-12-13 04:45:27 +00:00
|
|
|
either (liftIO . print) (const noop) =<< tryIO <~> handler file
|
2012-07-03 14:58:40 +00:00
|
|
|
|
|
|
|
{- Called when there's an error with inotify. -}
|
|
|
|
onErr :: Handler
|
2023-04-10 17:38:14 +00:00
|
|
|
onErr = giveup
|
2012-07-03 14:58:40 +00:00
|
|
|
|
2012-07-06 20:30:55 +00:00
|
|
|
{- Called when a new transfer information file is written. -}
|
2012-07-03 14:58:40 +00:00
|
|
|
onAdd :: Handler
|
2012-10-29 17:09:58 +00:00
|
|
|
onAdd file = case parseTransferFile file of
|
2012-07-03 14:58:40 +00:00
|
|
|
Nothing -> noop
|
2012-10-29 17:09:58 +00:00
|
|
|
Just t -> go t =<< liftAnnex (checkTransfer t)
|
|
|
|
where
|
|
|
|
go _ Nothing = noop -- transfer already finished
|
|
|
|
go t (Just info) = do
|
git style filename quoting controlled by core.quotePath
This is by no means complete, but escaping filenames in actionItemDesc does
cover most commands.
Note that for ActionItemBranchFilePath, the value is branch:file, and I
choose to only quote the file part (if necessary). I considered quoting the
whole thing. But, branch names cannot contain control characters, and while
they can contain unicode, git coes not quote unicode when displaying branch
names. So, it would be surprising for git-annex to quote unicode in a
branch name.
The find command is the most obvious command that still needs to be
dealt with. There are probably other places that filenames also get
displayed, eg embedded in error messages.
Some other commands use ActionItemOther with a filename, I think that
ActionItemOther should either be pre-sanitized, or should explicitly not
be used for filenames, so that needs more work.
When --json is used, unicode does not get escaped, but control
characters were already escaped in json.
(Key escaping may turn out to be needed, but I'm ignoring that for now.)
Sponsored-by: unqueued on Patreon
2023-04-08 18:20:02 +00:00
|
|
|
qp <- liftAnnex $ coreQuotePath <$> Annex.getGitConfig
|
|
|
|
debug [ "transfer starting:", describeTransfer qp t info ]
|
2013-04-02 20:39:11 +00:00
|
|
|
r <- liftAnnex $ Remote.remoteFromUUID $ transferUUID t
|
2012-10-30 19:39:15 +00:00
|
|
|
updateTransferInfo t info { transferRemote = r }
|
2012-07-03 14:58:40 +00:00
|
|
|
|
2012-09-20 21:24:40 +00:00
|
|
|
{- Called when a transfer information file is updated.
|
|
|
|
-
|
|
|
|
- The only thing that should change in the transfer info is the
|
|
|
|
- bytesComplete, so that's the only thing updated in the DaemonStatus. -}
|
|
|
|
onModify :: Handler
|
2013-10-03 02:59:07 +00:00
|
|
|
onModify file = case parseTransferFile file of
|
|
|
|
Nothing -> noop
|
|
|
|
Just t -> go t =<< liftIO (readTransferInfoFile Nothing file)
|
2012-10-31 06:34:03 +00:00
|
|
|
where
|
|
|
|
go _ Nothing = noop
|
|
|
|
go t (Just newinfo) = alterTransferInfo t $
|
|
|
|
\i -> i { bytesComplete = bytesComplete newinfo }
|
2012-09-20 21:24:40 +00:00
|
|
|
|
|
|
|
{- This thread can only watch transfer sizes when the DirWatcher supports
|
2023-03-14 02:39:16 +00:00
|
|
|
- tracking modifications to files. -}
|
2012-09-20 21:24:40 +00:00
|
|
|
watchesTransferSize :: Bool
|
|
|
|
watchesTransferSize = modifyTracked
|
|
|
|
|
2012-07-18 23:13:56 +00:00
|
|
|
{- Called when a transfer information file is removed. -}
|
2012-07-03 14:58:40 +00:00
|
|
|
onDel :: Handler
|
2012-10-29 17:09:58 +00:00
|
|
|
onDel file = case parseTransferFile file of
|
2012-07-03 14:58:40 +00:00
|
|
|
Nothing -> noop
|
2012-07-20 23:29:59 +00:00
|
|
|
Just t -> do
|
2012-10-29 17:09:58 +00:00
|
|
|
debug [ "transfer finishing:", show t]
|
2012-10-30 19:39:15 +00:00
|
|
|
minfo <- removeTransfer t
|
2012-10-19 20:59:18 +00:00
|
|
|
|
2013-11-23 21:21:04 +00:00
|
|
|
-- Run transfer hook.
|
2013-11-24 04:26:20 +00:00
|
|
|
m <- transferHook <$> getDaemonStatus
|
|
|
|
maybe noop (\hook -> void $ liftIO $ forkIO $ hook t)
|
|
|
|
(M.lookup (transferKey t) m)
|
2013-11-23 21:21:04 +00:00
|
|
|
|
2012-10-29 17:09:58 +00:00
|
|
|
finished <- asIO2 finishedTransfer
|
|
|
|
void $ liftIO $ forkIO $ do
|
2012-10-19 20:59:18 +00:00
|
|
|
{- XXX race workaround delay. The location
|
2012-12-13 04:45:27 +00:00
|
|
|
- log needs to be updated before finishedTransfer
|
|
|
|
- runs. -}
|
2012-10-19 20:59:18 +00:00
|
|
|
threadDelay 10000000 -- 10 seconds
|
2012-10-29 17:09:58 +00:00
|
|
|
finished t minfo
|