{-# LANGUAGE LambdaCase #-}

-----------------------------------------------------------------------------

-----------------------------------------------------------------------------

-- |
-- Module      :  Distribution.Client.Init.NonInteractive.Heuristics
-- Copyright   :  (c) Benedikt Huber 2009
-- License     :  BSD-like
--
-- Maintainer  :  cabal-devel@haskell.org
-- Stability   :  provisional
-- Portability :  portable
--
-- Heuristics for creating initial cabal files.
module Distribution.Client.Init.NonInteractive.Heuristics
  ( guessPackageName
  , guessMainFile
  , guessLicense
  , guessExtraDocFiles
  , guessAuthorName
  , guessAuthorEmail
  , guessCabalSpecVersion
  , guessLanguage
  , guessPackageType
  , guessSourceDirectories
  , guessApplicationDirectories
  ) where

import Distribution.Client.Compat.Prelude hiding (many, readFile, (<|>))

import Distribution.Simple.Setup (fromFlagOrDefault)

import qualified Data.List as L
import qualified Data.Set as Set
import Distribution.CabalSpecVersion
import Distribution.Client.Init.Defaults
import Distribution.Client.Init.FlagExtractors (getCabalVersionNoPrompt)
import Distribution.Client.Init.Types
import Distribution.Client.Init.Utils
import Distribution.FieldGrammar.Newtypes
import Distribution.Simple.Compiler
import Distribution.Types.PackageName (PackageName)
import Distribution.Version
import Language.Haskell.Extension
import System.FilePath

-- | Guess the main file, returns a default value if none is found.
guessMainFile :: Interactive m => FilePath -> m HsFilePath
guessMainFile :: forall (m :: * -> *). Interactive m => FilePath -> m HsFilePath
guessMainFile FilePath
pkgDir = do
  Bool
exists <- FilePath -> m Bool
forall (m :: * -> *). Interactive m => FilePath -> m Bool
doesDirectoryExist FilePath
pkgDir
  if Bool
exists
    then do
      [FilePath]
files <- (FilePath -> Bool) -> [FilePath] -> [FilePath]
forall a. (a -> Bool) -> [a] -> [a]
filter FilePath -> Bool
isMain ([FilePath] -> [FilePath]) -> m [FilePath] -> m [FilePath]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> m [FilePath]
forall (m :: * -> *). Interactive m => FilePath -> m [FilePath]
listFilesRecursive FilePath
pkgDir
      HsFilePath -> m HsFilePath
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (HsFilePath -> m HsFilePath) -> HsFilePath -> m HsFilePath
forall a b. (a -> b) -> a -> b
$
        case [FilePath]
files of
          [] -> HsFilePath
defaultMainIs
          (FilePath
f : [FilePath]
_) -> FilePath -> HsFilePath
toHsFilePath FilePath
f
    else HsFilePath -> m HsFilePath
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return HsFilePath
defaultMainIs

-- | Juggling characters around to guess the desired cabal version based on
--   the system's cabal version.
guessCabalSpecVersion :: Interactive m => m CabalSpecVersion
guessCabalSpecVersion :: forall (m :: * -> *). Interactive m => m CabalSpecVersion
guessCabalSpecVersion = do
  (ExitCode
_, FilePath
verString, FilePath
_) <- FilePath
-> [FilePath] -> FilePath -> m (ExitCode, FilePath, FilePath)
forall (m :: * -> *).
Interactive m =>
FilePath
-> [FilePath] -> FilePath -> m (ExitCode, FilePath, FilePath)
readProcessWithExitCode FilePath
"cabal" [FilePath
"--version"] FilePath
""
  case FilePath -> Maybe Version
forall a. Parsec a => FilePath -> Maybe a
simpleParsec (FilePath -> Maybe Version) -> FilePath -> Maybe Version
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> FilePath -> FilePath
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (Bool -> Bool
not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
isSpace) (FilePath -> FilePath) -> FilePath -> FilePath
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> FilePath -> FilePath
forall a. (a -> Bool) -> [a] -> [a]
dropWhile (Bool -> Bool
not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
isDigit) FilePath
verString of
    Just Version
v -> CabalSpecVersion -> m CabalSpecVersion
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CabalSpecVersion -> m CabalSpecVersion)
-> CabalSpecVersion -> m CabalSpecVersion
forall a b. (a -> b) -> a -> b
$ CabalSpecVersion -> Maybe CabalSpecVersion -> CabalSpecVersion
forall a. a -> Maybe a -> a
fromMaybe CabalSpecVersion
defaultCabalVersion (Maybe CabalSpecVersion -> CabalSpecVersion)
-> Maybe CabalSpecVersion -> CabalSpecVersion
forall a b. (a -> b) -> a -> b
$ case Version -> [Int]
versionNumbers Version
v of
      [Int
x, Int
y, Int
_, Int
_] -> [Int] -> Maybe CabalSpecVersion
cabalSpecFromVersionDigits [Int
x, Int
y]
      [Int
x, Int
y, Int
_] -> [Int] -> Maybe CabalSpecVersion
cabalSpecFromVersionDigits [Int
x, Int
y]
      [Int]
