addurl, get: Added --json-progress option, which adds progress objects to the json output.

This doesn't work right when used with -J yet, and there is some really
ugly hand-crafting of part of the json output.
This commit is contained in:
Joey Hess 2016-09-09 15:06:54 -04:00
parent f421a7f001
commit 05d4438383
No known key found for this signature in database
GPG key ID: C910D9222512E3C7
12 changed files with 55 additions and 12 deletions

View file

@ -6,6 +6,8 @@ git-annex (6.20160908) UNRELEASED; urgency=medium
over ssh etc. over ssh etc.
* Make --json and --quiet work when used with -J. * Make --json and --quiet work when used with -J.
Previously, -J override the other options. Previously, -J override the other options.
* addurl, get: Added --json-progress option, which adds progress
objects to the json output.
* Remove key:null from git-annex add --json output. * Remove key:null from git-annex add --json output.
-- Joey Hess <id@joeyh.name> Thu, 08 Sep 2016 12:48:55 -0400 -- Joey Hess <id@joeyh.name> Thu, 08 Sep 2016 12:48:55 -0400

View file

@ -286,12 +286,19 @@ combiningOptions =
shortopt o h = globalFlag (Limit.addToken [o]) ( short o <> help h <> hidden ) shortopt o h = globalFlag (Limit.addToken [o]) ( short o <> help h <> hidden )
jsonOption :: GlobalOption jsonOption :: GlobalOption
jsonOption = globalFlag (Annex.setOutput JSONOutput) jsonOption = globalFlag (Annex.setOutput (JSONOutput False))
( long "json" <> short 'j' ( long "json" <> short 'j'
<> help "enable JSON output" <> help "enable JSON output"
<> hidden <> hidden
) )
jsonProgressOption :: GlobalOption
jsonProgressOption = globalFlag (Annex.setOutput (JSONOutput True))
( long "json-progress" <> short 'j'
<> help "include progress in JSON output"
<> hidden
)
-- Note that a command that adds this option should wrap its seek -- Note that a command that adds this option should wrap its seek
-- action in `allowConcurrentOutput`. -- action in `allowConcurrentOutput`.
jobsOption :: GlobalOption jobsOption :: GlobalOption

View file

@ -31,7 +31,7 @@ import Annex.Quvi
import qualified Utility.Quvi as Quvi import qualified Utility.Quvi as Quvi
cmd :: Command cmd :: Command
cmd = notBareRepo $ withGlobalOptions [jobsOption, jsonOption] $ cmd = notBareRepo $ withGlobalOptions [jobsOption, jsonOption, jsonProgressOption] $
command "addurl" SectionCommon "add urls to annex" command "addurl" SectionCommon "add urls to annex"
(paramRepeating paramUrl) (seek <$$> optParser) (paramRepeating paramUrl) (seek <$$> optParser)

View file

@ -16,7 +16,7 @@ import Annex.Wanted
import qualified Command.Move import qualified Command.Move
cmd :: Command cmd :: Command
cmd = withGlobalOptions (jobsOption : jsonOption : annexedMatchingOptions) $ cmd = withGlobalOptions (jobsOption : jsonOption : jsonProgressOption : annexedMatchingOptions) $
command "get" SectionCommon command "get" SectionCommon
"make content of annexed files available" "make content of annexed files available"
paramPaths (seek <$$> optParser) paramPaths (seek <$$> optParser)

View file

@ -79,7 +79,7 @@ seek o = do
(seeker $ whenAnnexed $ start now o) (seeker $ whenAnnexed $ start now o)
(forFiles o) (forFiles o)
Batch -> withMessageState $ \s -> case outputType s of Batch -> withMessageState $ \s -> case outputType s of
JSONOutput -> batchInput parseJSONInput $ JSONOutput _ -> batchInput parseJSONInput $
commandAction . startBatch now commandAction . startBatch now
_ -> error "--batch is currently only supported in --json mode" _ -> error "--batch is currently only supported in --json mode"

View file

