liftIO $ withCreateProcess p waitproc
waitproc Nothing (Just o) (Just e) pid = do
- output <- fmap fst $
- hGetContentsStrict o
- `concurrently`
- hGetContentsStrict e
+ errt <- async $ discardstderr pid e
+ output <- hGetContentsStrict o
ok <- liftIO $ checkSuccessProcess pid
+ wait errt
return $ case (ok, lines output) of
(True, (f:_)) | not (null f) -> Right f
_ -> nomedia
waitproc _ _ _ _ = error "internal"
+ discardstderr pid e = hGetLineUntilExitOrEOF pid e >>= \case
+ Nothing -> return ()
+ Just _ -> discardstderr pid e
+
nomedia = Left "no media in url"
youtubeDlOpts :: [CommandParam] -> Annex [CommandParam]
where
go _ (Just outh) (Just errh) pid = do
(o1, o2) <- concurrently
- (parseFsckOutput maxobjs r outh)
- (parseFsckOutput maxobjs r errh)
+ (parseFsckOutput maxobjs r outh pid)
+ (parseFsckOutput maxobjs r errh pid)
fsckok <- checkSuccessProcess pid
case mappend o1 o2 of
FsckOutput badobjs truncated
findMissing :: [Sha] -> Repo -> IO MissingObjects
findMissing objs r = S.fromList <$> filterM (`isMissing` r) objs
-parseFsckOutput :: Int -> Repo -> Handle -> IO FsckOutput
-parseFsckOutput maxobjs r h = do
- ls <- lines <$> hGetContents h
+parseFsckOutput :: Int -> Repo -> Handle -> ProcessHandle -> IO FsckOutput
+parseFsckOutput maxobjs r h pid = do
+ ls <- getlines []
if null ls
then return NoFsckOutput
else if all ("duplicateEntries" `isInfixOf`) ls
let !truncated = length shas > maxobjs
missingobjs <- findMissing (take maxobjs shas) r
return $ FsckOutput missingobjs truncated
+ where
+ getlines c = hGetLineUntilExitOrEOF pid h >>= \case
+ Nothing -> return (reverse c)
+ Just l -> getlines (l:c)
isMissing :: Sha -> Repo -> IO Bool
isMissing s r = either (const True) (const False) <$> tryIO dump
-- Work around stupid stdout buffering behavior of python.
-- See https://github.com/warner/magic-wormhole/issues/108
environ <- addEntry "PYTHONUNBUFFERED" "1" <$> getEnvironment
- runWormHoleProcess p { env = Just environ} $ \_hin hout herr -> do
- (inout, inerr) <- findcode hout `concurrently` findcode herr
+ runWormHoleProcess p { env = Just environ} $ \_hin hout herr ph -> do
+ (inout, inerr) <- concurrently
+ (findcode ph hout)
+ (findcode ph herr)
return (inout || inerr)
where
p = wormHoleProcess (Param "send" : ps ++ [File f])
- findcode h = findcode' =<< words <$> hGetContents h
+ findcode ph h = findcode' =<< getwords ph h []
findcode' [] = return False
findcode' (w:ws) = case mkCode w of
Just code -> do
_ <- tryPutMVar observer code
return True
Nothing -> findcode' ws
+ getwords ph h c = hGetLineUntilExitOrEOF ph h >>= \case
+ Nothing -> return $ concatMap words $ reverse c
+ Just l -> getwords ph h (l:c)
-- | Receives a file. Once the receive is under way, the Code will be
-- read from the CodeProducer, and fed to wormhole on stdin.
receiveFile :: FilePath -> CodeProducer -> WormHoleParams -> IO Bool
-receiveFile f (CodeProducer producer) ps = runWormHoleProcess p $ \hin _hout _herr -> do
+receiveFile f (CodeProducer producer) ps = runWormHoleProcess p $ \hin _hout _herr _ph -> do
Code c <- readMVar producer
hPutStrLn hin c
hFlush hin
wormHoleProcess :: WormHoleParams -> CreateProcess
wormHoleProcess = proc "wormhole" . toCommand
-runWormHoleProcess :: CreateProcess -> (Handle -> Handle -> Handle -> IO Bool) -> IO Bool
+runWormHoleProcess :: CreateProcess -> (Handle -> Handle -> Handle -> ProcessHandle -> IO Bool) -> IO Bool
runWormHoleProcess p consumer =
withCreateProcess p' go `catchNonAsync` const (return False)
where
, std_err = CreatePipe
}
go (Just hin) (Just hout) (Just herr) pid =
- consumer hin hout herr <&&> waitbool pid
+ consumer hin hout herr pid <&&> waitbool pid
go _ _ _ _ = error "internal"
waitbool pid = do
r <- waitForProcess pid