_ -> CabalSpecVersion -> Maybe CabalSpecVersion
forall a. a -> Maybe a
Just CabalSpecVersion
defaultCabalVersion
    Maybe Version
Nothing -> CabalSpecVersion -> m CabalSpecVersion
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure CabalSpecVersion
defaultCabalVersion

-- | Guess the language specification based on the GHC version
guessLanguage :: Interactive m => Compiler -> m Language
guessLanguage :: forall (m :: * -> *). Interactive m => Compiler -> m Language
guessLanguage Compiler{compilerId :: Compiler -> CompilerId
compilerId = CompilerId CompilerFlavor
GHC Version
ver} =
  Language -> m Language
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Language -> m Language) -> Language -> m Language
forall a b. (a -> b) -> a -> b
$
    if Version
ver Version -> Version -> Bool
forall a. Ord a => a -> a -> Bool
< [Int] -> Version
mkVersion [Int
7, Int
0, Int
1]
      then Language
Haskell98
      else Language
Haskell2010
guessLanguage Compiler
_ = Language -> m Language
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Language
defaultLanguage

-- | Guess the package name based on the given root directory.
guessPackageName :: Interactive m => FilePath -> m PackageName
guessPackageName :: forall (m :: * -> *). Interactive m => FilePath -> m PackageName
guessPackageName = FilePath -> m PackageName
forall (m :: * -> *). Interactive m => FilePath -> m PackageName
filePathToPkgName

-- | Try to guess the license from an already existing @LICENSE@ file in
--   the package directory, comparing the file contents with the ones
--   listed in @Licenses.hs@, for now it only returns a default value.
guessLicense :: Interactive m => InitFlags -> m SpecLicense
guessLicense :: forall (m :: * -> *). Interactive m => InitFlags -> m SpecLicense
guessLicense InitFlags
flags = SpecLicense -> m SpecLicense
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (SpecLicense -> m SpecLicense)
-> (CabalSpecVersion -> SpecLicense)
-> CabalSpecVersion
-> m SpecLicense
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CabalSpecVersion -> SpecLicense
defaultLicense (CabalSpecVersion -> m SpecLicense)
-> CabalSpecVersion -> m SpecLicense
forall a b. (a -> b) -> a -> b
$ InitFlags -> CabalSpecVersion
getCabalVersionNoPrompt InitFlags
flags

guessExtraDocFiles :: Interactive m => InitFlags -> m (Maybe (Set FilePath))
guessExtraDocFiles :: forall (m :: * -> *).
Interactive m =>
InitFlags -> m (Maybe (Set FilePath))
guessExtraDocFiles InitFlags
flags = do
  FilePath
pkgDir <- m FilePath -> Flag (m FilePath) -> m FilePath
forall a. a -> Flag a -> a
fromFlagOrDefault m FilePath
forall (m :: * -> *). Interactive m => m FilePath
getCurrentDirectory (Flag (m FilePath) -> m FilePath)
-> Flag (m FilePath) -> m FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> m FilePath
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (FilePath -> m FilePath) -> Flag FilePath -> Flag (m FilePath)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> InitFlags -> Flag FilePath
packageDir InitFlags
flags
  [FilePath]
