commandProgressDisabled :: Annex Bool
commandProgressDisabled = withMessageState $ \s -> return $
case outputType s of
+ NormalOutput -> concurrentOutputEnabled s
QuietOutput -> True
JSONOutput _ -> True
- NormalOutput -> concurrentOutputEnabled s
+ SerializedOutput -> True
jsonOutputEnabled :: Annex Bool
jsonOutputEnabled = withMessageState $ \s -> return $
{- git-annex output messages, including concurrent output to display regions
-
- - Copyright 2010-2018 Joey Hess <id@joeyh.name>
+ - Copyright 2010-2020 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
| otherwise -> liftIO $ flushed $ S.putStr msg
JSONOutput _ -> void $ jsonoutputter jsonbuilder s
QuietOutput -> q
+ SerializedOutput -> liftIO $ outputSerialized $ OutputMessage (decodeBS' msg)
-- Buffer changes to JSON until end is reached and then emit it.
bufferJSON :: JSONBuilder -> MessageState -> Annex Bool
let jb' = Just (JSON.addErrorMessage (lines msg) jb)
in Annex.changeState $ \st ->
st { Annex.output = s { jsonBuffer = jb' } }
+ (SerializedOutput, _) ->
+ liftIO $ outputSerialized $ OutputError msg
_
| concurrentOutputEnabled s -> concurrentMessage s True msg go
| otherwise -> go
flushed :: IO () -> IO ()
flushed a = a >> hFlush stdout
+
+outputSerialized :: SerializedOutput -> IO ()
+outputSerialized = print
{- git-annex progress output
-
- - Copyright 2010-2019 Joey Hess <id@joeyh.name>
+ - Copyright 2010-2020 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
import Utility.InodeCache
import qualified Messages.JSON as JSON
import Messages.Concurrent
+import Messages.Internal
import qualified System.Console.Regions as Regions
import qualified System.Console.Concurrent as Console
showOutput
meter <- liftIO $ mkMeter msize $
displayMeterHandle stdout bandwidthMeter
- m <- liftIO $ rateLimitMeterUpdate 0.2 meter $
+ m <- liftIO $ rateLimitMeterUpdate consoleratelimit meter $
updateMeter meter
r <- a meter (combinemeter m)
liftIO $ clearMeterHandle meter stdout
meter <- liftIO $ mkMeter msize $ \_ msize' old new ->
let s = bandwidthMeter msize' old new
in Regions.setConsoleRegion r ('\n' : s)
- m <- liftIO $ rateLimitMeterUpdate 0.2 meter $
+ m <- liftIO $ rateLimitMeterUpdate consoleratelimit meter $
updateMeter meter
a meter (combinemeter m)
go msize (MessageState { outputType = JSONOutput jsonoptions })
| jsonProgress jsonoptions = do
buf <- withMessageState $ return . jsonBuffer
- meter <- liftIO $ mkMeter msize $ \_ msize' _old (new, _now) ->
- JSON.progress buf msize' new
- m <- liftIO $ rateLimitMeterUpdate 0.1 meter $
+ meter <- liftIO $ mkMeter msize $ \_ msize' _old new ->
+ JSON.progress buf msize' (meterBytesProcessed new)
+ m <- liftIO $ rateLimitMeterUpdate jsonratelimit meter $
updateMeter meter
a meter (combinemeter m)
| otherwise = nometer
-
+ go msize (MessageState { outputType = SerializedOutput }) = do
+ meter <- liftIO $ mkMeter msize $ \_ msize' old new ->
+ outputSerialized $ ProgressMeter msize' old new
+ m <- liftIO $ rateLimitMeterUpdate minratelimit meter $
+ updateMeter meter
+ a meter (combinemeter m)
nometer = do
dummymeter <- liftIO $ mkMeter Nothing $
\_ _ _ _ -> return ()
Nothing -> m
Just om -> combineMeterUpdate m om
+ consoleratelimit = 0.2
+
+ jsonratelimit = 0.1
+
+ minratelimit = min consoleratelimit jsonratelimit
+
{- Poll file size to display meter. -}
meteredFile :: FilePath -> Maybe MeterUpdate -> Key -> Annex a -> Annex a
meteredFile file combinemeterupdate key a =
{- git-annex Messages data types
-
- - Copyright 2012-2018 Joey Hess <id@joeyh.name>
+ - Copyright 2012-2020 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
module Types.Messages where
import qualified Utility.Aeson as Aeson
+import Utility.Metered
import Control.Concurrent
import System.Console.Regions (ConsoleRegion)
-data OutputType = NormalOutput | QuietOutput | JSONOutput JSONOptions
+data OutputType
+ = NormalOutput
+ | QuietOutput
+ | JSONOutput JSONOptions
+ | SerializedOutput
deriving (Show)
data JSONOptions = JSONOptions
, jsonBuffer = Nothing
, promptLock = promptlock
}
+
+data SerializedOutput
+ = OutputMessage String
+ | OutputError String
+ | ProgressMeter (Maybe Integer) MeterState MeterState
+ deriving (Show, Read)
module Utility.Metered (
MeterUpdate,
+ MeterState(..),
nullMeterUpdate,
combineMeterUpdate,
TotalSize(..),
{- Total number of bytes processed so far. -}
newtype BytesProcessed = BytesProcessed Integer
- deriving (Eq, Ord, Show)
+ deriving (Eq, Ord, Show, Read)
class AsBytesProcessed a where
toBytesProcessed :: a -> BytesProcessed
data Meter = Meter (MVar (Maybe Integer)) (MVar MeterState) (MVar String) DisplayMeter
-type MeterState = (BytesProcessed, POSIXTime)
+data MeterState = MeterState
+ { meterBytesProcessed :: BytesProcessed
+ , meterTimeStamp :: Double
+ } deriving (Show, Read)
-type DisplayMeter = MVar String -> Maybe Integer -> (BytesProcessed, POSIXTime) -> (BytesProcessed, POSIXTime) -> IO ()
+type DisplayMeter = MVar String -> Maybe Integer -> MeterState -> MeterState -> IO ()
-type RenderMeter = Maybe Integer -> (BytesProcessed, POSIXTime) -> (BytesProcessed, POSIXTime) -> String
+type RenderMeter = Maybe Integer -> MeterState -> MeterState -> String
-- | Make a meter. Pass the total size, if it's known.
mkMeter :: Maybe Integer -> DisplayMeter -> IO Meter
-mkMeter totalsize displaymeter = Meter
- <$> newMVar totalsize
- <*> ((\t -> newMVar (zeroBytesProcessed, t)) =<< getPOSIXTime)
- <*> newMVar ""
- <*> pure displaymeter
+mkMeter totalsize displaymeter = do
+ ts <- realToFrac <$> getPOSIXTime
+ Meter
+ <$> newMVar totalsize
+ <*> newMVar (MeterState zeroBytesProcessed ts)
+ <*> newMVar ""
+ <*> pure displaymeter
setMeterTotalSize :: Meter -> Integer -> IO ()
setMeterTotalSize (Meter totalsizev _ _ _) = void . swapMVar totalsizev . Just
-- | Updates the meter, displaying it if necessary.
updateMeter :: Meter -> MeterUpdate
updateMeter (Meter totalsizev sv bv displaymeter) new = do
- now <- getPOSIXTime
- (old, before) <- swapMVar sv (new, now)
- when (old /= new) $ do
+ now <- realToFrac <$> getPOSIXTime
+ let curms = MeterState new now
+ oldms <- swapMVar sv curms
+ when (meterBytesProcessed oldms /= new) $ do
totalsize <- readMVar totalsizev
- displaymeter bv totalsize (old, before) (new, now)
+ displaymeter bv totalsize oldms curms
-- | Display meter to a Handle.
displayMeterHandle :: Handle -> RenderMeter -> DisplayMeter
-- or when total size is not known:
-- 1.3 MiB 300 KiB/s
bandwidthMeter :: RenderMeter
-bandwidthMeter mtotalsize (BytesProcessed old, before) (BytesProcessed new, now) =
+bandwidthMeter mtotalsize (MeterState (BytesProcessed old) before) (MeterState (BytesProcessed new) now) =
unwords $ catMaybes
[ Just percentamount
-- Pad enough for max width: "100% xxxx.xx KiB xxxx KiB/s"