Skip to content

Commit 31afb68

Browse files
committed
Use typed-process
1 parent 7f2467a commit 31afb68

File tree

4 files changed

+147
-154
lines changed

4 files changed

+147
-154
lines changed

src/Database/Postgres/Temp/Internal.hs

+39-22
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ import Control.Exception
1616
import Control.Monad (void, join)
1717
import Control.Monad.Trans.Cont
1818
import Data.ByteString (ByteString)
19+
import qualified Data.ByteString.Lazy.Char8 as LBSC
20+
import qualified Data.ByteString.Lazy as LBS
1921
import qualified Data.Map.Strict as Map
2022
import qualified Database.PostgreSQL.Simple.Options as Client
2123
import GHC.Generics
2224
import Prettyprinter
23-
import System.Exit (ExitCode(..))
2425
import System.IO.Unsafe (unsafePerformIO)
25-
import System.Process
26+
import System.Process.Typed
2627
import System.Directory
2728

2829
-- | Handle for holding temporary resources, the @postgres@ process handle
@@ -381,6 +382,20 @@ stopPostgres = stopPlan . dbPostgresProcess
381382
stopPostgresGracefully :: DB -> IO ExitCode
382383
stopPostgresGracefully = stopPostgresProcess True . dbPostgresProcess
383384