files <- FilePath -> m [FilePath]
forall (m :: * -> *). Interactive m => FilePath -> m [FilePath]
getDirectoryContents FilePath
pkgDir

  let extraDocCandidates :: [FilePath]
extraDocCandidates = [FilePath
"CHANGES", FilePath
"CHANGELOG", FilePath
"README"]
      extraDocs :: [FilePath]
extraDocs = [FilePath
y | FilePath
x <- [FilePath]
extraDocCandidates, FilePath
y <- [FilePath]
files, FilePath
x FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== (Char -> Char) -> FilePath -> FilePath
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toUpper (FilePath -> FilePath
takeBaseName FilePath
y)]

  Maybe (Set FilePath) -> m (Maybe (Set FilePath))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (Set FilePath) -> m (Maybe (Set FilePath)))
-> Maybe (Set FilePath) -> m (Maybe (Set FilePath))
forall a b. (a -> b) -> a -> b
$
    Set FilePath -> Maybe (Set FilePath)
forall a. a -> Maybe a
Just (Set FilePath -> Maybe (Set FilePath))
-> Set FilePath -> Maybe (Set FilePath)
forall a b. (a -> b) -> a -> b
$
      if [FilePath] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [FilePath]
extraDocs
        then FilePath -> Set FilePath
forall a. a -> Set a
Set.singleton FilePath
defaultChangelog
        else [FilePath] -> Set FilePath
forall a. Ord a => [a] -> Set a
Set.fromList [FilePath]
extraDocs

-- | Try to guess the package type from the files in the package directory,
--   looking for unique characteristics from each type, defaults to Executable.
guessPackageType :: Interactive m => InitFlags -> m PackageType
guessPackageType :: forall (m :: * -> *). Interactive m => InitFlags -> m PackageType
guessPackageType InitFlags
flags = do
  if Bool -> Flag Bool -> Bool
forall a. a -> Flag a -> a
fromFlagOrDefault Bool
False (InitFlags -> Flag Bool
initializeTestSuite InitFlags
flags)
    then PackageType -> m PackageType
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return PackageType
TestSuite
    else do
      let lastDir :: FilePath -> FilePath
lastDir FilePath
dirs = [FilePath] -> FilePath
forall a. HasCallStack => [a] -> a
L.last ([FilePath] -> FilePath)
-> (FilePath -> [FilePath]) -> FilePath -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> [FilePath]
splitDirectories (FilePath -> FilePath) -> FilePath -> FilePath
forall a b. (a -> b) -> a -> b
$ FilePath
dirs
          srcCandidates :: [FilePath]
srcCandidates = [FilePath
defaultSourceDir, FilePath
"src", FilePath
"source"]
          testCandidates :: [FilePath]
testCandidates = [FilePath
defaultTestDir, FilePath
"test", FilePath
"tests"]

      FilePath
pkgDir <- m FilePath -> Flag (m FilePath) -> m FilePath
forall a. a -> Flag a -> a
fromFlagOrDefault m FilePath
forall (m :: * -> *). Interactive m => m FilePath
getCurrentDirectory (Flag (m FilePath) -> m FilePath)
-> Flag (m FilePath) -> m FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> m FilePath
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (FilePath -> m FilePath) -> Flag FilePath -> Flag (m FilePath)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> InitFlags -> Flag FilePath
packageDir InitFlags
flags
      [FilePath]
files <- (FilePath -> m Bool) -> FilePath -> m [FilePath]
forall (m :: * -> *).
Interactive m =>
(FilePath -> m Bool) -> FilePath -> m [FilePath]
listFilesInside (\FilePath
x -> Bool -> m Bool
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> m Bool) -> Bool -> m Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath
lastDir FilePath
x FilePath -> [FilePath] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [FilePath]
testCandidates) FilePath
pkgDir
      [FilePath]
files' <-
        (FilePath -> Bool) -> [FilePath] -> [FilePath]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (FilePath -> Bool) -> FilePath -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Bool] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([Bool] -> Bool) -> (FilePath -> [Bool]) -> FilePath -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath -> Bool) -> [FilePath] -> [Bool]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath -> [FilePath] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [FilePath]
