2015-04-04 00:08:25 +00:00
|
|
|
{- git-annex progress output
|
|
|
|
-
|
|
|
|
- Copyright 2010-2015 Joey Hess <id@joeyh.name>
|
|
|
|
-
|
|
|
|
- Licensed under the GNU GPL version 3 or higher.
|
|
|
|
-}
|
|
|
|
|
2015-05-12 17:54:16 +00:00
|
|
|
{-# LANGUAGE CPP #-}
|
|
|
|
|
2015-04-03 20:48:30 +00:00
|
|
|
module Messages.Progress where
|
|
|
|
|
|
|
|
import Common
|
|
|
|
import Messages
|
|
|
|
import Messages.Internal
|
|
|
|
import Utility.Metered
|
|
|
|
import Types
|
|
|
|
import Types.Messages
|
|
|
|
import Types.Key
|
|
|
|
|
2015-11-04 17:45:34 +00:00
|
|
|
#ifdef WITH_CONCURRENTOUTPUT
|
|
|
|
import System.Console.Concurrent
|
|
|
|
import System.Console.Regions
|
2015-04-04 19:58:38 +00:00
|
|
|
import Control.Concurrent
|
2015-11-04 17:45:34 +00:00
|
|
|
#endif
|
2015-05-12 17:54:16 +00:00
|
|
|
import Data.Progress.Meter
|
|
|
|
import Data.Progress.Tracker
|
|
|
|
import Data.Quantity
|
2015-04-03 20:48:30 +00:00
|
|
|
|
|
|
|
{- Shows a progress meter while performing a transfer of a key.
|
|
|
|
- The action is passed a callback to use to update the meter. -}
|
2015-04-14 20:35:10 +00:00
|
|
|
metered :: Maybe MeterUpdate -> Key -> AssociatedFile -> (MeterUpdate -> Annex a) -> Annex a
|
|
|
|
metered combinemeterupdate key af a = case keySize key of
|
|
|
|
Nothing -> nometer
|
|
|
|
Just size -> withOutputType (go $ fromInteger size)
|
2015-04-03 20:48:30 +00:00
|
|
|
where
|
2015-04-14 20:35:10 +00:00
|
|
|
go _ QuietOutput = nometer
|
|
|
|
go _ JSONOutput = nometer
|
2015-11-04 17:45:34 +00:00
|
|
|
#if 0
|
2015-04-14 20:35:10 +00:00
|
|
|
go size _ = do
|
2015-04-03 20:48:30 +00:00
|
|
|
showOutput
|
2015-04-04 19:58:38 +00:00
|
|
|
liftIO $ putStrLn ""
|
2015-04-14 20:35:10 +00:00
|
|
|
|
2015-04-14 20:39:30 +00:00
|
|
|
cols <- liftIO $ maybe 79 Terminal.width <$> Terminal.size
|
|
|
|
let desc = truncatepretty cols $ fromMaybe (key2file key) af
|
2015-04-14 20:35:10 +00:00
|
|
|
|
|
|
|
result <- liftIO newEmptyMVar
|
2015-04-04 19:58:38 +00:00
|
|
|
pg <- liftIO $ newProgressBar def
|
2015-04-14 20:39:30 +00:00
|
|
|
{ pgWidth = cols
|
2015-04-14 20:35:10 +00:00
|
|
|
, pgFormat = desc ++ " :percent :bar ETA :eta"
|
|
|
|
, pgTotal = size
|
|
|
|
, pgOnCompletion = do
|
|
|
|
ok <- takeMVar result
|
2015-04-14 20:46:06 +00:00
|
|
|
putStrLn $ desc ++ " " ++ endResult ok
|
2015-04-04 19:58:38 +00:00
|
|
|
}
|
|
|
|
r <- a $ liftIO . pupdate pg
|
|
|
|
|
2015-04-14 20:35:10 +00:00
|
|
|
liftIO $ do
|
|
|
|
-- See if the progress bar is complete or not.
|
|
|
|
sofar <- stCompleted <$> getProgressStats pg
|
|
|
|
putMVar result (sofar >= size)
|
|
|
|
-- May not be actually complete if the action failed,
|
|
|
|
-- but this just clears the progress bar.
|
|
|
|
complete pg
|
2015-04-04 19:58:38 +00:00
|
|
|
|
2015-04-03 20:48:30 +00:00
|
|
|
return r
|
2015-05-12 17:54:16 +00:00
|
|
|
#else
|
2015-11-04 17:45:34 +00:00
|
|
|
-- Old progress bar code, not suitable for concurrent output.
|
2015-11-04 20:19:00 +00:00
|
|
|
go _ (ConcurrentOutput _) = nometer
|
2015-05-12 17:54:16 +00:00
|
|
|
go size NormalOutput = do
|
|
|
|
showOutput
|
|
|
|
progress <- liftIO $ newProgress "" size
|
|
|
|
meter <- liftIO $ newMeter progress "B" 25 (renderNums binaryOpts 1)
|
|
|
|
r <- a $ liftIO . pupdate meter progress
|
|
|
|
liftIO $ clearMeter stdout meter
|
|
|
|
return r
|
|
|
|
#endif
|
2015-04-04 19:58:38 +00:00
|
|
|
|
2015-11-04 17:45:34 +00:00
|
|
|
#if 0
|
2015-04-04 19:58:38 +00:00
|
|
|
pupdate pg n = do
|
|
|
|
let i = fromBytesProcessed n
|
|
|
|
sofar <- stCompleted <$> getProgressStats pg
|
|
|
|
when (i > sofar) $
|
|
|
|
tickN pg (i - sofar)
|
|
|
|
threadDelay 100
|
2015-05-12 17:54:16 +00:00
|
|
|
#else
|
|
|
|
pupdate meter progress n = do
|
|
|
|
setP progress $ fromBytesProcessed n
|
|
|
|
displayMeter stdout meter
|
|
|
|
#endif
|
2015-04-04 19:58:38 +00:00
|
|
|
maybe noop (\m -> m n) combinemeterupdate
|
|
|
|
|
|
|
|
nometer = a (const noop)
|
2015-04-03 20:48:30 +00:00
|
|
|
|
2015-11-04 17:45:34 +00:00
|
|
|
{- Use when the progress meter is only desired for concurrent
|
|
|
|
- output; as when a command's own progress output is preferred. -}
|
|
|
|
concurrentMetered :: Maybe MeterUpdate -> Key -> AssociatedFile -> (MeterUpdate -> Annex a) -> Annex a
|
|
|
|
concurrentMetered combinemeterupdate key af a = withOutputType go
|
2015-04-14 20:35:10 +00:00
|
|
|
where
|
2015-11-04 17:45:34 +00:00
|
|
|
go (ConcurrentOutput _) = metered combinemeterupdate key af a
|
2015-04-14 20:35:10 +00:00
|
|
|
go _ = a (fromMaybe (const noop) combinemeterupdate)
|
|
|
|
|
2015-04-03 20:48:30 +00:00
|
|
|
{- Progress dots. -}
|
|
|
|
showProgressDots :: Annex ()
|
2015-11-04 17:45:34 +00:00
|
|
|
showProgressDots = outputMessage q "."
|
2015-04-03 20:48:30 +00:00
|
|
|
|
2015-04-04 18:34:03 +00:00
|
|
|
{- Runs a command, that may output progress to either stdout or
|
|
|
|
- stderr, as well as other messages.
|
2015-04-04 00:38:56 +00:00
|
|
|
-
|
2015-04-04 18:34:03 +00:00
|
|
|
- In quiet mode, the output is suppressed, except for error messages.
|
2015-04-04 00:38:56 +00:00
|
|
|
-}
|
2015-04-04 18:34:03 +00:00
|
|
|
progressCommand :: FilePath -> [CommandParam] -> Annex Bool
|
|
|
|
progressCommand cmd params = progressCommandEnv cmd params Nothing
|
2015-04-04 00:38:56 +00:00
|
|
|
|
2015-04-04 18:34:03 +00:00
|
|
|
progressCommandEnv :: FilePath -> [CommandParam] -> Maybe [(String, String)] -> Annex Bool
|
|
|
|
progressCommandEnv cmd params environ = ifM commandProgressDisabled
|
|
|
|
( do
|
|
|
|
oh <- mkOutputHandler
|
|
|
|
liftIO $ demeterCommandEnv oh cmd params environ
|
|
|
|
, liftIO $ boolSystemEnv cmd params environ
|
|
|
|
)
|
2015-04-03 20:48:30 +00:00
|
|
|
|
2015-04-04 18:34:03 +00:00
|
|
|
mkOutputHandler :: Annex OutputHandler
|
|
|
|
mkOutputHandler = OutputHandler
|
|
|
|
<$> commandProgressDisabled
|
|
|
|
<*> mkStderrEmitter
|
2015-04-04 00:38:56 +00:00
|
|
|
|
2015-04-04 18:53:17 +00:00
|
|
|
mkStderrRelayer :: Annex (Handle -> IO ())
|
|
|
|
mkStderrRelayer = do
|
|
|
|
quiet <- commandProgressDisabled
|
|
|
|
emitter <- mkStderrEmitter
|
|
|
|
return $ \h -> avoidProgress quiet h emitter
|
|
|
|
|
2015-04-03 20:48:30 +00:00
|
|
|
{- Generates an IO action that can be used to emit stderr.
|
|
|
|
-
|
|
|
|
- When a progress meter is displayed, this takes care to avoid
|
|
|
|
- messing it up with interleaved stderr from a command.
|
|
|
|
-}
|
|
|
|
mkStderrEmitter :: Annex (String -> IO ())
|
|
|
|
mkStderrEmitter = withOutputType go
|
|
|
|
where
|
2015-11-04 17:45:34 +00:00
|
|
|
#ifdef WITH_CONCURRENTOUTPUT
|
|
|
|
go (ConcurrentOutput _) = return errorConcurrent
|
|
|
|
#endif
|
2015-04-03 20:48:30 +00:00
|
|
|
go _ = return (hPutStrLn stderr)
|