385+
stopPostgresGracefullyOrThrow :: DB -> IO ()
386+
stopPostgresGracefullyOrThrow db = do
387+
let postgresProcess = dbPostgresProcess db
388+
exitCode <- stopPostgresProcess True postgresProcess
389+
case exitCode of
390+
ExitSuccess -> pure ()
391+
ExitFailure _ ->
392+
throwIO $ ExitCodeException
393+
{ eceExitCode = exitCode
394+
, eceProcessConfig = postgresProcessConfig postgresProcess
395+
, eceStdout = LBS.empty
396+
, eceStderr = LBS.empty
397+
}
398+
384399
-- | Restart the @postgres@ from 'DB' using the prior 'Config'. This
385400
-- will also start an instance previously stoppped with 'stopPostgres'.
386401
--
@@ -498,22 +513,25 @@ cowCheck = unsafePerformIO $ do
498513
#else
499514
cpFlag = "--reflink=auto"
500515
#endif
501-
(_, _, errorOutput)<- readProcessWithExitCode "cp" [cpFlag] ""
516+
(_exitCode, stderr) <- readProcessStderr $ proc "cp" [cpFlag]
502517
-- if the flags do not exist we get a message like "cp: illegal option"
503518
let usage = "usage:" -- macos
504519
missingFile = "cp: missing file operand" -- linux
505-
pure $ usage == take (length usage) errorOutput
506-
|| missingFile == take (length missingFile) errorOutput
520+
stderrString = LBSC.unpack stderr
521+
pure $ usage == take (length usage) stderrString
522+
|| missingFile == take (length missingFile) stderrString
507523
{-# NOINLINE cowCheck #-}
508524

509-
cpFlags :: String
510-
cpFlags = if cowCheck
525+
cpFlags :: [String]
526+
cpFlags =
527+
["-R"]
528+
++ if cowCheck
511529
#ifdef darwin_HOST_OS
512-
then "cp -Rc "
530+
then ["-c"]
513531
#else
514-
then "cp -R --reflink=auto "
532+
then ["--reflink=auto"]
515533
#endif
516-
else "cp -R "
534+
else []
517535

518536
{-|
519537
'defaultCacheConfig' attempts to determine if the @cp@ on the path
@@ -628,20 +646,19 @@ takeSnapshot
628646
-- ^ The handle. The @postgres@ is shutdown and the data directory is copied.
629647
-> IO (Either StartError Snapshot)
630648
takeSnapshot db = try $ do
631-
throwIfNotSuccess id =<< stopPostgresGracefully db
649+
stopPostgresGracefullyOrThrow db
632650
bracketOnError
633651
(setupDirectoryType
634652
(toTemporaryDirectory db)
635653
"tmp-postgres-snapshot"
636654
Temporary
637655
)
638656
cleanupDirectoryType $ \snapShotDir -> do
639-
let snapshotCopyCmd = cpFlags <>
640-
toDataDirectory db <> "/* " <> toFilePath snapShotDir
641-
throwIfNotSuccess (SnapshotCopyFailed snapshotCopyCmd) =<<
642-
system snapshotCopyCmd
657+
let snapshotCopyFlags = cpFlags ++ [toDataDirectory db, toFilePath snapShotDir]
658+
snapshotCopyCmd = proc "cp" snapshotCopyFlags
643659

644-
pure $ Snapshot snapShotDir
660+
(readProcess_ snapshotCopyCmd >> (pure $ Snapshot snapShotDir))
661+
`catch` (throwIO . SnapshotCopyFailed)
645662

646663
{-|
647664
Cleanup any temporary resources used for the snapshot.
@@ -769,11 +786,11 @@ cacheAction cachePath action config = do
769786
if nonEmpty then pure $ pure result else fmap join $ withConfig config $ \db -> do
770787
action db
771788
-- TODO see if parallel is better
772-
throwIfNotSuccess id =<< stopPostgresGracefully db
789+
stopPostgresGracefullyOrThrow db
773790
createDirectoryIfMissing True fixCachePath
774791

775-
let snapshotCopyCmd = cpFlags <>
776-
toDataDirectory db <> "/* " <> fixCachePath
777-
system snapshotCopyCmd >>= \case
778-
ExitSuccess -> pure $ pure result
779-
x -> pure $ Left $ SnapshotCopyFailed snapshotCopyCmd x
792+
let snapshotCopyFlags = cpFlags ++ [toDataDirectory db, fixCachePath]
793+
snapshotCopyCmd = proc "cp" snapshotCopyFlags
794+
795+
(readProcess_ snapshotCopyCmd >> (pure $ Right result))
796+
`catch` (pure . Left . SnapshotCopyFailed)

src/Database/Postgres/Temp/Internal/Config.hs

+18-18
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import Control.Monad.Trans.Class
2525
import Control.Monad.Trans.Cont
2626
import qualified Data.ByteString.Char8 as BSC
2727
import qualified Data.ByteString.Base64.URL as Base64
28+
import qualified Data.ByteString.Lazy.Char8 as LBSC
2829
import Data.Char
2930
import qualified Data.Map.Strict as Map
3031
import Data.Map.Strict (Map)
@@ -39,12 +40,12 @@ import Network.Socket.Free (getFreePort)
3940
import Prettyprinter
4041
import System.Directory
4142
import System.Environment
42-
import System.Exit (ExitCode(..))
43-
import System.IO
43+
import System.IO (Handle, openFile, IOMode(..))
44+
import qualified System.IO as IO
4445
import System.IO.Error
4546
import System.IO.Temp (createTempDirectory)
4647
import System.IO.Unsafe (unsafePerformIO)
47-
import System.Process
48+
import qualified System.Process.Typed as P
4849
import Control.Applicative
4950

5051
{-|
@@ -253,9 +254,9 @@ standardProcessConfig = mempty
253254
{ environmentVariables = mempty
254255
{ inherit = pure True
255256
}
256-
, stdIn = pure stdin
257-
, stdOut = pure stdout
258-
, stdErr = pure stderr
257+
, stdIn = pure IO.stdin
258+
, stdOut = pure IO.stdout
259+
, stdErr = pure IO.stderr
259260
}
260261

261262
-- | A global reference to @\/dev\/null@ 'Handle'.
@@ -636,18 +637,17 @@ completeCopyDirectory theDataDirectory CopyDirectoryCommand {..} =
636637
}
637638

638639
getInitDbVersion :: String
639-
getInitDbVersion = unsafePerformIO $ readProcessWithExitCode "initdb" ["--version"] "" >>= \case
640-
(ExitSuccess, outputString, _) -> do
641-
let
642-
theLastPart = last $ words outputString
643-
versionPart = takeWhile (\x -> isDigit x || x == '.' || x == '-') theLastPart
644-
humanReadable = if last versionPart == '.'
645-
then init versionPart
646-
else versionPart
647-
pure $ humanReadable <> take 8 (makeArgumentHash outputString)
648-
649-
(startErrorExitCode, startErrorStdOut, startErrorStdErr) ->
650-
throwIO InitDbFailed {..}
640+
getInitDbVersion = unsafePerformIO $ do
641+
(stdout, _stderr) <- P.readProcess_ (P.proc "initdb" ["--version"])
642+
`catch` (throwIO . InitDbFailed)
643+
let stdoutString = LBSC.unpack stdout
644+
theLastPart = last $ words stdoutString
645+
versionPart = takeWhile (\x -> isDigit x || x == '.' || x == '-') theLastPart
646+
humanReadable =
647+
if last versionPart == '.'
648+
then init versionPart
649+
else versionPart
650+
pure $ humanReadable <> take 8 (makeArgumentHash stdoutString)
651651
{-# NOINLINE getInitDbVersion #-}
652652

653653
makeCommandLine :: String -> CompleteProcessConfig -> String

0 commit comments

Comments
 (0)