packages feed

polysemy-process-0.15.0.0: lib/Polysemy/Process/Executable.hs

{-# options_haddock prune #-}

-- | Description: Executable helpers, Internal
module Polysemy.Process.Executable where

import Path (Abs, File, Path, Rel, toFilePath)
import qualified Path.IO as Path
import Path.IO (executable, getPermissions)

checkExecutable ::
  Member (Embed IO) r =>
  Text ->
  Path Abs File ->
  Sem r (Either Text (Path Abs File))
checkExecutable name path =
  tryIOError (getPermissions path) <&> \case
    Right (executable -> True) ->
      Right path
    Right _ ->
      Left (message "executable")
    Left _ ->
      Left (message "a readable file")
  where
    message what =
      "specified path for `" <> name <> "` is not " <> what <> ": " <> pathText
    pathText =
      toText (toFilePath path)

-- | Find a file in @$PATH@, verifying that it is executable by this process.
resolveExecutable ::
  Member (Embed IO) r =>
  -- | Executable name, for @$PATH@ lookup and error messages
  Path Rel File ->
  -- | Explicit override to be checked for adequate permissions
  Maybe (Path Abs File) ->
  Sem r (Either Text (Path Abs File))
resolveExecutable exe = \case
  Just path ->
    checkExecutable name path
  Nothing ->
    tryIOError (Path.findExecutable exe) <&> \case
      Right (Just path) ->
        Right path
      _ ->
        Left ("could not find executable `" <> name <> "` in `$PATH`.")
  where
    name =
      toText (toFilePath exe)