@@ -16,13 +16,14 @@ import Control.Exception
16
16
import Control.Monad (void , join )
17
17
import Control.Monad.Trans.Cont
18
18
import Data.ByteString (ByteString )
19
+ import qualified Data.ByteString.Lazy.Char8 as LBSC
20
+ import qualified Data.ByteString.Lazy as LBS
19
21
import qualified Data.Map.Strict as Map
20
22
import qualified Database.PostgreSQL.Simple.Options as Client
21
23
import GHC.Generics
22
24
import Prettyprinter
23
- import System.Exit (ExitCode (.. ))
24
25
import System.IO.Unsafe (unsafePerformIO )
25
- import System.Process
26
+ import System.Process.Typed
26
27
import System.Directory
27
28
28
29
-- | Handle for holding temporary resources, the @postgres@ process handle
@@ -381,6 +382,20 @@ stopPostgres = stopPlan . dbPostgresProcess
381
382
stopPostgresGracefully :: DB -> IO ExitCode
382
383
stopPostgresGracefully = stopPostgresProcess True . dbPostgresProcess
383
384
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
+
384
399
-- | Restart the @postgres@ from 'DB' using the prior 'Config'. This
385
400
-- will also start an instance previously stoppped with 'stopPostgres'.
386
401
--
@@ -498,22 +513,25 @@ cowCheck = unsafePerformIO $ do
498
513
#else
499
514
cpFlag = " --reflink=auto"
500
515
#endif
501
- (_, _, errorOutput) <- readProcessWithExitCode " cp" [cpFlag] " "
516
+ (_exitCode, stderr) <- readProcessStderr $ proc " cp" [cpFlag]
502
517
-- if the flags do not exist we get a message like "cp: illegal option"
503
518
let usage = " usage:" -- macos
504
519
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
507
523
{-# NOINLINE cowCheck #-}
508
524
509
- cpFlags :: String
510
- cpFlags = if cowCheck
525
+ cpFlags :: [String ]
526
+ cpFlags =
527
+ [" -R" ]
528
+ ++ if cowCheck
511
529
#ifdef darwin_HOST_OS
512
- then " cp -Rc "
530
+ then [ " -c " ]
513
531
#else
514
- then " cp -R -- reflink=auto "
532
+ then [ " -- reflink=auto" ]
515
533
#endif
516
- else " cp -R "
534
+ else []
517
535
518
536
{-|
519
537
'defaultCacheConfig' attempts to determine if the @cp@ on the path
@@ -628,20 +646,19 @@ takeSnapshot
628
646
-- ^ The handle. The @postgres@ is shutdown and the data directory is copied.
629
647
-> IO (Either StartError Snapshot )
630
648
takeSnapshot db = try $ do
631
- throwIfNotSuccess id =<< stopPostgresGracefully db
649
+ stopPostgresGracefullyOrThrow db
632
650
bracketOnError
633
651
(setupDirectoryType
634
652
(toTemporaryDirectory db)
635
653
" tmp-postgres-snapshot"
636
654
Temporary
637
655
)
638
656
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
643
659
644
- pure $ Snapshot snapShotDir
660
+ (readProcess_ snapshotCopyCmd >> (pure $ Snapshot snapShotDir))
661
+ `catch` (throwIO . SnapshotCopyFailed )
645
662
646
663
{-|
647
664
Cleanup any temporary resources used for the snapshot.
@@ -769,11 +786,11 @@ cacheAction cachePath action config = do
769
786
if nonEmpty then pure $ pure result else fmap join $ withConfig config $ \ db -> do
770
787
action db
771
788
-- TODO see if parallel is better
772
- throwIfNotSuccess id =<< stopPostgresGracefully db
789
+ stopPostgresGracefullyOrThrow db
773
790
createDirectoryIfMissing True fixCachePath
774
791
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 )
0 commit comments