@ -213,7 +213,7 @@ commandProgressDisabled :: Annex Bool
commandProgressDisabled = withMessageState $ \s -> return $ commandProgressDisabled = withMessageState $ \s -> return $
case outputType s of case outputType s of
QuietOutput -> True QuietOutput -> True
JSONOutput -> True JSONOutput _ -> True
NormalOutput -> concurrentOutputEnabled s NormalOutput -> concurrentOutputEnabled s
{- Use to show a message that is displayed implicitly, and so might be {- Use to show a message that is displayed implicitly, and so might be

View file

@ -26,20 +26,20 @@ outputMessage' endmessage json msg = withMessageState $ \s -> case outputType s
NormalOutput NormalOutput
| concurrentOutputEnabled s -> concurrentMessage s False msg q | concurrentOutputEnabled s -> concurrentMessage s False msg q
| otherwise -> liftIO $ flushed $ putStr msg | otherwise -> liftIO $ flushed $ putStr msg
JSONOutput -> void $ outputJSON json endmessage s JSONOutput _ -> void $ outputJSON json endmessage s
QuietOutput -> q QuietOutput -> q
outputJSON :: IO () -> Bool -> MessageState -> Annex Bool outputJSON :: IO () -> Bool -> MessageState -> Annex Bool
outputJSON json endmessage s = case outputType s of outputJSON json endmessage s = case outputType s of
JSONOutput JSONOutput withprogress
| concurrentOutputEnabled s -> do | withprogress || concurrentOutputEnabled s -> do
-- Buffer json fragments until end is reached. -- Buffer json fragments until end is reached.
if endmessage if endmessage
then do then do
Annex.changeState $ \st -> Annex.changeState $ \st ->
st { Annex.output = s { jsonBuffer = [] } } st { Annex.output = s { jsonBuffer = [] } }
liftIO $ flushed $ do liftIO $ flushed $ do
sequence_ $ reverse $ jsonBuffer s showJSONBuffer s
json json
else Annex.changeState $ \st -> else Annex.changeState $ \st ->
st { Annex.output = s { jsonBuffer = json : jsonBuffer s } } st { Annex.output = s { jsonBuffer = json : jsonBuffer s } }
@ -49,6 +49,9 @@ outputJSON json endmessage s = case outputType s of
return True return True
_ -> return False _ -> return False
showJSONBuffer :: MessageState -> IO ()
showJSONBuffer s = sequence_ $ reverse $ jsonBuffer s
outputError :: String -> Annex () outputError :: String -> Annex ()
outputError msg = withMessageState $ \s -> outputError msg = withMessageState $ \s ->
if concurrentOutputEnabled s if concurrentOutputEnabled s

View file

@ -13,6 +13,7 @@ module Messages.JSON (
note, note,
add, add,
complete, complete,
progress,
DualDisp(..), DualDisp(..),
ObjectMap(..), ObjectMap(..),
JSONActionItem(..), JSONActionItem(..),
@ -30,6 +31,8 @@ import Prelude
import qualified Utility.JSONStream as Stream import qualified Utility.JSONStream as Stream
import Types.Key import Types.Key
import Utility.Metered
import Utility.Percentage
start :: String -> Maybe FilePath -> Maybe Key -> IO () start :: String -> Maybe FilePath -> Maybe Key -> IO ()
start command file key = B.hPut stdout $ Stream.start $ Stream.AesonObject o start command file key = B.hPut stdout $ Stream.start $ Stream.AesonObject o
@ -53,6 +56,20 @@ add = B.hPut stdout . Stream.add
complete :: Stream.JSONChunk a -> IO () complete :: Stream.JSONChunk a -> IO ()
complete v = B.hPut stdout $ Stream.start v `B.append` Stream.end complete v = B.hPut stdout $ Stream.start v `B.append` Stream.end
progress :: IO () -> Integer -> BytesProcessed -> IO ()
progress jsonbuffer size bytesprocessed = do
B.hPut stdout $ Stream.start $ Stream.AesonObject o
putStr ",\"action\":"
jsonbuffer
B.hPut stdout $ Stream.end
B.hPut stdout $ Stream.end
where
n = fromBytesProcessed bytesprocessed :: Integer
Object o = object
[ "byte-progress" .= n
, "percent-progress" .= showPercentage 2 (percentage size n)
]
-- A value that can be displayed either normally, or as JSON. -- A value that can be displayed either normally, or as JSON.
data DualDisp = DualDisp data DualDisp = DualDisp
{ dispNormal :: String { dispNormal :: String

View file

@ -16,6 +16,7 @@ import Utility.Metered
import Types import Types
import Types.Messages import Types.Messages
import Types.Key import Types.Key
import qualified Messages.JSON as JSON
#ifdef WITH_CONCURRENTOUTPUT #ifdef WITH_CONCURRENTOUTPUT
import Messages.Concurrent import Messages.Concurrent
@ -35,7 +36,6 @@ metered othermeter key a = case keySize key of
Just size -> withMessageState (go $ fromInteger size) Just size -> withMessageState (go $ fromInteger size)
where where
go _ (MessageState { outputType = QuietOutput }) = nometer go _ (MessageState { outputType = QuietOutput }) = nometer
go _ (MessageState { outputType = JSONOutput }) = nometer
go size (MessageState { outputType = NormalOutput, concurrentOutputEnabled = False }) = do go size (MessageState { outputType = NormalOutput, concurrentOutputEnabled = False }) = do
showOutput showOutput
(progress, meter) <- mkmeter size (progress, meter) <- mkmeter size
@ -57,6 +57,12 @@ metered othermeter key a = case keySize key of
#else #else
nometer nometer
#endif #endif
go _ (MessageState { outputType = JSONOutput False }) = nometer
go size (MessageState { outputType = JSONOutput True }) = do
buf <- withMessageState $ return . showJSONBuffer
m <- liftIO $ rateLimitMeterUpdate 0.1 (Just size) $
JSON.progress buf size
a (combinemeter m)
mkmeter size = do mkmeter size = do
progress <- liftIO $ newProgress "" size progress <- liftIO $ newProgress "" size

View file

@ -15,7 +15,7 @@ import Data.Default
import System.Console.Regions (ConsoleRegion) import System.Console.Regions (ConsoleRegion)
#endif #endif
data OutputType = NormalOutput | QuietOutput | JSONOutput data OutputType = NormalOutput | QuietOutput | JSONOutput Bool
deriving (Show) deriving (Show)
data SideActionBlock = NoBlock | StartBlock | InBlock data SideActionBlock = NoBlock | StartBlock | InBlock

View file

@ -88,6 +88,10 @@ be used to get better filenames.
Enable JSON output. This is intended to be parsed by programs that use Enable JSON output. This is intended to be parsed by programs that use
git-annex. Each line of output is a JSON object. git-annex. Each line of output is a JSON object.
* `--json-progress`
Include progress objects in JSON output.
# CAVEATS # CAVEATS
If annex.largefiles is configured, and does not match a file, `git annex If annex.largefiles is configured, and does not match a file, `git annex

View file

@ -86,7 +86,7 @@ or transferring them from some kind of key-value store.
displayed. If the specified file's content is already present, or displayed. If the specified file's content is already present, or
it is not an annexed file, a blank line is output in response instead. it is not an annexed file, a blank line is output in response instead.
Since the usual progress output while getting a file is verbose and not Since the usual output while getting a file is verbose and not
machine-parseable, you may want to use --json in combination with machine-parseable, you may want to use --json in combination with
--batch. --batch.
@ -95,6 +95,10 @@ or transferring them from some kind of key-value store.
Enable JSON output. This is intended to be parsed by programs that use Enable JSON output. This is intended to be parsed by programs that use
git-annex. Each line of output is a JSON object. git-annex. Each line of output is a JSON object.
* `--json-progress`
Include progress objects in JSON output.
# SEE ALSO # SEE ALSO
[[git-annex]](1) [[git-annex]](1)