rsync progress interception
Current implementation parses rsync's output a character a time, which is hardly efficient. It could be sped up a lot by using hGetBufSome, but that would require going really lowlevel, down to raw C style buffers (good example of that here: http://users.aber.ac.uk/afc/stricthaskell.html) But rsync doesn't output very much, so currently it seems ok.
This commit is contained in:
parent
aff09a1f33
commit
e1037adebc
2 changed files with 25 additions and 10 deletions
|
@ -245,7 +245,7 @@ copyFromRemote r key file dest
|
||||||
loc <- inRepo $ gitAnnexLocation key
|
loc <- inRepo $ gitAnnexLocation key
|
||||||
upload u key file $
|
upload u key file $
|
||||||
rsyncOrCopyFile params loc dest
|
rsyncOrCopyFile params loc dest
|
||||||
| Git.repoIsSsh r = rsyncHelper =<< rsyncParamsRemote r True key dest file
|
| Git.repoIsSsh r = rsyncHelper Nothing =<< rsyncParamsRemote r True key dest file
|
||||||
| Git.repoIsHttp r = Annex.Content.downloadUrl (keyUrls r key) dest
|
| Git.repoIsHttp r = Annex.Content.downloadUrl (keyUrls r key) dest
|
||||||
| otherwise = error "copying from non-ssh, non-http repo not supported"
|
| otherwise = error "copying from non-ssh, non-http repo not supported"
|
||||||
|
|
||||||
|
@ -280,13 +280,13 @@ copyToRemote r key file p
|
||||||
)
|
)
|
||||||
| Git.repoIsSsh r = commitOnCleanup r $ do
|
| Git.repoIsSsh r = commitOnCleanup r $ do
|
||||||
keysrc <- inRepo $ gitAnnexLocation key
|
keysrc <- inRepo $ gitAnnexLocation key
|
||||||
rsyncHelper =<< rsyncParamsRemote r False key keysrc file
|
rsyncHelper (Just p) =<< rsyncParamsRemote r False key keysrc file
|
||||||
| otherwise = error "copying to non-ssh repo not supported"
|
| otherwise = error "copying to non-ssh repo not supported"
|
||||||
|
|
||||||
rsyncHelper :: [CommandParam] -> Annex Bool
|
rsyncHelper :: Maybe ProgressCallback -> [CommandParam] -> Annex Bool
|
||||||
rsyncHelper p = do
|
rsyncHelper callback params = do
|
||||||
showOutput -- make way for progress bar
|
showOutput -- make way for progress bar
|
||||||
ifM (liftIO $ rsync p)
|
ifM (liftIO $ (maybe rsync rsyncProgress callback) params)
|
||||||
( return True
|
( return True
|
||||||
, do
|
, do
|
||||||
showLongNote "rsync failed -- run git annex again to resume file transfer"
|
showLongNote "rsync failed -- run git annex again to resume file transfer"
|
||||||
|
@ -299,7 +299,7 @@ rsyncOrCopyFile :: [CommandParam] -> FilePath -> FilePath -> ProgressCallback ->
|
||||||
rsyncOrCopyFile rsyncparams src dest p =
|
rsyncOrCopyFile rsyncparams src dest p =
|
||||||
ifM (sameDeviceIds src dest)
|
ifM (sameDeviceIds src dest)
|
||||||
( liftIO $ copyFileExternal src dest
|
( liftIO $ copyFileExternal src dest
|
||||||
, rsyncHelper $ rsyncparams ++ [Param src, Param dest]
|
, rsyncHelper (Just p) $ rsyncparams ++ [Param src, Param dest]
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
sameDeviceIds a b = (==) <$> (getDeviceId a) <*> (getDeviceId b)
|
sameDeviceIds a b = (==) <$> (getDeviceId a) <*> (getDeviceId b)
|
||||||
|
|
|
@ -7,11 +7,8 @@
|
||||||
|
|
||||||
module Utility.Rsync where
|
module Utility.Rsync where
|
||||||
|
|
||||||
import Utility.SafeCommand
|
import Common
|
||||||
import Utility.PartialPrelude
|
|
||||||
|
|
||||||
import Data.String.Utils
|
|
||||||
import Data.List
|
|
||||||
import Data.Char
|
import Data.Char
|
||||||
|
|
||||||
{- Generates parameters to make rsync use a specified command as its remote
|
{- Generates parameters to make rsync use a specified command as its remote
|
||||||
|
@ -49,6 +46,24 @@ rsyncServerParams =
|
||||||
rsync :: [CommandParam] -> IO Bool
|
rsync :: [CommandParam] -> IO Bool
|
||||||
rsync = boolSystem "rsync"
|
rsync = boolSystem "rsync"
|
||||||
|
|
||||||
|
{- Runs rsync, but intercepts its progress output and feeds bytes
|
||||||
|
- complete values into the callback. The progress output is also output
|
||||||
|
- to stdout. -}
|
||||||
|
rsyncProgress :: (Integer -> IO ()) -> [CommandParam] -> IO Bool
|
||||||
|
rsyncProgress callback params = catchBoolIO $
|
||||||
|
withHandle StdoutHandle createProcessSuccess p (feedprogress [])
|
||||||
|
where
|
||||||
|
p = proc "rsync" (toCommand params)
|
||||||
|
feedprogress buf h =
|
||||||
|
catchMaybeIO (hGetChar h) >>= \v -> case v of
|
||||||
|
Just c -> do
|
||||||
|
putChar c
|
||||||
|
hFlush stdout
|
||||||
|
let (mbytes, buf') = parseRsyncProgress (buf++[c])
|
||||||
|
maybe noop callback mbytes
|
||||||
|
feedprogress buf' h
|
||||||
|
Nothing -> return True
|
||||||
|
|
||||||
{- Checks if an rsync url involves the remote shell (ssh or rsh).
|
{- Checks if an rsync url involves the remote shell (ssh or rsh).
|
||||||
- Use of such urls with rsync requires additional shell
|
- Use of such urls with rsync requires additional shell
|
||||||
- escaping. -}
|
- escaping. -}
|
||||||
|
|
Loading…
Reference in a new issue