testCandidates) ([FilePath] -> [Bool])
-> (FilePath -> [FilePath]) -> FilePath -> [Bool]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> [FilePath]
splitDirectories)
          ([FilePath] -> [FilePath]) -> m [FilePath] -> m [FilePath]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> m [FilePath]
forall (m :: * -> *). Interactive m => FilePath -> m [FilePath]
listFilesRecursive FilePath
pkgDir

      let hasExe :: Bool
hasExe = Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [FilePath] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [FilePath
f | FilePath
f <- [FilePath]
files, FilePath -> Bool
isMain (FilePath -> Bool) -> FilePath -> Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath
takeFileName FilePath
f]
          hasLib :: Bool
hasLib = Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [FilePath] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [FilePath
f | FilePath
f <- [FilePath]
files, FilePath -> FilePath
lastDir FilePath
f FilePath -> [FilePath] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [FilePath]
srcCandidates]
          hasTest :: Bool
hasTest = Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [FilePath] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [FilePath
f | FilePath
f <- [FilePath]
files', FilePath -> Bool
isMain (FilePath -> Bool) -> FilePath -> Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath
takeFileName FilePath
f]

      PackageType -> m PackageType
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (PackageType -> m PackageType) -> PackageType -> m PackageType
forall a b. (a -> b) -> a -> b
$ case (Bool
hasLib, Bool
hasExe, Bool
hasTest) of
        (Bool
True, Bool
True, Bool
_) -> PackageType
LibraryAndExecutable
        (Bool
True, Bool
False, Bool
_) -> PackageType
Library
        (Bool
False, Bool
False, Bool
True) -> PackageType
TestSuite
        (Bool, Bool, Bool)
_ -> PackageType
Executable

-- | Try to guess the application directories from the package directory,
--   using a default value as fallback.
guessApplicationDirectories :: Interactive m => InitFlags -> m [FilePath]
guessApplicationDirectories :: forall (m :: * -> *). Interactive m => InitFlags -> m [FilePath]
guessApplicationDirectories InitFlags
flags = do
  FilePath
pkgDirs <-
    m FilePath -> Flag (m FilePath) -> m FilePath
forall a. a -> Flag a -> a
fromFlagOrDefault
      m FilePath
forall (m :: * -> *). Interactive m => m FilePath
getCurrentDirectory
      (FilePath -> m FilePath
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (FilePath -> m FilePath) -> Flag FilePath -> Flag (m FilePath)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> InitFlags -> Flag FilePath
packageDir InitFlags
flags)
  [FilePath]
pkgDirsContents <- FilePath -> m [FilePath]
forall (m :: * -> *). Interactive m => FilePath -> m [FilePath]
listDirectory FilePath
pkgDirs

  let candidates :: [FilePath]
candidates = [FilePath
defaultApplicationDir, FilePath
"app", FilePath
"src-exe"]
   in [FilePath] -> m [FilePath]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([FilePath] -> m [FilePath]) -> [FilePath] -> m [FilePath]
forall a b. (a -> b) -> a -> b
$ case [FilePath
y | FilePath
x <- [FilePath]
candidates, FilePath
y <- [FilePath]
pkgDirsContents, FilePath
x FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
y] of
        [] -> [FilePath
defaultApplicationDir]
        [FilePath]
