aboutsummaryrefslogtreecommitdiff
path: root/Messages
diff options
context:
space:
mode:
authorGravatar Joey Hess <joeyh@joeyh.name>2015-11-05 17:22:45 -0400
committerGravatar Joey Hess <joeyh@joeyh.name>2015-11-05 17:23:26 -0400
commite0d5901349c15b3eeace319cbe8854e655a602d6 (patch)
treeda3346ca3aeb17f283fd2e814b2e3faa470dd8aa /Messages
parent021c06e8998a365c95db2f362d37bdf00f61ea01 (diff)
join back threads before ending concurrent output so display works
I didn't really want to put allowConcurrentOutput in CmdLine.Action, but there were dep loops and that was the best place available.
Diffstat (limited to 'Messages')
-rw-r--r--Messages/Concurrent.hs96
-rw-r--r--Messages/Internal.hs90
2 files changed, 97 insertions, 89 deletions
diff --git a/Messages/Concurrent.hs b/Messages/Concurrent.hs
new file mode 100644
index 000000000..bb949af03
--- /dev/null
+++ b/Messages/Concurrent.hs
@@ -0,0 +1,96 @@
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+
+{- git-annex output messages, including concurrent output to display regions
+ -
+ - Copyright 2010-2015 Joey Hess <id@joeyh.name>
+ -
+ - Licensed under the GNU GPL version 3 or higher.
+ -}
+
+{-# LANGUAGE CPP #-}
+
+module Messages.Concurrent where
+
+import Common
+import Annex
+import Types.Messages
+
+#ifdef WITH_CONCURRENTOUTPUT
+import qualified System.Console.Concurrent as Console
+import qualified System.Console.Regions as Regions
+import Control.Concurrent.STM
+import qualified Data.Text as T
+#endif
+
+{- Outputs a message in a concurrency safe way.
+ -
+ - The message may be an error message, in which case it goes to stderr.
+ -
+ - When built without concurrent-output support, the fallback action is run
+ - instead.
+ -}
+concurrentMessage :: Bool -> String -> Annex () -> Annex ()
+#ifdef WITH_CONCURRENTOUTPUT
+concurrentMessage iserror msg _ = go =<< consoleRegion <$> Annex.getState Annex.output
+ where
+ go Nothing
+ | iserror = liftIO $ Console.errorConcurrent msg
+ | otherwise = liftIO $ Console.outputConcurrent msg
+ go (Just r) = do
+ -- Can't display the error to stdout while
+ -- console regions are in use, so set the errflag
+ -- to get it to display to stderr later.
+ when iserror $ do
+ Annex.changeState $ \s ->
+ s { Annex.output = (Annex.output s) { consoleRegionErrFlag = True } }
+ liftIO $ Regions.appendConsoleRegion r msg
+#else
+concurrentMessage _ _ fallback = fallback
+#endif
+
+{- Runs an action in its own dedicated region of the console.
+ -
+ - The region is closed at the end or on exception, and at that point
+ - the value of the region is displayed in the scrolling area above
+ - any other active regions.
+ -
+ - When not at a console, a region is not displayed until the action is
+ - complete.
+ -}
+inOwnConsoleRegion :: Annex a -> Annex a
+#ifdef WITH_CONCURRENTOUTPUT
+inOwnConsoleRegion a = do
+ r <- mkregion
+ setregion (Just r)
+ eret <- tryNonAsync a `onException` rmregion r
+ case eret of
+ Left e -> do
+ -- Add error message to region before it closes.
+ concurrentMessage True (show e) noop
+ rmregion r
+ throwM e
+ Right ret -> do
+ rmregion r
+ return ret
+ where
+ mkregion = Regions.openConsoleRegion Regions.Linear
+ setregion r = Annex.changeState $ \s -> s { Annex.output = (Annex.output s) { consoleRegion = r } }
+ rmregion r = do
+ errflag <- consoleRegionErrFlag <$> Annex.getState Annex.output
+ let h = if errflag then Console.StdErr else Console.StdOut
+ Annex.changeState $ \s ->
+ s { Annex.output = (Annex.output s) { consoleRegionErrFlag = False } }
+ setregion Nothing
+ liftIO $ atomically $ do
+ t <- Regions.getConsoleRegion r
+ unless (T.null t) $
+ Console.bufferOutputSTM h t
+ Regions.closeConsoleRegion r
+#else
+inOwnConsoleRegion = id
+#endif
+
+#ifdef WITH_CONCURRENTOUTPUT
+instance Regions.LiftRegion Annex where
+ liftRegion = liftIO . atomically
+#endif
diff --git a/Messages/Internal.hs b/Messages/Internal.hs
index 168846205..fcbbe10b4 100644
--- a/Messages/Internal.hs
+++ b/Messages/Internal.hs
@@ -1,5 +1,3 @@
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-
{- git-annex output messages, including concurrent output to display regions
-
- Copyright 2010-2015 Joey Hess <id@joeyh.name>
@@ -7,20 +5,12 @@
- Licensed under the GNU GPL version 3 or higher.
-}
-{-# LANGUAGE CPP #-}
-
module Messages.Internal where
import Common
import Annex
import Types.Messages
-
-#ifdef WITH_CONCURRENTOUTPUT
-import qualified System.Console.Concurrent as Console
-import qualified System.Console.Regions as Regions
-import Control.Concurrent.STM
-import qualified Data.Text as T
-#endif
+import Messages.Concurrent
withOutputType :: (OutputType -> Annex a) -> Annex a
withOutputType a = outputType <$> Annex.getState Annex.output >>= a
@@ -48,81 +38,3 @@ q = noop
flushed :: IO () -> IO ()
flushed a = a >> hFlush stdout
-
-{- Outputs a message in a concurrency safe way.
- -
- - The message may be an error message, in which case it goes to stderr.
- -
- - When built without concurrent-output support, the fallback action is run
- - instead.
- -}
-concurrentMessage :: Bool -> String -> Annex () -> Annex ()
-#ifdef WITH_CONCURRENTOUTPUT
-concurrentMessage iserror msg _ = go =<< consoleRegion <$> Annex.getState Annex.output
- where
- go Nothing
- | iserror = liftIO $ Console.errorConcurrent msg
- | otherwise = liftIO $ Console.outputConcurrent msg
- go (Just r) = do
- -- Can't display the error to stdout while
- -- console regions are in use, so set the errflag
- -- to get it to display to stderr later.
- when iserror $ do
- Annex.changeState $ \s ->
- s { Annex.output = (Annex.output s) { consoleRegionErrFlag = True } }
- liftIO $ Regions.appendConsoleRegion r msg
-#else
-concurrentMessage _ _ fallback = fallback
-#endif
-
-{- Do concurrent output when that has been requested. -}
-allowConcurrentOutput :: Annex a -> Annex a
-#ifdef WITH_CONCURRENTOUTPUT
-allowConcurrentOutput a = go =<< Annex.getState Annex.concurrentjobs
- where
- go (Just n) = Regions.displayConsoleRegions $ bracket_
- (Annex.setOutput (ConcurrentOutput n))
- (Annex.setOutput NormalOutput)
- a
- go Nothing = a
-#else
-allowConcurrentOutput = id
-#endif
-
-{- Runs an action in its own dedicated region of the console.
- -
- - The region is closed at the end or on exception, and at that point
- - the value of the region is displayed in the scrolling area above
- - any other active regions.
- -
- - When not at a console, a region is not displayed until the action is
- - complete.
- -}
-inOwnConsoleRegion :: Annex a -> Annex a
-#ifdef WITH_CONCURRENTOUTPUT
-inOwnConsoleRegion a = bracket mkregion rmregion go
- where
- go r = do
- setregion (Just r)
- a
- mkregion = Regions.openConsoleRegion Regions.Linear
- rmregion r = do
- errflag <- consoleRegionErrFlag <$> Annex.getState Annex.output
- let h = if errflag then Console.StdErr else Console.StdOut
- Annex.changeState $ \s ->
- s { Annex.output = (Annex.output s) { consoleRegionErrFlag = False } }
- setregion Nothing
- liftIO $ atomically $ do
- t <- Regions.getConsoleRegion r
- unless (T.null t) $
- Console.bufferOutputSTM h t
- Regions.closeConsoleRegion r
- setregion r = Annex.changeState $ \s -> s { Annex.output = (Annex.output s) { consoleRegion = r } }
-#else
-inOwnConsoleRegion = id
-#endif
-
-#ifdef WITH_CONCURRENTOUTPUT
-instance Regions.LiftRegion Annex where
- liftRegion = liftIO . atomically
-#endif