bdcs-api 0.1.0 → 0.1.1
raw patch · 11 files changed
+86/−84 lines, 11 filesdep −safe-exceptionsdep ~extra
Dependencies removed: safe-exceptions
Dependency ranges changed: extra
Files
- ChangeLog.md +5/−0
- bdcs-api.cabal +3/−6
- src/BDCS/API/Compose.hs +6/−6
- src/BDCS/API/Error.hs +3/−3
- src/BDCS/API/Recipes.hs +15/−15
- src/BDCS/API/Server.hs +6/−6
- src/BDCS/API/Utils.hs +4/−4
- src/BDCS/API/V0.hs +34/−34
- src/BDCS/API/Workspace.hs +3/−3
- tests/ServerSpec.hs +1/−1
- tools/bdcs-api-server.hs +6/−6
ChangeLog.md view
@@ -1,3 +1,8 @@+## 0.1.1++* Remove the build dependency on safe-exceptions.+* Relax the lower bound on the extra module build dependency.+ ## 0.1.0 * Initial release.
bdcs-api.cabal view
@@ -1,5 +1,5 @@ name: bdcs-api-version: 0.1.0+version: 0.1.1 synopsis: BDCS API Server description: This module provides an API server and library component that works with the BDCS project. It provides a web interface for clients to create, edit, and delete@@ -60,7 +60,7 @@ cond >= 0.4.1.1 && < 0.5.0.0, containers >= 0.5.7.1 && < 0.6, directory >= 1.3.0.0 && < 1.4.0.0,- extra >= 1.6.5 && < 1.7.0,+ extra >= 1.6.0 && < 1.7.0, filepath >= 1.4.1.1 && < 1.5.0.0, gi-gio >= 2.0.14 && < 2.1.0, gi-ggit >= 1.0.1 && < 1.1,@@ -77,7 +77,6 @@ persistent >= 2.7.0 && < 2.8.0, persistent-sqlite >= 2.6.0 && < 2.7.0, resourcet >= 1.1.9 && < 1.2,- safe-exceptions < 0.2.0.0, semver >= 0.3.3 && < 0.4, servant-options >= 0.1.0 && < 0.2, servant-server >= 0.12 && < 0.14,@@ -105,8 +104,7 @@ main-is: bdcs-api-server.hs hs-source-dirs: tools build-depends: base >= 4.9 && < 5.0,- bdcs-api,- safe-exceptions < 0.2.0.0+ bdcs-api other-modules: Cmdline default-language: Haskell2010 ghc-options: -Wall -threaded@@ -126,7 +124,6 @@ hspec == 2.*, http-client >= 0.5.7.0 && < 0.6.0.0, monad-loops >= 0.4.0 && < 0.5,- safe-exceptions < 0.2.0.0, servant-client >= 0.12.0.1 && < 0.14.0, servant-server >= 0.12 && < 0.14, string-conversions >= 0.4.0 && < 0.5,
src/BDCS/API/Compose.hs view
@@ -43,7 +43,7 @@ import BDCS.Export.Types(ExportType(..)) import BDCS.Utils.Either(maybeToEither) import Control.Conditional(ifM)-import qualified Control.Exception.Safe as CES+import qualified Control.Exception as CE import Control.Monad(filterM) import Control.Monad.Except(ExceptT(..), runExceptT) import Control.Monad.Logger(MonadLoggerIO, logErrorN, logInfoN)@@ -169,9 +169,9 @@ then return $ Left $ "Build " ++ cs uuid ++ " not in FINISHED or FAILED" else do let path = dir </> cs uuid- CES.catch (do removePathForcibly path- return $ Right UuidStatus { usStatus=True, usUuid=uuid })- (\(e :: CES.IOException) -> return $ Left $ cs uuid ++ ": " ++ cs (show e))+ CE.catch (do removePathForcibly path+ return $ Right UuidStatus { usStatus=True, usUuid=uuid })+ (\(e :: CE.IOException) -> return $ Left $ cs uuid ++ ": " ++ cs (show e)) getComposesWithStatus :: FilePath -> QueueStatus -> IO [ComposeStatus] getComposesWithStatus resultsDir status = do@@ -188,8 +188,8 @@ matches uuid = do let statusFile = resultsDir </> cs uuid </> "STATUS" ifM (doesFileExist statusFile)- (do line <- CES.catch (TIO.readFile statusFile)- (\(_ :: CES.IOException) -> return "")+ (do line <- CE.catch (TIO.readFile statusFile)+ (\(_ :: CE.IOException) -> return "") return $ queueStatusFromText line == Just status) (return False)
src/BDCS/API/Error.hs view
@@ -25,7 +25,7 @@ APIResponse(..)) where -import qualified Control.Exception.Safe as CES+import qualified Control.Exception as CE import Control.Monad.Except(ExceptT(..)) import Control.Monad.IO.Class(liftIO) import Data.Aeson@@ -76,5 +76,5 @@ -- | Convert IO Exceptions into an ExceptT. tryIO :: IO a -> ExceptT String IO a-tryIO fn = ExceptT $ liftIO $ CES.catch (Right <$> fn)- (\(e :: CES.IOException) -> return $ Left (show e))+tryIO fn = ExceptT $ liftIO $ CE.catch (Right <$> fn)+ (\(e :: CE.IOException) -> return $ Left (show e))
src/BDCS/API/Recipes.hs view
@@ -63,7 +63,7 @@ import BDCS.API.Utils(caseInsensitive, maybeThrow) import BDCS.API.Workspace import Control.Conditional(ifM, whenM)-import qualified Control.Exception.Safe as CES+import qualified Control.Exception as CE import Control.Monad(filterM, unless, void) import Control.Monad.IO.Class(MonadIO) import Control.Monad.Loops(allM)@@ -136,7 +136,7 @@ | OIdError -- ^ Error creating a String from an OId deriving (Eq, Show) -instance CES.Exception GitError+instance CE.Exception GitError -- | Get the branch's HEAD Commit --@@ -1019,7 +1019,7 @@ | ChangesOrderError deriving (Eq, Show) -instance CES.Exception TestError+instance CE.Exception TestError -- | Run the Git repository tests with a temporary directory runGitRepoTests :: IO Bool@@ -1047,7 +1047,7 @@ putStrLn " - Checking Recipe Version" erecipe <- readRecipeCommit repo "master" "test-server" Nothing let recipe = snd $ head $ rights [erecipe]- unless (testRecipe == recipe) (CES.throwIO $ RecipeMismatchError [testRecipe, recipe])+ unless (testRecipe == recipe) (CE.throwIO $ RecipeMismatchError [testRecipe, recipe]) -- Check that saving a changed recipe, with the same version, bumps it. let new_recipe1 = testRecipe { rDescription = "Second commit with same version, should bump" }@@ -1058,7 +1058,7 @@ putStrLn " - Checking Modified Recipe's Version" erecipe' <- readRecipeCommit repo "master" "test-server" Nothing let recipe' = snd $ head $ rights [erecipe']- unless (new_recipe1 {rVersion = Just "0.1.3"} == recipe') (CES.throwIO $ RecipeMismatchError [new_recipe1, recipe'])+ unless (new_recipe1 {rVersion = Just "0.1.3"} == recipe') (CE.throwIO $ RecipeMismatchError [new_recipe1, recipe']) -- Check that saving a changed recipe, with a completely different version, uses it without bumping. let new_recipe2 = testRecipe {rDescription = "Third commit with new version, should just use it",@@ -1070,12 +1070,12 @@ putStrLn " - Checking Modified Recipe's Version" erecipe'' <- readRecipeCommit repo "master" "test-server" Nothing let recipe'' = snd $ head $ rights [erecipe'']- unless (new_recipe2 == recipe'') (CES.throwIO $ RecipeMismatchError [new_recipe2, recipe''])+ unless (new_recipe2 == recipe'') (CE.throwIO $ RecipeMismatchError [new_recipe2, recipe'']) -- List the files on master putStrLn " - Listing the committed files" files <- listBranchFiles repo "master"- unless (files == testFiles) (CES.throwIO $ FileListError files)+ unless (files == testFiles) (CE.throwIO $ FileListError files) -- Get the commits to http-server.toml putStrLn " - List commits to http-server.toml"@@ -1083,7 +1083,7 @@ -- Should be 1 commit let expected_msg_1 = "Recipe http-server.toml, version 0.2.0 saved" let msg_1 = cdMessage (head http_commits)- unless (msg_1 == expected_msg_1) (CES.throwIO $ HttpCommitError http_commits)+ unless (msg_1 == expected_msg_1) (CE.throwIO $ HttpCommitError http_commits) -- delete http-server.toml file putStrLn " - Delete the http-server.toml file"@@ -1092,7 +1092,7 @@ -- List the files on master putStrLn " - Check that http-server.toml has been deleted" files2 <- listBranchFiles repo "master"- unless (files2 == testFiles2) (CES.throwIO $ FileListError files2)+ unless (files2 == testFiles2) (CE.throwIO $ FileListError files2) -- Revert the delete commit_id <- Git.oIdNewFromString (cdCommit $ head http_commits) >>= maybeThrow NewOIdError@@ -1101,23 +1101,23 @@ -- List the files on master putStrLn " - Check that http-server.toml has been restored" files3 <- listBranchFiles repo "master"- unless (files3 == testFiles) (CES.throwIO $ FileListError files3)+ unless (files3 == testFiles) (CE.throwIO $ FileListError files3) -- tag a commit putStrLn " - Tag most recent commit of http-server.toml" ok <- tagRecipeCommit repo "master" "http-server"- unless ok (CES.throwIO TagCommitError)+ unless ok (CE.throwIO TagCommitError) -- list the commits and check for the tag putStrLn " - Check the Tag" commits <- listCommits repo "master" "http-server.toml" let revision = cdRevision (head commits)- unless (revision == Just 1) (CES.throwIO $ CommitRevisionError commits)+ unless (revision == Just 1) (CE.throwIO $ CommitRevisionError commits) -- Make sure the first listed commit is the reverted commit let top_commit = cdCommit $ head commits revert_hash <- fromJust <$> Git.oIdToString revert_id- unless (top_commit == revert_hash) (CES.throwIO ChangesOrderError)+ unless (top_commit == revert_hash) (CE.throwIO ChangesOrderError) return True @@ -1139,13 +1139,13 @@ -- Read the Recipe, does it match? putStrLn " - Read Recipe from Workspace for master branch" recipe <- workspaceRead repo "master" "test-server" >>= maybeThrow RecipeReadError- unless (testRecipe == recipe) (CES.throwIO $ RecipeMismatchError [testRecipe, recipe])+ unless (testRecipe == recipe) (CE.throwIO $ RecipeMismatchError [testRecipe, recipe]) -- Delete the Recipe, is it gone? putStrLn " - Delete Recipe from Workspace for master branch" workspaceDelete repo "master" "test-server" dir <- workspaceDir repo "master" let filename = dir </> T.unpack (recipeTomlFilename $ T.unpack "test-server")- whenM (doesFileExist filename) (CES.throwIO $ DeleteFailedError filename)+ whenM (doesFileExist filename) (CE.throwIO $ DeleteFailedError filename) return True
src/BDCS/API/Server.hs view
@@ -46,7 +46,7 @@ import Control.Concurrent.STM.TChan(newTChan, readTChan) import Control.Concurrent.STM.TMVar(TMVar, newTMVar, putTMVar, readTMVar, takeTMVar) import Control.Conditional(whenM)-import qualified Control.Exception.Safe as CES+import qualified Control.Exception as CE import Control.Monad(forever, void) import Control.Monad.Except(runExceptT) import Control.Monad.Logger(runFileLoggingT, runStderrLoggingT)@@ -78,7 +78,7 @@ | NoSocketError deriving(Show) -instance CES.Exception SocketException+instance CE.Exception SocketException type InProgressMap = Map.Map T.Text (Async (), ComposeInfo) @@ -200,9 +200,9 @@ where getSocket :: FilePath -> IO Socket getSocket fp = lookupEnv "LISTEN_FDS" >>= \case- Nothing -> if fp == "" then CES.throw NoSocketError else newSocket fp+ Nothing -> if fp == "" then CE.throw NoSocketError else newSocket fp Just s -> case readMaybe s of- Nothing -> CES.throw BadFileDescriptor+ Nothing -> CE.throw BadFileDescriptor Just fd -> mkSocket fd AF_UNIX Stream defaultProtocol Bound newSocket :: FilePath -> IO Socket@@ -210,8 +210,8 @@ whenM (doesPathExist path) $ removePathForcibly path - gid <- CES.catchIO (groupID <$> getGroupEntryForName socketGroup)- (\_ -> CES.throw $ BadGroup socketGroup)+ gid <- CE.catch (groupID <$> getGroupEntryForName socketGroup)+ (\(_ :: CE.IOException) -> CE.throw $ BadGroup socketGroup) s <- socket AF_UNIX Stream defaultProtocol bind s (SockAddrUnix path)
src/BDCS/API/Utils.hs view
@@ -28,7 +28,7 @@ where import qualified Control.Concurrent.ReadWriteLock as RWL-import qualified Control.Exception.Safe as CES+import qualified Control.Exception as CE import Control.Monad (liftM) import Data.List.Split (splitOn) import qualified Data.Text as T@@ -46,11 +46,11 @@ -- | Turn exceptions from an action into 'Nothing' maybeIO :: IO a -> IO (Maybe a)-maybeIO act = CES.handle (\(_ :: CES.SomeException) -> (return Nothing)) (Just `liftM` act)+maybeIO act = CE.handle (\(_ :: CE.SomeException) -> (return Nothing)) (Just `liftM` act) -- | Throw an IO error when a 'Maybe' is 'Nothing'-maybeThrow :: CES.Exception e => e -> Maybe a -> IO a-maybeThrow err Nothing = CES.throwIO err+maybeThrow :: CE.Exception e => e -> Maybe a -> IO a+maybeThrow err Nothing = CE.throwIO err maybeThrow _ (Just v) = return v -- | Take a list of possiby comma, or comma-space, separated options and turn it into a list of options
src/BDCS/API/V0.hs view
@@ -85,7 +85,7 @@ import qualified Control.Concurrent.ReadWriteLock as RWL import Control.Concurrent.STM.TChan(writeTChan) import Control.Concurrent.STM.TMVar(newEmptyTMVar, readTMVar)-import qualified Control.Exception.Safe as CES+import qualified Control.Exception as CE import Control.Monad.STM(atomically) import Control.Monad.Except import Data.Aeson@@ -490,15 +490,15 @@ -- | Read the recipe from the workspace, and convert WorkspaceErrors into Nothing catch_ws_recipe :: IO (Maybe Recipe) catch_ws_recipe =- CES.catch (workspaceRead (gitRepo repoLock) branch recipe_name)- (\(_ :: WorkspaceError) -> return Nothing)+ CE.catch (workspaceRead (gitRepo repoLock) branch recipe_name)+ (\(_ :: WorkspaceError) -> return Nothing) -- | Read the recipe from git, and convert errors into Left descriptions of what went wrong. catch_git_recipe :: IO (Either String (T.Text, Recipe)) catch_git_recipe =- CES.catches (readRecipeCommit (gitRepo repoLock) branch recipe_name Nothing)- [CES.Handler (\(e :: GitError) -> return $ Left (show e)),- CES.Handler (\(e :: GError) -> return $ Left (show e))]+ CE.catches (readRecipeCommit (gitRepo repoLock) branch recipe_name Nothing)+ [CE.Handler (\(e :: GitError) -> return $ Left (show e)),+ CE.Handler (\(e :: GError) -> return $ Left (show e))] -- | Details about commits to a blueprint@@ -638,9 +638,9 @@ catch_recipe_changes :: T.Text -> IO (Either String [CommitDetails]) catch_recipe_changes recipe_name =- CES.catches (Right <$> listRecipeCommits (gitRepo cfgRepoLock) (defaultBranch mbranch) recipe_name)- [CES.Handler (\(e :: GitError) -> return $ Left (show e)),- CES.Handler (\(e :: GError) -> return $ Left (show e))]+ CE.catches (Right <$> listRecipeCommits (gitRepo cfgRepoLock) (defaultBranch mbranch) recipe_name)+ [CE.Handler (\(e :: GitError) -> return $ Left (show e)),+ CE.Handler (\(e :: GError) -> return $ Left (show e))] -- | POST /api/v0/blueprints/new@@ -669,9 +669,9 @@ where catch_recipe_new :: IO (Either String Git.OId) catch_recipe_new =- CES.catches (Right <$> commitRecipe (gitRepo cfgRepoLock) (defaultBranch mbranch) recipe)- [CES.Handler (\(e :: GitError) -> return $ Left (show e)),- CES.Handler (\(e :: GError) -> return $ Left (show e))]+ CE.catches (Right <$> commitRecipe (gitRepo cfgRepoLock) (defaultBranch mbranch) recipe)+ [CE.Handler (\(e :: GitError) -> return $ Left (show e)),+ CE.Handler (\(e :: GError) -> return $ Left (show e))] -- | DELETE /api/v0/blueprints/delete/\<recipe\>@@ -696,9 +696,9 @@ where catch_recipe_delete :: IO (Either String Git.OId) catch_recipe_delete =- CES.catches (Right <$> deleteRecipe (gitRepo cfgRepoLock) (defaultBranch mbranch) (T.pack recipe_name))- [CES.Handler (\(e :: GitError) -> return $ Left (show e)),- CES.Handler (\(e :: GError) -> return $ Left (show e))]+ CE.catches (Right <$> deleteRecipe (gitRepo cfgRepoLock) (defaultBranch mbranch) (T.pack recipe_name))+ [CE.Handler (\(e :: GitError) -> return $ Left (show e)),+ CE.Handler (\(e :: GError) -> return $ Left (show e))] -- | POST /api/v0/blueprints/undo/\<recipe\>/\<commit\>@@ -724,9 +724,9 @@ where catch_recipe_undo :: IO (Either String Git.OId) catch_recipe_undo =- CES.catches (Right <$> revertRecipe (gitRepo cfgRepoLock) (defaultBranch mbranch) (T.pack recipe_name) (T.pack commit))- [CES.Handler (\(e :: GitError) -> return $ Left (show e)),- CES.Handler (\(e :: GError) -> return $ Left (show e))]+ CE.catches (Right <$> revertRecipe (gitRepo cfgRepoLock) (defaultBranch mbranch) (T.pack recipe_name) (T.pack commit))+ [CE.Handler (\(e :: GitError) -> return $ Left (show e)),+ CE.Handler (\(e :: GError) -> return $ Left (show e))] -- | POST /api/v0/blueprints/workspace@@ -754,9 +754,9 @@ where catch_recipe_ws :: IO (Either String ()) catch_recipe_ws =- CES.catches (Right <$> workspaceWrite (gitRepo cfgRepoLock) (defaultBranch mbranch) recipe)- [CES.Handler (\(e :: GitError) -> return $ Left (show e)),- CES.Handler (\(e :: GError) -> return $ Left (show e))]+ CE.catches (Right <$> workspaceWrite (gitRepo cfgRepoLock) (defaultBranch mbranch) recipe)+ [CE.Handler (\(e :: GitError) -> return $ Left (show e)),+ CE.Handler (\(e :: GError) -> return $ Left (show e))] -- | DELETE /api/v0/blueprints/workspace/\<recipe\>@@ -781,9 +781,9 @@ where catch_recipe_delete :: IO (Either String ()) catch_recipe_delete =- CES.catches (Right <$> workspaceDelete (gitRepo cfgRepoLock) (defaultBranch mbranch) (T.pack recipe_name))- [CES.Handler (\(e :: GitError) -> return $ Left (show e)),- CES.Handler (\(e :: GError) -> return $ Left (show e))]+ CE.catches (Right <$> workspaceDelete (gitRepo cfgRepoLock) (defaultBranch mbranch) (T.pack recipe_name))+ [CE.Handler (\(e :: GitError) -> return $ Left (show e)),+ CE.Handler (\(e :: GError) -> return $ Left (show e))] -- | POST /api/v0/blueprints/tag/<blueprint>@@ -810,9 +810,9 @@ where catch_recipe_tag :: IO (Either String Bool) catch_recipe_tag =- CES.catches (Right <$> tagRecipeCommit (gitRepo cfgRepoLock) (defaultBranch mbranch) (T.pack recipe_name))- [CES.Handler (\(e :: GitError) -> return $ Left (show e)),- CES.Handler (\(e :: GError) -> return $ Left (show e))]+ CE.catches (Right <$> tagRecipeCommit (gitRepo cfgRepoLock) (defaultBranch mbranch) (T.pack recipe_name))+ [CE.Handler (\(e :: GitError) -> return $ Left (show e)),+ CE.Handler (\(e :: GError) -> return $ Left (show e))] -- | JSON response for /blueprints/diff@@ -949,15 +949,15 @@ -- | Read the recipe from the workspace, and convert WorkspaceErrors into Nothing catch_ws_recipe :: T.Text -> IO (Maybe Recipe) catch_ws_recipe name =- CES.catch (workspaceRead (gitRepo cfgRepoLock) (defaultBranch mbranch) name)- (\(_ :: WorkspaceError) -> return Nothing)+ CE.catch (workspaceRead (gitRepo cfgRepoLock) (defaultBranch mbranch) name)+ (\(_ :: WorkspaceError) -> return Nothing) -- | Read the recipe from git, and convert errors into Left descriptions of what went wrong. catch_git_recipe :: T.Text -> Maybe T.Text -> IO (Either String (T.Text, Recipe)) catch_git_recipe name commit =- CES.catches (readRecipeCommit (gitRepo cfgRepoLock) (defaultBranch mbranch) name commit)- [CES.Handler (\(e :: GitError) -> return $ Left (show e)),- CES.Handler (\(e :: GError) -> return $ Left (show e))]+ CE.catches (readRecipeCommit (gitRepo cfgRepoLock) (defaultBranch mbranch) name commit)+ [CE.Handler (\(e :: GitError) -> return $ Left (show e)),+ CE.Handler (\(e :: GError) -> return $ Left (show e))] -- | The blueprint's dependency details@@ -2213,6 +2213,6 @@ where readArtifactFile :: FilePath -> IO (Maybe String) readArtifactFile dir =- CES.catch (Just <$> readFile (dir </> "ARTIFACT"))- (\(_ :: CES.IOException) -> return Nothing)+ CE.catch (Just <$> readFile (dir </> "ARTIFACT"))+ (\(_ :: CE.IOException) -> return Nothing) filename fn = cs uuid ++ "-" ++ takeFileName fn
src/BDCS/API/Workspace.hs view
@@ -34,7 +34,7 @@ import BDCS.API.Recipe(Recipe(..), parseRecipe, recipeTOML, recipeTomlFilename) import BDCS.API.Utils(maybeThrow) import Control.Conditional(ifM, whenM)-import qualified Control.Exception.Safe as CES+import qualified Control.Exception as CE import qualified Data.Text as T import qualified Data.Text.IO as TIO import GI.Gio(fileGetPath)@@ -48,7 +48,7 @@ | ParseRecipeError String -- ^ There was an error parsing the recipe, details will be included deriving (Eq, Show) -instance CES.Exception WorkspaceError+instance CE.Exception WorkspaceError -- | Create the branch's workspace path --@@ -81,7 +81,7 @@ toml_in <- TIO.readFile filename let erecipe = parseRecipe toml_in case erecipe of- Left e -> CES.throwIO $ ParseRecipeError e+ Left e -> CE.throwIO $ ParseRecipeError e Right recipe -> return recipe -- | Write a 'Recipe' to the branch's workspace
tests/ServerSpec.hs view
@@ -28,7 +28,7 @@ import BDCS.API.V0 import BDCS.DB(Projects(..), schemaVersion) import Control.Conditional(whenM)-import Control.Exception.Safe(throwIO)+import Control.Exception(throwIO) import Control.Monad.Loops(allM) import qualified Data.ByteString.Lazy as LBS import Data.List(isSuffixOf)
tools/bdcs-api-server.hs view
@@ -21,7 +21,7 @@ import BDCS.API.Server(SocketException(..), runServer) import BDCS.API.Version(buildVersion) import Cmdline(CliOptions(..), parseArgs)-import qualified Control.Exception.Safe as CES+import qualified Control.Exception as CE import Control.Monad(when) main :: IO ()@@ -30,8 +30,8 @@ when optShowVersion $ putStrLn ("bdcs-api " ++ buildVersion) - CES.catch (runServer optSocketPath optSocketGroup optBDCS optRecipeRepo optMetadataDB)- (\case- BadFileDescriptor -> putStrLn "Bad value provided in $LISTEN_FDS"- BadGroup g -> putStrLn $ "Provided group does not exist: " ++ g- NoSocketError -> putStrLn "One of $LISTEN_FDS or -s <socket> must be provided")+ CE.catch (runServer optSocketPath optSocketGroup optBDCS optRecipeRepo optMetadataDB)+ (\case+ BadFileDescriptor -> putStrLn "Bad value provided in $LISTEN_FDS"+ BadGroup g -> putStrLn $ "Provided group does not exist: " ++ g+ NoSocketError -> putStrLn "One of $LISTEN_FDS or -s <socket> must be provided")