x -> (FilePath -> FilePath) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath -> FilePath -> FilePath
</> FilePath
pkgDirs) ([FilePath] -> [FilePath])
-> ([FilePath] -> [FilePath]) -> [FilePath] -> [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> [FilePath]
forall a. Eq a => [a] -> [a]
nub ([FilePath] -> [FilePath]) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> a -> b
$ [FilePath]
x

-- | Try to guess the source directories, using a default value as fallback.
guessSourceDirectories :: Interactive m => InitFlags -> m [FilePath]
guessSourceDirectories :: forall (m :: * -> *). Interactive m => InitFlags -> m [FilePath]
guessSourceDirectories InitFlags
flags = do
  FilePath
pkgDir <- m FilePath -> Flag (m FilePath) -> m FilePath
forall a. a -> Flag a -> a
fromFlagOrDefault m FilePath
forall (m :: * -> *). Interactive m => m FilePath
getCurrentDirectory (Flag (m FilePath) -> m FilePath)
-> Flag (m FilePath) -> m FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> m FilePath
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (FilePath -> m FilePath) -> Flag FilePath -> Flag (m FilePath)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> InitFlags -> Flag FilePath
packageDir InitFlags
flags

  FilePath -> m Bool
forall (m :: * -> *). Interactive m => FilePath -> m Bool
doesDirectoryExist (FilePath
pkgDir FilePath -> FilePath -> FilePath
</> FilePath
"src")
    m Bool -> (Bool -> m [FilePath]) -> m [FilePath]
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= [FilePath] -> m [FilePath]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([FilePath] -> m [FilePath])
-> (Bool -> [FilePath]) -> Bool -> m [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. \case
      Bool
False -> [FilePath
defaultSourceDir]
      Bool
True -> [FilePath
"src"]

-- | Guess author and email using git configuration options.
guessAuthorName :: Interactive m => m (Maybe String)
guessAuthorName :: forall (m :: * -> *). Interactive m => m (Maybe FilePath)
guessAuthorName = FilePath -> m (Maybe FilePath)
forall (m :: * -> *).
Interactive m =>
FilePath -> m (Maybe FilePath)
guessGitInfo FilePath
"user.name"

guessAuthorEmail :: Interactive m => m (Maybe String)
guessAuthorEmail :: forall (m :: * -> *). Interactive m => m (Maybe FilePath)
guessAuthorEmail = FilePath -> m (Maybe FilePath)
forall (m :: * -> *).
Interactive m =>
FilePath -> m (Maybe FilePath)
guessGitInfo FilePath
"user.email"

guessGitInfo :: Interactive m => String -> m (Maybe String)
guessGitInfo :: forall (m :: * -> *).
Interactive m =>
FilePath -> m (Maybe FilePath)
guessGitInfo FilePath
target = do
  Maybe (ExitCode, FilePath, FilePath)
localInfo <- FilePath
-> [FilePath]
-> FilePath
-> m (Maybe (ExitCode, FilePath, FilePath))
forall (m :: * -> *).
Interactive m =>
FilePath
-> [FilePath]
-> FilePath
-> m (Maybe (ExitCode, FilePath, FilePath))
maybeReadProcessWithExitCode FilePath
"git" [FilePath
"config", FilePath
"--local", FilePath
target] FilePath
""
  case Maybe (ExitCode, FilePath, FilePath)
localInfo of
    Maybe (ExitCode, FilePath, FilePath)
Nothing -> Maybe FilePath -> m (Maybe FilePath)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe FilePath
forall a. Maybe a
Nothing
    Just (ExitCode
_, FilePath
localStdout, FilePath
_) ->
      if FilePath -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null FilePath
localStdout
        then do
          Maybe (ExitCode, FilePath, FilePath)
globalInfo <- FilePath
-> [FilePath]
-> FilePath
-> m (Maybe (ExitCode, FilePath, FilePath))
forall (m :: * -> *).
Interactive m =>
FilePath
-> [FilePath]
-> FilePath
-> m (Maybe (ExitCode, FilePath, FilePath))
maybeReadProcessWithExitCode FilePath
"git" [FilePath
"config", FilePath
"--global", FilePath
target] FilePath
""
          case Maybe (ExitCode, FilePath, FilePath)
globalInfo of
            Just (ExitCode
ExitSuccess, FilePath
globalStdout, FilePath
_) -> Maybe FilePath -> m (Maybe FilePath)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe FilePath -> m (Maybe FilePath))
-> Maybe FilePath -> m (Maybe FilePath)
forall a b. (a -> b) -> a -> b
$ FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just (FilePath -> FilePath
trim FilePath
globalStdout)
            Maybe (ExitCode, FilePath, FilePath)
_ -> Maybe FilePath -> m (Maybe FilePath)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe FilePath
forall a. Maybe a
Nothing
        else Maybe FilePath -> m (Maybe FilePath)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe FilePath -> m (Maybe FilePath))
-> Maybe FilePath -> m (Maybe FilePath)
forall a b. (a -> b) -> a -> b
$ FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just (FilePath -> FilePath
trim FilePath
localStdout)