1 {-# LANGUAGE BangPatterns #-}
3 {-# LANGUAGE DeriveGeneric #-}
4 {-# LANGUAGE FlexibleContexts #-}
5 {-# LANGUAGE FlexibleInstances #-}
7 {-# LANGUAGE InstanceSigs #-}
8 {-# LANGUAGE LambdaCase #-}
9 {-# LANGUAGE RankNTypes #-}
10 {-# LANGUAGE ScopedTypeVariables #-}
12 -----------------------------------------------------------------------------
15 -- Module : Distribution.Simple.Utils
16 -- Copyright : Isaac Jones, Simon Marlow 2003-2004
18 -- portions Copyright (c) 2007, Galois Inc.
20 -- Maintainer : cabal-devel@haskell.org
21 -- Portability : portable
23 -- A large and somewhat miscellaneous collection of utility functions used
24 -- throughout the rest of the Cabal lib and in other tools that use the Cabal
25 -- lib like @cabal-install@. It has a very simple set of logging actions. It
26 -- has low level functions for running programs, a bunch of wrappers for
27 -- various directory and file functions that do extra logging.
28 module Distribution
.Simple
.Utils
31 -- * logging and errors
51 , exceptionWithMetadata
63 , rawSystemExitWithEnv
67 , rawSystemIOWithEnvAndAction
73 -- ** 'IOData' re-export
76 -- These types are re-exported from
77 -- "Distribution.Utils.IOData" for convenience as they're
78 -- exposed in the API of 'rawSystemStdInOut'
80 , KnownIODataMode
(..)
82 , VerboseException
(..)
85 , createDirectoryIfMissingVerbose
92 , installExecutableFile
93 , installMaybeExecutableFile
94 , installOrdinaryFiles
95 , installExecutableFiles
96 , installMaybeExecutableFiles
97 , installDirectoryContents
98 , copyDirectoryRecursive
100 -- * File permissions
101 , doesExecutableExist
115 , findFileWithExtension
116 , findFileCwdWithExtension
117 , findFileWithExtension
'
118 , findAllFilesWithExtension
119 , findAllFilesCwdWithExtension
122 , getDirectoryContentsRecursive
124 -- * environment variables
128 -- * modification time
130 , existsAndIsMoreRecentThan
132 -- * temp files and dirs
133 , TempFileOptions
(..)
134 , defaultTempFileOptions
138 , withTempDirectoryEx
139 , createTempDirectory
141 -- * .cabal and .buildinfo files
146 , tryFindPackageDescCwd
147 , findHookedPackageDesc
149 -- * reading and writing files safely
161 , withUTF8FileContents
163 , normaliseLineEndings
190 , isAbsoluteOnAnyPlatform
191 , isRelativeOnAnyPlatform
192 , exceptionWithCallStackPrefix
195 import Distribution
.Compat
.Async
(waitCatch
, withAsyncNF
)
196 import Distribution
.Compat
.CopyFile
197 import Distribution
.Compat
.FilePath as FilePath
198 import Distribution
.Compat
.Internal
.TempFile
199 import Distribution
.Compat
.Lens
(Lens
', over
)
200 import Distribution
.Compat
.Prelude
201 import Distribution
.Compat
.Stack
202 import Distribution
.ModuleName
as ModuleName
203 import Distribution
.Simple
.Errors
204 import Distribution
.System
205 import Distribution
.Types
.PackageId
206 import Distribution
.Utils
.Generic
207 import Distribution
.Utils
.IOData
(IOData
(..), IODataMode
(..), KnownIODataMode
(..))
208 import qualified Distribution
.Utils
.IOData
as IOData
209 import Distribution
.Verbosity
210 import Distribution
.Version
213 #ifdef CURRENT_PACKAGE_KEY
214 #define BOOTSTRAPPED_CABAL
1
217 #ifdef BOOTSTRAPPED_CABAL
218 import qualified Paths_Cabal
(version
)
221 import Distribution
.Parsec
222 import Distribution
.Pretty
224 import qualified Data
.ByteString
.Lazy
as BS
229 import qualified Control
.Exception
as Exception
230 import Data
.Time
.Clock
.POSIX
(POSIXTime
, getPOSIXTime
)
231 import Distribution
.Compat
.Process
(proc
)
232 import Foreign
.C
.Error
(Errno
(..), ePIPE
)
233 import qualified GHC
.IO.Exception
as GHC
234 import GHC
.Stack
(HasCallStack
)
235 import Numeric
(showFFloat)
236 import System
.Directory
237 ( Permissions (executable)
241 , getDirectoryContents
242 , getModificationTime
244 , removeDirectoryRecursive
247 import System
.Environment
250 import System
.FilePath as FilePath
254 , searchPathSeparator
274 import System
.IO.Error
275 import System
.IO.Unsafe
278 import qualified System
.Process
as Process
279 import qualified Text
.PrettyPrint
as Disp
281 -- We only get our own version number when we're building with ourselves
282 cabalVersion
:: Version
283 #if defined
(BOOTSTRAPPED_CABAL
)
284 cabalVersion
= mkVersion
' Paths_Cabal
.version
285 #elif defined
(CABAL_VERSION
)
286 cabalVersion
= mkVersion
[CABAL_VERSION
]
288 cabalVersion
= mkVersion
[3,0] --used when bootstrapping
291 -- ----------------------------------------------------------------------------
292 -- Exception and logging utils
294 -- Cabal's logging infrastructure has a few constraints:
296 -- * We must make all logging formatting and emissions decisions based
297 -- on the 'Verbosity' parameter, which is the only parameter that is
298 -- plumbed to enough call-sites to actually be used for this matter.
299 -- (One of Cabal's "big mistakes" is to have never have defined a
300 -- monad of its own.)
302 -- * When we 'die', we must raise an IOError. This a backwards
303 -- compatibility consideration, because that's what we've raised
304 -- previously, and if we change to any other exception type,
305 -- exception handlers which match on IOError will no longer work.
306 -- One case where it is known we rely on IOError being catchable
307 -- is 'readPkgConfigDb' in cabal-install; there may be other
308 -- user code that also assumes this.
310 -- * The 'topHandler' does not know what 'Verbosity' is, because
311 -- it gets called before we've done command line parsing (where
312 -- the 'Verbosity' parameter would come from).
314 -- This leads to two big architectural choices:
316 -- * Although naively we might imagine 'Verbosity' to be a simple
317 -- enumeration type, actually it is a full-on abstract data type
318 -- that may contain arbitrarily complex information. At the
319 -- moment, it is fully representable as a string, but we might
320 -- eventually also use verbosity to let users register their
321 -- own logging handler.
323 -- * When we call 'die', we perform all the formatting and addition
324 -- of extra information we need, and then ship this in the IOError
325 -- to the top-level handler. Here are alternate designs that
328 -- a) Ship the unformatted info to the handler. This doesn't
329 -- work because at the point the handler gets the message,
330 -- we've lost call stacks, and even if we did, we don't have access
331 -- to 'Verbosity' to decide whether or not to render it.
333 -- b) Print the information at the 'die' site, then raise an
334 -- error. This means that if the exception is subsequently
335 -- caught by a handler, we will still have emitted the output,
336 -- which is not the correct behavior.
338 -- For the top-level handler to "know" that an error message
339 -- contains one of these fully formatted packets, we set a sentinel
340 -- in one of IOError's extra fields. This is handled by
341 -- 'ioeSetVerbatim' and 'ioeGetVerbatim'.
344 dieNoVerbosity
:: String -> IO a
346 ioError (userError msg
)
348 _
= callStack
-- TODO: Attach CallStack to exception
350 -- | Tag an 'IOError' whose error string should be output to the screen
352 ioeSetVerbatim
:: IOError -> IOError
353 ioeSetVerbatim e
= ioeSetLocation e
"dieVerbatim"
355 -- | Check if an 'IOError' should be output verbatim to screen.
356 ioeGetVerbatim
:: IOError -> Bool
357 ioeGetVerbatim e
= ioeGetLocation e
== "dieVerbatim"
359 -- | Create a 'userError' whose error text will be output verbatim
360 verbatimUserError
:: String -> IOError
361 verbatimUserError
= ioeSetVerbatim
. userError
363 dieWithLocation
' :: Verbosity
-> FilePath -> Maybe Int -> String -> IO a
364 dieWithLocation
' verbosity filename mb_lineno msg
=
367 ++ ( case mb_lineno
of
368 Just lineno
-> ":" ++ show lineno
374 die
' :: Verbosity
-> String -> IO a
375 die
' verbosity msg
= withFrozenCallStack
$ do
376 ioError . verbatimUserError
377 =<< annotateErrorString verbosity
378 =<< pure
. wrapTextVerbosity verbosity
379 =<< pure
. addErrorPrefix
380 =<< prefixWithProgName msg
382 -- Type which will be a wrapper for cabal -expections and cabal-install exceptions
383 data VerboseException a
= VerboseException CallStack POSIXTime Verbosity a
384 deriving (Show, Typeable
)
386 -- Function which will replace the existing die' call sites
387 dieWithException
:: (HasCallStack
, Show a1
, Typeable a1
, Exception
(VerboseException a1
)) => Verbosity
-> a1
-> IO a
388 dieWithException verbosity exception
= do
390 throwIO
$ VerboseException callStack ts verbosity exception
392 -- Instance for Cabal Exception which will display error code and error message with callStack info
393 instance Exception
(VerboseException CabalException
) where
394 displayException
:: VerboseException CabalException
-> [Char]
395 displayException
(VerboseException stack timestamp verb cabalexception
) =
400 , show (exceptionCode cabalexception
)
404 ++ exceptionWithMetadata stack timestamp verb
(exceptionMessage cabalexception
)
406 dieNoWrap
:: Verbosity
-> String -> IO a
407 dieNoWrap verbosity msg
= withFrozenCallStack
$ do
408 -- TODO: should this have program name or not?
409 ioError . verbatimUserError
410 =<< annotateErrorString
414 -- | Prefixing a message to indicate that it is a fatal error,
415 -- if the 'errorPrefix' is not already present.
416 addErrorPrefix
:: String -> String
418 | errorPrefix `
isPrefixOf` msg
= msg
419 -- Backpack prefixes its errors already with "Error:", see
420 -- 'Distribution.Utils.LogProgress.dieProgress'.
421 -- Taking it away there destroys the layout, so we rather
422 -- check here whether the prefix is already present.
423 |
otherwise = unwords [errorPrefix
, msg
]
425 -- | A prefix indicating that a message is a fatal error.
426 errorPrefix
:: String
427 errorPrefix
= "Error:"
429 -- | Prefix an error string with program name from 'getProgName'
430 prefixWithProgName
:: String -> IO String
431 prefixWithProgName msg
= do
433 return $ pname
++ ": " ++ msg
435 -- | Annotate an error string with timestamp and 'withMetadata'.
436 annotateErrorString
:: Verbosity
-> String -> IO String
437 annotateErrorString verbosity msg
= do
439 return $ withMetadata ts AlwaysMark VerboseTrace verbosity msg
441 -- | Given a block of IO code that may raise an exception, annotate
442 -- it with the metadata from the current scope. Use this as close
443 -- to external code that raises IO exceptions as possible, since
444 -- this function unconditionally wraps the error message with a trace
445 -- (so it is NOT idempotent.)
446 annotateIO
:: Verbosity
-> IO a
-> IO a
447 annotateIO verbosity act
= do
449 flip modifyIOError act
$
450 ioeModifyErrorString
$
451 withMetadata ts NeverMark VerboseTrace verbosity
453 -- | A semantic editor for the error message inside an 'IOError'.
454 ioeModifyErrorString
:: (String -> String) -> IOError -> IOError
455 ioeModifyErrorString
= over ioeErrorString
457 -- | A lens for the error message inside an 'IOError'.
458 ioeErrorString
:: Lens
' IOError String
459 ioeErrorString f ioe
= ioeSetErrorString ioe
<$> f
(ioeGetErrorString ioe
)
461 {-# NOINLINE topHandlerWith #-}
462 topHandlerWith
:: forall a
. (Exception
.SomeException
-> IO a
) -> IO a
-> IO a
463 topHandlerWith cont prog
= do
464 -- By default, stderr to a terminal device is NoBuffering. But this
466 hSetBuffering stderr LineBuffering
469 [ Exception
.Handler rethrowAsyncExceptions
470 , Exception
.Handler rethrowExitStatus
471 , Exception
.Handler handle
474 -- Let async exceptions rise to the top for the default top-handler
475 rethrowAsyncExceptions
:: Exception
.AsyncException
-> IO a
476 rethrowAsyncExceptions a
= throwIO a
478 -- ExitCode gets thrown asynchronously too, and we don't want to print it
479 rethrowExitStatus
:: ExitCode -> IO a
480 rethrowExitStatus
= throwIO
482 -- Print all other exceptions
483 handle
:: Exception
.SomeException
-> IO a
487 hPutStr stderr (message pname se
)
490 message
:: String -> Exception
.SomeException
-> String
491 message pname
(Exception
.SomeException se
) =
492 case cast se
:: Maybe Exception
.IOException
of
494 | ioeGetVerbatim ioe
->
495 -- Use the message verbatim
496 ioeGetErrorString ioe
++ "\n"
498 let file
= case ioeGetFileName ioe
of
500 Just path
-> path
++ location
++ ": "
501 location
= case ioeGetLocation ioe
of
502 l
@(n
: _
) |
isDigit n
-> ':' : l
504 detail
= ioeGetErrorString ioe
505 in wrapText
$ addErrorPrefix
$ pname
++ ": " ++ file
++ detail
507 displaySomeException se
++ "\n"
509 -- | BC wrapper around 'Exception.displayException'.
510 displaySomeException
:: Exception
.Exception e
=> e
-> String
511 displaySomeException se
= Exception
.displayException se
513 topHandler
:: IO a
-> IO a
514 topHandler prog
= topHandlerWith
(const $ exitWith (ExitFailure
1)) prog
516 -- | Depending on 'isVerboseStderr', set the output handle to 'stderr' or 'stdout'.
517 verbosityHandle
:: Verbosity
-> Handle
518 verbosityHandle verbosity
519 | isVerboseStderr verbosity
= stderr
522 -- | Non fatal conditions that may be indicative of an error or problem.
524 -- We display these at the 'normal' verbosity level.
525 warn
:: Verbosity
-> String -> IO ()
526 warn verbosity msg
= warnMessage
"Warning" verbosity msg
528 -- | Like 'warn', but prepend @Error: …@ instead of @Waring: …@ before the
529 -- the message. Useful when you want to highlight the condition is an error
530 -- but do not want to quit the program yet.
531 warnError
:: Verbosity
-> String -> IO ()
532 warnError verbosity message
= warnMessage
"Error" verbosity message
534 -- | Warning message, with a custom label.
535 warnMessage
:: String -> Verbosity
-> String -> IO ()
536 warnMessage l verbosity msg
= withFrozenCallStack
$ do
537 when ((verbosity
>= normal
) && not (isVerboseNoWarn verbosity
)) $ do
541 . withMetadata ts NormalMark FlagTrace verbosity
542 . wrapTextVerbosity verbosity
545 -- | Useful status messages.
547 -- We display these at the 'normal' verbosity level.
549 -- This is for the ordinary helpful status messages that users see. Just
550 -- enough information to know that things are working but not floods of detail.
551 notice
:: Verbosity
-> String -> IO ()
552 notice verbosity msg
= withFrozenCallStack
$ do
553 when (verbosity
>= normal
) $ do
554 let h
= verbosityHandle verbosity
557 withMetadata ts NormalMark FlagTrace verbosity
$
558 wrapTextVerbosity verbosity
$
561 -- | Display a message at 'normal' verbosity level, but without
563 noticeNoWrap
:: Verbosity
-> String -> IO ()
564 noticeNoWrap verbosity msg
= withFrozenCallStack
$ do
565 when (verbosity
>= normal
) $ do
566 let h
= verbosityHandle verbosity
568 hPutStr h
. withMetadata ts NormalMark FlagTrace verbosity
$ msg
570 -- | Pretty-print a 'Disp.Doc' status message at 'normal' verbosity
571 -- level. Use this if you need fancy formatting.
572 noticeDoc
:: Verbosity
-> Disp
.Doc
-> IO ()
573 noticeDoc verbosity msg
= withFrozenCallStack
$ do
574 when (verbosity
>= normal
) $ do
575 let h
= verbosityHandle verbosity
578 withMetadata ts NormalMark FlagTrace verbosity
$
579 Disp
.renderStyle defaultStyle
$
582 -- | Display a "setup status message". Prefer using setupMessage'
584 setupMessage
:: Verbosity
-> String -> PackageIdentifier
-> IO ()
585 setupMessage verbosity msg pkgid
= withFrozenCallStack
$ do
586 noticeNoWrap verbosity
(msg
++ ' ' : prettyShow pkgid
++ "...")
588 -- | More detail on the operation of some action.
590 -- We display these messages when the verbosity level is 'verbose'
591 info
:: Verbosity
-> String -> IO ()
592 info verbosity msg
= withFrozenCallStack
$
593 when (verbosity
>= verbose
) $ do
594 let h
= verbosityHandle verbosity
597 withMetadata ts NeverMark FlagTrace verbosity
$
598 wrapTextVerbosity verbosity
$
601 infoNoWrap
:: Verbosity
-> String -> IO ()
602 infoNoWrap verbosity msg
= withFrozenCallStack
$
603 when (verbosity
>= verbose
) $ do
604 let h
= verbosityHandle verbosity
607 withMetadata ts NeverMark FlagTrace verbosity
$
610 -- | Detailed internal debugging information
612 -- We display these messages when the verbosity level is 'deafening'
613 debug
:: Verbosity
-> String -> IO ()
614 debug verbosity msg
= withFrozenCallStack
$
615 when (verbosity
>= deafening
) $ do
616 let h
= verbosityHandle verbosity
619 withMetadata ts NeverMark FlagTrace verbosity
$
620 wrapTextVerbosity verbosity
$
622 -- ensure that we don't lose output if we segfault/infinite loop
625 -- | A variant of 'debug' that doesn't perform the automatic line
626 -- wrapping. Produces better output in some cases.
627 debugNoWrap
:: Verbosity
-> String -> IO ()
628 debugNoWrap verbosity msg
= withFrozenCallStack
$
629 when (verbosity
>= deafening
) $ do
630 let h
= verbosityHandle verbosity
633 withMetadata ts NeverMark FlagTrace verbosity
$
635 -- ensure that we don't lose output if we segfault/infinite loop
638 -- | Perform an IO action, catching any IO exceptions and printing an error
642 -- ^ a description of the action we were attempting
644 -- ^ the action itself
646 chattyTry desc action
=
647 catchIO action
$ \exception
->
648 hPutStrLn stderr $ "Error while " ++ desc
++ ": " ++ show exception
650 -- | Run an IO computation, returning @e@ if it raises a "file
651 -- does not exist" error.
652 handleDoesNotExist
:: a
-> IO a
-> IO a
653 handleDoesNotExist e
=
655 (\ioe
-> if isDoesNotExistError ioe
then Just ioe
else Nothing
)
658 -- -----------------------------------------------------------------------------
661 -- | Wraps text unless the @+nowrap@ verbosity flag is active
662 wrapTextVerbosity
:: Verbosity
-> String -> String
663 wrapTextVerbosity verb
664 | isVerboseNoWrap verb
= withTrailingNewline
665 |
otherwise = withTrailingNewline
. wrapText
667 -- | Prepends a timestamp if @+timestamp@ verbosity flag is set
669 -- This is used by 'withMetadata'
670 withTimestamp
:: Verbosity
-> POSIXTime
-> String -> String
671 withTimestamp v ts msg
672 | isVerboseTimestamp v
= msg
'
673 |
otherwise = msg
-- no-op
675 msg
' = case lines msg
of
677 l1
: rest
-> unlines (tsstr
(' ' : l1
) : map (contpfx
++) rest
)
679 -- format timestamp to be prepended to first line with msec precision
680 tsstr
= showFFloat (Just
3) (realToFrac ts
:: Double)
682 -- continuation prefix for subsequent lines of msg
683 contpfx
= replicate (length (tsstr
" ")) ' '
685 -- | Wrap output with a marker if @+markoutput@ verbosity flag is set.
687 -- NB: Why is markoutput done with start/end markers, and not prefixes?
688 -- Markers are more convenient to add (if we want to add prefixes,
689 -- we have to 'lines' and then 'map'; here's it's just some
690 -- concatenates). Note that even in the prefix case, we can't
691 -- guarantee that the markers are unambiguous, because some of
692 -- Cabal's output comes straight from external programs, where
693 -- we don't have the ability to interpose on the output.
695 -- This is used by 'withMetadata'
696 withOutputMarker
:: Verbosity
-> String -> String
697 withOutputMarker v xs |
not (isVerboseMarkOutput v
) = xs
698 withOutputMarker _
"" = "" -- Minor optimization, don't mark uselessly
699 withOutputMarker _ xs
=
700 "-----BEGIN CABAL OUTPUT-----\n"
701 ++ withTrailingNewline xs
702 ++ "-----END CABAL OUTPUT-----\n"
704 -- | Append a trailing newline to a string if it does not
705 -- already have a trailing newline.
706 withTrailingNewline
:: String -> String
707 withTrailingNewline
"" = ""
708 withTrailingNewline
(x
: xs
) = x
: go x xs
710 go _
(c
: cs
) = c
: go c cs
714 -- | Prepend a call-site and/or call-stack based on Verbosity
715 withCallStackPrefix
:: WithCallStack
(TraceWhen
-> Verbosity
-> String -> String)
716 withCallStackPrefix tracer verbosity s
=
717 withFrozenCallStack
$
718 ( if isVerboseCallSite verbosity
722 -- Hack: need a newline before starting output marker :(
723 if isVerboseMarkOutput verbosity
728 ++ ( case traceWhen verbosity tracer
of
729 Just pre
-> pre
++ prettyCallStack callStack
++ "\n"
734 -- | When should we emit the call stack? We always emit
735 -- for internal errors, emit the trace for errors when we
736 -- are in verbose mode, and otherwise only emit it if
737 -- explicitly asked for using the @+callstack@ verbosity
738 -- flag. (At the moment, 'AlwaysTrace' is not used.
745 -- | Determine if we should emit a call stack.
746 -- If we trace, it also emits any prefix we should append.
747 traceWhen
:: Verbosity
-> TraceWhen
-> Maybe String
748 traceWhen _ AlwaysTrace
= Just
""
749 traceWhen v VerboseTrace | v
>= verbose
= Just
""
750 traceWhen v FlagTrace | isVerboseCallStack v
= Just
"----\n"
751 traceWhen _ _
= Nothing
753 -- | When should we output the marker? Things like 'die'
754 -- always get marked, but a 'NormalMark' will only be
755 -- output if we're not a quiet verbosity.
756 data MarkWhen
= AlwaysMark | NormalMark | NeverMark
758 -- | Add all necessary metadata to a logging message
759 withMetadata
:: WithCallStack
(POSIXTime
-> MarkWhen
-> TraceWhen
-> Verbosity
-> String -> String)
760 withMetadata ts marker tracer verbosity x
=
763 -- NB: order matters. Output marker first because we
764 -- don't want to capture call stacks.
766 . withCallStackPrefix tracer verbosity
768 AlwaysMark
-> withOutputMarker verbosity
770 |
not (isVerboseQuiet verbosity
) ->
771 withOutputMarker verbosity
776 -- Clear out any existing markers
778 . withTimestamp verbosity ts
781 -- | Add all necessary metadata to a logging message
782 exceptionWithMetadata
:: CallStack
-> POSIXTime
-> Verbosity
-> String -> String
783 exceptionWithMetadata stack ts verbosity x
=
785 . exceptionWithCallStackPrefix stack verbosity
786 . withOutputMarker verbosity
788 . withTimestamp verbosity ts
791 clearMarkers
:: String -> String
792 clearMarkers s
= unlines . filter isMarker
$ lines s
794 isMarker
"-----BEGIN CABAL OUTPUT-----" = False
795 isMarker
"-----END CABAL OUTPUT-----" = False
798 -- | Append a call-site and/or call-stack based on Verbosity
799 exceptionWithCallStackPrefix
:: CallStack
-> Verbosity
-> String -> String
800 exceptionWithCallStackPrefix stack verbosity s
=
802 ++ withFrozenCallStack
803 ( ( if isVerboseCallSite verbosity
807 -- Hack: need a newline before starting output marker :(
808 if isVerboseMarkOutput verbosity
813 ++ ( if verbosity
>= verbose
814 then prettyCallStack stack
++ "\n"
819 -- -----------------------------------------------------------------------------
820 -- rawSystem variants
822 -- These all use 'Distribution.Compat.Process.proc' to ensure we
823 -- consistently use process jobs on Windows and Ctrl-C delegation
826 -- Additionally, they take care of logging command execution.
829 -- | Helper to use with one of the 'rawSystem' variants, and exit
830 -- unless the command completes successfully.
831 maybeExit
:: IO ExitCode -> IO ()
834 unless (exitcode
== ExitSuccess
) $ exitWith exitcode
836 -- | Log a command execution (that's typically about to happen)
837 -- at info level, and log working directory and environment overrides
838 -- at debug level if specified.
839 logCommand
:: Verbosity
-> Process
.CreateProcess
-> IO ()
840 logCommand verbosity cp
= do
841 infoNoWrap verbosity
$
842 "Running: " <> case Process
.cmdspec cp
of
843 Process
.ShellCommand sh
-> sh
844 Process
.RawCommand path args
-> Process
.showCommandForUser path args
845 case Process
.env cp
of
846 Just env
-> debugNoWrap verbosity
$ "with environment: " ++ show env
848 case Process
.cwd cp
of
849 Just cwd
-> debugNoWrap verbosity
$ "with working directory: " ++ show cwd
853 -- | Execute the given command with the given arguments, exiting
854 -- with the same exit code if the command fails.
855 rawSystemExit
:: Verbosity
-> FilePath -> [String] -> IO ()
856 rawSystemExit verbosity path args
=
857 withFrozenCallStack
$
859 rawSystemExitCode verbosity path args
861 -- | Execute the given command with the given arguments, returning
862 -- the command's exit code.
863 rawSystemExitCode
:: Verbosity
-> FilePath -> [String] -> IO ExitCode
864 rawSystemExitCode verbosity path args
=
865 withFrozenCallStack
$
866 rawSystemProc verbosity
$
869 -- | Execute the given command with the given arguments, returning
870 -- the command's exit code.
872 -- Create the process argument with 'Distribution.Compat.Process.proc'
873 -- to ensure consistent options with other 'rawSystem' functions in this
875 rawSystemProc
:: Verbosity
-> Process
.CreateProcess
-> IO ExitCode
876 rawSystemProc verbosity cp
= withFrozenCallStack
$ do
877 (exitcode
, _
) <- rawSystemProcAction verbosity cp
$ \_ _ _
-> return ()
880 -- | Execute the given command with the given arguments, returning
881 -- the command's exit code. 'action' is executed while the command
882 -- is running, and would typically be used to communicate with the
883 -- process through pipes.
885 -- Create the process argument with 'Distribution.Compat.Process.proc'
886 -- to ensure consistent options with other 'rawSystem' functions in this
890 -> Process
.CreateProcess
891 -> (Maybe Handle -> Maybe Handle -> Maybe Handle -> IO a
)
893 rawSystemProcAction verbosity cp action
= withFrozenCallStack
$ do
894 logCommand verbosity cp
895 (exitcode
, a
) <- Process
.withCreateProcess cp
$ \mStdin mStdout mStderr p
-> do
896 a
<- action mStdin mStdout mStderr
897 exitcode
<- Process
.waitForProcess p
899 unless (exitcode
== ExitSuccess
) $ do
900 let cmd
= case Process
.cmdspec cp
of
901 Process
.ShellCommand sh
-> sh
902 Process
.RawCommand path _args
-> path
903 debug verbosity
$ cmd
++ " returned " ++ show exitcode
906 -- | fromJust for dealing with 'Maybe Handle' values as obtained via
907 -- 'System.Process.CreatePipe'. Creating a pipe using 'CreatePipe' guarantees
908 -- a 'Just' value for the corresponding handle.
909 fromCreatePipe
:: Maybe Handle -> Handle
910 fromCreatePipe
= maybe (error "fromCreatePipe: Nothing") id
912 -- | Execute the given command with the given arguments and
913 -- environment, exiting with the same exit code if the command fails.
918 -> [(String, String)]
920 rawSystemExitWithEnv verbosity path args env
=
921 withFrozenCallStack
$
923 rawSystemProc verbosity
$
925 { Process
.env
= Just env
928 -- | Execute the given command with the given arguments, returning
929 -- the command's exit code.
931 -- Optional arguments allow setting working directory, environment
932 -- and input and output handles.
938 -- ^ New working dir or inherit
939 -> Maybe [(String, String)]
940 -- ^ New environment or inherit
948 rawSystemIOWithEnv verbosity path args mcwd menv inp out err
= withFrozenCallStack
$ do
950 rawSystemIOWithEnvAndAction
964 -- | Execute the given command with the given arguments, returning
965 -- the command's exit code. 'action' is executed while the command
966 -- is running, and would typically be used to communicate with the
967 -- process through pipes.
969 -- Optional arguments allow setting working directory, environment
970 -- and input and output handles.
971 rawSystemIOWithEnvAndAction
976 -- ^ New working dir or inherit
977 -> Maybe [(String, String)]
978 -- ^ New environment or inherit
980 -- ^ action to perform after process is created, but before 'waitForProcess'.
988 rawSystemIOWithEnvAndAction verbosity path args mcwd menv action inp out err
= withFrozenCallStack
$ do
993 , Process
.std_in
= mbToStd inp
994 , Process
.std_out
= mbToStd out
995 , Process
.std_err
= mbToStd err
997 rawSystemProcAction verbosity cp
(\_ _ _
-> action
)
999 mbToStd
:: Maybe Handle -> Process
.StdStream
1000 mbToStd
= maybe Process
.Inherit Process
.UseHandle
1002 -- | Execute the given command with the given arguments, returning
1003 -- the command's output. Exits if the command exits with error.
1005 -- Provides control over the binary/text mode of the output.
1006 rawSystemStdout
:: forall mode
. KnownIODataMode mode
=> Verbosity
-> FilePath -> [String] -> IO mode
1007 rawSystemStdout verbosity path args
= withFrozenCallStack
$ do
1008 (output
, errors
, exitCode
) <-
1016 (IOData
.iodataMode
:: IODataMode mode
)
1017 when (exitCode
/= ExitSuccess
) $
1018 dieWithException verbosity
$
1019 RawSystemStdout errors
1022 -- | Execute the given command with the given arguments, returning
1023 -- the command's output, errors and exit code.
1025 -- Optional arguments allow setting working directory, environment
1026 -- and command input.
1028 -- Provides control over the binary/text mode of the input and output.
1030 :: KnownIODataMode mode
1033 -- ^ Program location
1037 -- ^ New working dir or inherit
1038 -> Maybe [(String, String)]
1039 -- ^ New environment or inherit
1041 -- ^ input text and binary mode
1043 -- ^ iodata mode, acts as proxy
1044 -> IO (mode
, String, ExitCode)
1045 -- ^ output, errors, exit
1046 rawSystemStdInOut verbosity path args mcwd menv input _
= withFrozenCallStack
$ do
1049 { Process
.cwd
= mcwd
1050 , Process
.env
= menv
1051 , Process
.std_in
= Process
.CreatePipe
1052 , Process
.std_out
= Process
.CreatePipe
1053 , Process
.std_err
= Process
.CreatePipe
1056 (exitcode
, (mberr1
, mberr2
)) <- rawSystemProcAction verbosity cp
$ \mb_in mb_out mb_err
-> do
1057 let (inh
, outh
, errh
) = (fromCreatePipe mb_in
, fromCreatePipe mb_out
, fromCreatePipe mb_err
)
1058 flip Exception
.finally
(hClose inh
>> hClose outh
>> hClose errh
) $ do
1059 -- output mode depends on what the caller wants
1060 -- but the errors are always assumed to be text (in the current locale)
1061 hSetBinaryMode errh
False
1063 -- fork off a couple threads to pull on the stderr and stdout
1064 -- so if the process writes to stderr we do not block.
1066 withAsyncNF
(hGetContents errh
) $ \errA
-> withAsyncNF
(IOData
.hGetIODataContents outh
) $ \outA
-> do
1067 -- push all the input, if any
1068 ignoreSigPipe
$ case input
of
1069 Nothing
-> hClose inh
1070 Just inputData
-> IOData
.hPutContents inh inputData
1072 -- wait for both to finish
1073 mberr1
<- waitCatch outA
1074 mberr2
<- waitCatch errA
1075 return (mberr1
, mberr2
)
1077 -- get the stderr, so it can be added to error message
1078 err
<- reportOutputIOError mberr2
1080 unless (exitcode
== ExitSuccess
) $
1088 " with error message:\n"
1092 Just d | IOData
.null d
-> ""
1093 Just
(IODataText inp
) -> "\nstdin input:\n" ++ inp
1094 Just
(IODataBinary inp
) -> "\nstdin input (binary):\n" ++ show inp
1096 -- Check if we hit an exception while consuming the output
1097 -- (e.g. a text decoding error)
1098 out
<- reportOutputIOError mberr1
1100 return (out
, err
, exitcode
)
1102 reportOutputIOError
:: Either Exception
.SomeException a
-> IO a
1103 reportOutputIOError
(Right x
) = return x
1104 reportOutputIOError
(Left exc
) = case fromException exc
of
1105 Just ioe
-> throwIO
(ioeSetFileName ioe
("output of " ++ path
))
1106 Nothing
-> throwIO exc
1108 -- | Ignore SIGPIPE in a subcomputation.
1109 ignoreSigPipe
:: IO () -> IO ()
1110 ignoreSigPipe
= Exception
.handle
$ \case
1111 GHC
.IOError{GHC
.ioe_type
= GHC
.ResourceVanished
, GHC
.ioe_errno
= Just ioe
}
1112 | Errno ioe
== ePIPE
-> return ()
1115 -- | Look for a program and try to find it's version number. It can accept
1116 -- either an absolute path or the name of a program binary, in which case we
1117 -- will look for the program on the path.
1121 -> (String -> String)
1122 -- ^ function to select version
1123 -- number from program output
1127 -> IO (Maybe Version
)
1128 findProgramVersion versionArg selectVersion verbosity path
= withFrozenCallStack
$ do
1130 rawSystemStdout verbosity path
[versionArg
]
1131 `catchIO`
(\_
-> return "")
1132 `
catch`
(\(_
:: VerboseException CabalException
) -> return "")
1133 `catchExit`
(\_
-> return "")
1134 let version
:: Maybe Version
1135 version
= simpleParsec
(selectVersion str
)
1139 "cannot determine version of "
1143 Just v
-> debug verbosity
$ path
++ " is version " ++ prettyShow v
1146 -- | Like the Unix xargs program. Useful for when we've got very long command
1147 -- lines that might overflow an OS limit on command line length and so you
1148 -- need to invoke a command multiple times to get all the args in.
1150 -- Use it with either of the rawSystem variants above. For example:
1152 -- > xargs (32*1024) (rawSystemExit verbosity) prog fixedArgs bigArgs
1155 -> ([String] -> IO ())
1159 xargs maxSize rawSystemFun fixedArgs bigArgs
=
1160 let fixedArgSize
= sum (map length fixedArgs
) + length fixedArgs
1161 chunkSize
= maxSize
- fixedArgSize
1162 in traverse_
(rawSystemFun
. (fixedArgs
++)) (chunks chunkSize bigArgs
)
1164 chunks len
= unfoldr $ \s
->
1167 else Just
(chunk
[] len s
)
1169 chunk acc _
[] = (reverse acc
, [])
1170 chunk acc len
(s
: ss
)
1171 | len
' < len
= chunk
(s
: acc
) (len
- len
' - 1) ss
1172 |
otherwise = (reverse acc
, s
: ss
)
1176 -- ------------------------------------------------------------
1180 -- ------------------------------------------------------------
1185 -- | Find a file by looking in a search path. The file path must match exactly.
1193 -- ^ relative search location
1197 findFileCwd verbosity cwd searchPath fileName
=
1201 | path
<- nub searchPath
1203 >>= maybe (dieWithException verbosity
$ FindFileCwd fileName
) return
1205 -- | Find a file by looking in a search path. The file path must match exactly.
1209 -- ^ search locations
1213 findFileEx verbosity searchPath fileName
=
1217 | path
<- nub searchPath
1219 >>= maybe (dieWithException verbosity
$ FindFileEx fileName
) return
1221 -- | Find a file by looking in a search path with one of a list of possible
1222 -- file extensions. The file base name should be given and it will be tried
1223 -- with each of the extensions in each element of the search path.
1224 findFileWithExtension
1228 -> IO (Maybe FilePath)
1229 findFileWithExtension extensions searchPath baseName
=
1232 [ path
</> baseName
<.> ext
1233 | path
<- nub searchPath
1234 , ext
<- nub extensions
1238 findFileCwdWithExtension
1243 -> IO (Maybe FilePath)
1244 findFileCwdWithExtension cwd extensions searchPath baseName
=
1247 [ path
</> baseName
<.> ext
1248 | path
<- nub searchPath
1249 , ext
<- nub extensions
1253 findAllFilesCwdWithExtension
1259 -- ^ relative search locations
1263 findAllFilesCwdWithExtension cwd extensions searchPath basename
=
1266 [ path
</> basename
<.> ext
1267 | path
<- nub searchPath
1268 , ext
<- nub extensions
1271 findAllFilesWithExtension
1276 findAllFilesWithExtension extensions searchPath basename
=
1279 [ path
</> basename
<.> ext
1280 | path
<- nub searchPath
1281 , ext
<- nub extensions
1284 -- | Like 'findFileWithExtension' but returns which element of the search path
1285 -- the file was found in, and the file path relative to that base directory.
1286 findFileWithExtension
'
1290 -> IO (Maybe (FilePath, FilePath))
1291 findFileWithExtension
' extensions searchPath baseName
=
1294 [ (path
, baseName
<.> ext
)
1295 | path
<- nub searchPath
1296 , ext
<- nub extensions
1299 findFirstFile
:: (a
-> FilePath) -> [a
] -> IO (Maybe a
)
1300 findFirstFile file
= findFirst
1302 findFirst
[] = return Nothing
1303 findFirst
(x
: xs
) = do
1304 exists
<- doesFileExist (file x
)
1306 then return (Just x
)
1309 findAllFiles
:: (a
-> FilePath) -> [a
] -> IO [a
]
1310 findAllFiles file
= filterM (doesFileExist . file
)
1312 -- | Finds the files corresponding to a list of Haskell module names.
1314 -- As 'findModuleFile' but for a list of module names.
1318 -- ^ build prefix (location of objects)
1320 -- ^ search suffixes
1323 -> IO [(FilePath, FilePath)]
1324 findModuleFilesEx verbosity searchPath extensions moduleNames
=
1325 traverse
(findModuleFileEx verbosity searchPath extensions
) moduleNames
1327 -- | Find the file corresponding to a Haskell module name.
1329 -- This is similar to 'findFileWithExtension'' but specialised to a module
1330 -- name. The function fails if the file corresponding to the module is missing.
1334 -- ^ build prefix (location of objects)
1336 -- ^ search suffixes
1339 -> IO (FilePath, FilePath)
1340 findModuleFileEx verbosity searchPath extensions mod_name
=
1341 maybe notFound
return
1342 =<< findFileWithExtension
'
1345 (ModuleName
.toFilePath mod_name
)
1348 dieWithException verbosity
$ FindModuleFileEx mod_name extensions searchPath
1350 -- | List all the files in a directory and all subdirectories.
1352 -- The order places files in sub-directories after all the files in their
1353 -- parent directories. The list is generated lazily so is not well defined if
1354 -- the source directory structure changes before the list is used.
1355 getDirectoryContentsRecursive
:: FilePath -> IO [FilePath]
1356 getDirectoryContentsRecursive topdir
= recurseDirectories
[""]
1358 recurseDirectories
:: [FilePath] -> IO [FilePath]
1359 recurseDirectories
[] = return []
1360 recurseDirectories
(dir
: dirs
) = unsafeInterleaveIO
$ do
1361 (files
, dirs
') <- collect
[] [] =<< getDirectoryContents (topdir
</> dir
)
1362 files
' <- recurseDirectories
(dirs
' ++ dirs
)
1363 return (files
++ files
')
1365 collect files dirs
' [] =
1370 collect files dirs
' (entry
: entries
)
1372 collect files dirs
' entries
1373 collect files dirs
' (entry
: entries
) = do
1374 let dirEntry
= dir
</> entry
1375 isDirectory
<- doesDirectoryExist (topdir
</> dirEntry
)
1377 then collect files
(dirEntry
: dirs
') entries
1378 else collect
(dirEntry
: files
) dirs
' entries
1381 ignore
['.', '.'] = True
1384 ------------------------
1385 -- Environment variables
1387 -- | Is this directory in the system search path?
1388 isInSearchPath
:: FilePath -> IO Bool
1389 isInSearchPath path
= fmap (elem path
) getSearchPath
1394 -> [(String, String)]
1395 -> [(String, String)]
1396 addLibraryPath os paths
= addEnv
1398 pathsString
= intercalate
[searchPathSeparator
] paths
1400 OSX
-> "DYLD_LIBRARY_PATH"
1401 _
-> "LD_LIBRARY_PATH"
1403 addEnv
[] = [(ldPath
, pathsString
)]
1404 addEnv
((key
, value) : xs
)
1407 then (key
, pathsString
) : xs
1408 else (key
, value ++ (searchPathSeparator
: pathsString
)) : xs
1409 |
otherwise = (key
, value) : addEnv xs
1411 --------------------
1412 -- Modification time
1414 -- | Compare the modification times of two files to see if the first is newer
1415 -- than the second. The first file must exist but the second need not.
1416 -- The expected use case is when the second file is generated using the first.
1417 -- In this use case, if the result is True then the second file is out of date.
1418 moreRecentFile
:: FilePath -> FilePath -> IO Bool
1419 moreRecentFile a b
= do
1420 exists
<- doesFileExist b
1424 tb
<- getModificationTime b
1425 ta
<- getModificationTime a
1428 -- | Like 'moreRecentFile', but also checks that the first file exists.
1429 existsAndIsMoreRecentThan
:: FilePath -> FilePath -> IO Bool
1430 existsAndIsMoreRecentThan a b
= do
1431 exists
<- doesFileExist a
1434 else a `moreRecentFile` b
1436 ----------------------------------------
1437 -- Copying and installing files and dirs
1439 -- | Same as 'createDirectoryIfMissing' but logs at higher verbosity levels.
1440 createDirectoryIfMissingVerbose
1443 -- ^ Create its parents too?
1446 createDirectoryIfMissingVerbose verbosity create_parents path0
1447 | create_parents
= withFrozenCallStack
$ createDirs
(parents path0
)
1448 |
otherwise = withFrozenCallStack
$ createDirs
(take 1 (parents path0
))
1450 parents
= reverse . scanl1 (</>) . splitDirectories
. normalise
1452 createDirs
[] = return ()
1453 createDirs
(dir
: []) = createDir dir throwIO
1454 createDirs
(dir
: dirs
) =
1455 createDir dir
$ \_
-> do
1457 createDir dir throwIO
1459 createDir
:: FilePath -> (IOException
-> IO ()) -> IO ()
1460 createDir dir notExistHandler
= do
1461 r
<- tryIO
$ createDirectoryVerbose verbosity dir
1462 case (r
:: Either IOException
()) of
1463 Right
() -> return ()
1465 |
isDoesNotExistError e
-> notExistHandler e
1466 -- createDirectory (and indeed POSIX mkdir) does not distinguish
1467 -- between a dir already existing and a file already existing. So we
1468 -- check for it here. Unfortunately there is a slight race condition
1469 -- here, but we think it is benign. It could report an exception in
1470 -- the case that the dir did exist but another process deletes the
1471 -- directory and creates a file in its place before we can check
1472 -- that the directory did indeed exist.
1473 |
isAlreadyExistsError e
->
1475 isDir
<- doesDirectoryExist dir
1476 unless isDir
$ throwIO e
1478 `catchIO`
((\_
-> return ()) :: IOException
-> IO ())
1479 |
otherwise -> throwIO e
1481 createDirectoryVerbose
:: Verbosity
-> FilePath -> IO ()
1482 createDirectoryVerbose verbosity dir
= withFrozenCallStack
$ do
1483 info verbosity
$ "creating " ++ dir
1487 -- | Copies a file without copying file permissions. The target file is created
1488 -- with default permissions. Any existing target file is replaced.
1490 -- At higher verbosity levels it logs an info message.
1491 copyFileVerbose
:: Verbosity
-> FilePath -> FilePath -> IO ()
1492 copyFileVerbose verbosity src dest
= withFrozenCallStack
$ do
1493 info verbosity
("copy " ++ src
++ " to " ++ dest
)
1496 -- | Install an ordinary file. This is like a file copy but the permissions
1497 -- are set appropriately for an installed file. On Unix it is \"-rw-r--r--\"
1498 -- while on Windows it uses the default permissions for the target directory.
1499 installOrdinaryFile
:: Verbosity
-> FilePath -> FilePath -> IO ()
1500 installOrdinaryFile verbosity src dest
= withFrozenCallStack
$ do
1501 info verbosity
("Installing " ++ src
++ " to " ++ dest
)
1502 copyOrdinaryFile src dest
1504 -- | Install an executable file. This is like a file copy but the permissions
1505 -- are set appropriately for an installed file. On Unix it is \"-rwxr-xr-x\"
1506 -- while on Windows it uses the default permissions for the target directory.
1507 installExecutableFile
:: Verbosity
-> FilePath -> FilePath -> IO ()
1508 installExecutableFile verbosity src dest
= withFrozenCallStack
$ do
1509 info verbosity
("Installing executable " ++ src
++ " to " ++ dest
)
1510 copyExecutableFile src dest
1512 -- | Install a file that may or not be executable, preserving permissions.
1513 installMaybeExecutableFile
:: Verbosity
-> FilePath -> FilePath -> IO ()
1514 installMaybeExecutableFile verbosity src dest
= withFrozenCallStack
$ do
1515 perms
<- getPermissions src
1516 if (executable perms
) -- only checks user x bit
1517 then installExecutableFile verbosity src dest
1518 else installOrdinaryFile verbosity src dest
1520 -- | Given a relative path to a file, copy it to the given directory, preserving
1521 -- the relative path and creating the parent directories if needed.
1522 copyFileTo
:: Verbosity
-> FilePath -> FilePath -> IO ()
1523 copyFileTo verbosity dir file
= withFrozenCallStack
$ do
1524 let targetFile
= dir
</> file
1525 createDirectoryIfMissingVerbose verbosity
True (takeDirectory targetFile
)
1526 installOrdinaryFile verbosity file targetFile
1528 -- | Common implementation of 'copyFiles', 'installOrdinaryFiles',
1529 -- 'installExecutableFiles' and 'installMaybeExecutableFiles'.
1531 :: (Verbosity
-> FilePath -> FilePath -> IO ())
1534 -> [(FilePath, FilePath)]
1536 copyFilesWith doCopy verbosity targetDir srcFiles
= withFrozenCallStack
$ do
1537 -- Create parent directories for everything
1538 let dirs
= map (targetDir
</>) . nub . map (takeDirectory
. snd) $ srcFiles
1539 traverse_
(createDirectoryIfMissingVerbose verbosity
True) dirs
1541 -- Copy all the files
1543 [ let src
= srcBase
</> srcFile
1544 dest
= targetDir
</> srcFile
1545 in doCopy verbosity src dest
1546 |
(srcBase
, srcFile
) <- srcFiles
1549 -- | Copies a bunch of files to a target directory, preserving the directory
1550 -- structure in the target location. The target directories are created if they
1553 -- The files are identified by a pair of base directory and a path relative to
1554 -- that base. It is only the relative part that is preserved in the
1559 -- > copyFiles normal "dist/src"
1560 -- > [("", "src/Foo.hs"), ("dist/build/", "src/Bar.hs")]
1562 -- This would copy \"src\/Foo.hs\" to \"dist\/src\/src\/Foo.hs\" and
1563 -- copy \"dist\/build\/src\/Bar.hs\" to \"dist\/src\/src\/Bar.hs\".
1565 -- This operation is not atomic. Any IO failure during the copy (including any
1566 -- missing source files) leaves the target in an unknown state so it is best to
1567 -- use it with a freshly created directory so that it can be simply deleted if
1568 -- anything goes wrong.
1569 copyFiles
:: Verbosity
-> FilePath -> [(FilePath, FilePath)] -> IO ()
1570 copyFiles v fp fs
= withFrozenCallStack
(copyFilesWith copyFileVerbose v fp fs
)
1572 -- | This is like 'copyFiles' but uses 'installOrdinaryFile'.
1573 installOrdinaryFiles
:: Verbosity
-> FilePath -> [(FilePath, FilePath)] -> IO ()
1574 installOrdinaryFiles v fp fs
= withFrozenCallStack
(copyFilesWith installOrdinaryFile v fp fs
)
1576 -- | This is like 'copyFiles' but uses 'installExecutableFile'.
1577 installExecutableFiles
1580 -> [(FilePath, FilePath)]
1582 installExecutableFiles v fp fs
= withFrozenCallStack
(copyFilesWith installExecutableFile v fp fs
)
1584 -- | This is like 'copyFiles' but uses 'installMaybeExecutableFile'.
1585 installMaybeExecutableFiles
1588 -> [(FilePath, FilePath)]
1590 installMaybeExecutableFiles v fp fs
= withFrozenCallStack
(copyFilesWith installMaybeExecutableFile v fp fs
)
1592 -- | This installs all the files in a directory to a target location,
1593 -- preserving the directory layout. All the files are assumed to be ordinary
1594 -- rather than executable files.
1595 installDirectoryContents
:: Verbosity
-> FilePath -> FilePath -> IO ()
1596 installDirectoryContents verbosity srcDir destDir
= withFrozenCallStack
$ do
1597 info verbosity
("copy directory '" ++ srcDir
++ "' to '" ++ destDir
++ "'.")
1598 srcFiles
<- getDirectoryContentsRecursive srcDir
1599 installOrdinaryFiles verbosity destDir
[(srcDir
, f
) | f
<- srcFiles
]
1601 -- | Recursively copy the contents of one directory to another path.
1602 copyDirectoryRecursive
:: Verbosity
-> FilePath -> FilePath -> IO ()
1603 copyDirectoryRecursive verbosity srcDir destDir
= withFrozenCallStack
$ do
1604 info verbosity
("copy directory '" ++ srcDir
++ "' to '" ++ destDir
++ "'.")
1605 srcFiles
<- getDirectoryContentsRecursive srcDir
1617 -- | Like 'doesFileExist', but also checks that the file is executable.
1618 doesExecutableExist
:: FilePath -> IO Bool
1619 doesExecutableExist f
= do
1620 exists
<- doesFileExist f
1623 perms
<- getPermissions f
1624 return (executable perms
)
1627 ---------------------------
1628 -- Temporary files and dirs
1630 -- | Advanced options for 'withTempFile' and 'withTempDirectory'.
1631 data TempFileOptions
= TempFileOptions
1632 { optKeepTempFiles
:: Bool
1633 -- ^ Keep temporary files?
1636 defaultTempFileOptions
:: TempFileOptions
1637 defaultTempFileOptions
= TempFileOptions
{optKeepTempFiles
= False}
1639 -- | Use a temporary filename that doesn't already exist.
1642 -- ^ Temp dir to create the file in
1644 -- ^ File name template. See 'openTempFile'.
1645 -> (FilePath -> Handle -> IO a
)
1647 withTempFile tmpDir template action
=
1648 withTempFileEx defaultTempFileOptions tmpDir template action
1650 -- | A version of 'withTempFile' that additionally takes a 'TempFileOptions'
1655 -- ^ Temp dir to create the file in
1657 -- ^ File name template. See 'openTempFile'.
1658 -> (FilePath -> Handle -> IO a
)
1660 withTempFileEx opts tmpDir template action
=
1662 (openTempFile tmpDir template
)
1663 ( \(name
, handle
) -> do
1665 unless (optKeepTempFiles opts
) $
1666 handleDoesNotExist
() . removeFile $
1669 (withLexicalCallStack
(\x
-> uncurry action x
))
1671 -- | Create and use a temporary directory.
1673 -- Creates a new temporary directory inside the given directory, making use
1674 -- of the template. The temp directory is deleted after use. For example:
1676 -- > withTempDirectory verbosity "src" "sdist." $ \tmpDir -> do ...
1678 -- The @tmpDir@ will be a new subdirectory of the given directory, e.g.
1680 withTempDirectory
:: Verbosity
-> FilePath -> String -> (FilePath -> IO a
) -> IO a
1681 withTempDirectory verbosity targetDir template f
=
1682 withFrozenCallStack
$
1685 defaultTempFileOptions
1688 (withLexicalCallStack
(\x
-> f x
))
1690 -- | A version of 'withTempDirectory' that additionally takes a
1691 -- 'TempFileOptions' argument.
1697 -> (FilePath -> IO a
)
1699 withTempDirectoryEx _verbosity opts targetDir template f
=
1700 withFrozenCallStack
$
1702 (createTempDirectory targetDir template
)
1703 ( unless (optKeepTempFiles opts
)
1704 . handleDoesNotExist
()
1705 . removeDirectoryRecursive
1707 (withLexicalCallStack
(\x
-> f x
))
1709 -----------------------------------
1710 -- Safely reading and writing files
1712 -- | Write a file but only if it would have new content. If we would be writing
1713 -- the same as the existing content then leave the file as is so that we do not
1714 -- update the file's modification time.
1716 -- NB: Before Cabal-3.0 the file content was assumed to be
1717 -- ASCII-representable. Since Cabal-3.0 the file is assumed to be
1719 rewriteFileEx
:: Verbosity
-> FilePath -> String -> IO ()
1720 rewriteFileEx verbosity path
=
1721 rewriteFileLBS verbosity path
. toUTF8LBS
1723 -- | Same as `rewriteFileEx` but for 'ByteString's.
1724 rewriteFileLBS
:: Verbosity
-> FilePath -> BS
.ByteString
-> IO ()
1725 rewriteFileLBS verbosity path newContent
=
1726 flip catchIO mightNotExist
$ do
1727 existingContent
<- annotateIO verbosity
$ BS
.readFile path
1728 _
<- evaluate
(BS
.length existingContent
)
1729 unless (existingContent
== newContent
) $
1730 annotateIO verbosity
$
1731 writeFileAtomic path newContent
1734 |
isDoesNotExistError e
=
1735 annotateIO verbosity
$ writeFileAtomic path newContent
1739 -- | The path name that represents the current directory.
1740 -- In Unix, it's @\".\"@, but this is system-specific.
1741 -- (E.g. AmigaOS uses the empty string @\"\"@ for the current directory.)
1742 currentDir
:: FilePath
1745 shortRelativePath
:: FilePath -> FilePath -> FilePath
1746 shortRelativePath from to
=
1747 case dropCommonPrefix
(splitDirectories from
) (splitDirectories to
) of
1748 (stuff
, path
) -> joinPath
(map (const "..") stuff
++ path
)
1750 dropCommonPrefix
:: Eq a
=> [a
] -> [a
] -> ([a
], [a
])
1751 dropCommonPrefix
(x
: xs
) (y
: ys
)
1752 | x
== y
= dropCommonPrefix xs ys
1753 dropCommonPrefix xs ys
= (xs
, ys
)
1755 -- | Drop the extension if it's one of 'exeExtensions', or return the path
1757 dropExeExtension
:: FilePath -> FilePath
1758 dropExeExtension filepath
=
1759 -- System.FilePath's extension handling functions are horribly
1760 -- inconsistent, consider:
1762 -- isExtensionOf "" "foo" == False but
1763 -- isExtensionOf "" "foo." == True.
1765 -- On the other hand stripExtension doesn't remove the empty extension:
1767 -- stripExtension "" "foo." == Just "foo."
1769 -- Since by "" in exeExtensions we mean 'no extension' anyways we can
1770 -- just always ignore it here.
1771 let exts
= [ext | ext
<- exeExtensions
, ext
/= ""]
1772 in fromMaybe filepath
$ do
1773 ext
<- find (`
FilePath.isExtensionOf` filepath
) exts
1774 ext `
FilePath.stripExtension` filepath
1776 -- | List of possible executable file extensions on the current build
1778 exeExtensions
:: [String]
1779 exeExtensions
= case (buildArch
, buildOS
) of
1780 -- Possible improvement: on Windows, read the list of extensions from the
1781 -- PATHEXT environment variable. By default PATHEXT is ".com; .exe; .bat;
1783 (_
, Windows
) -> ["", "exe"]
1784 (_
, Ghcjs
) -> ["", "exe"]
1785 (Wasm32
, _
) -> ["", "wasm"]
1788 -- ------------------------------------------------------------
1790 -- * Finding the description file
1792 -- ------------------------------------------------------------
1794 -- | Package description file (/pkgname/@.cabal@)
1795 defaultPackageDesc
:: Verbosity
-> IO FilePath
1796 defaultPackageDesc verbosity
= tryFindPackageDesc verbosity currentDir
1798 -- | Find a package description file in the given directory. Looks for
1803 -> IO (Either CabalException
FilePath)
1804 -- ^ <pkgname>.cabal
1805 findPackageDesc
= findPackageDescCwd
"."
1812 -- ^ relative directory
1813 -> IO (Either CabalException
FilePath)
1814 -- ^ <pkgname>.cabal relative to the project root
1815 findPackageDescCwd cwd dir
=
1817 files
<- getDirectoryContents (cwd
</> dir
)
1818 -- to make sure we do not mistake a ~/.cabal/ dir for a <pkgname>.cabal
1819 -- file we filter to exclude dirs and null base file names:
1822 (doesFileExist . snd)
1823 [ (dir
</> file
, cwd
</> dir
</> file
)
1825 , let (name
, ext
) = splitExtension file
1826 , not (null name
) && ext
== ".cabal"
1828 case map fst cabalFiles
of
1829 [] -> return (Left NoDesc
)
1830 [cabalFile
] -> return (Right cabalFile
)
1831 multiple
-> return (Left
$ MultiDesc multiple
)
1833 -- | Like 'findPackageDesc', but calls 'die' in case of error.
1834 tryFindPackageDesc
:: Verbosity
-> FilePath -> IO FilePath
1835 tryFindPackageDesc verbosity dir
=
1836 either (dieWithException verbosity
) return =<< findPackageDesc dir
1838 -- | Like 'findPackageDescCwd', but calls 'die' in case of error.
1841 tryFindPackageDescCwd
:: Verbosity
-> FilePath -> FilePath -> IO FilePath
1842 tryFindPackageDescCwd verbosity cwd dir
=
1843 either (dieWithException verbosity
) return =<< findPackageDescCwd cwd dir
1845 -- | Find auxiliary package information in the given directory.
1846 -- Looks for @.buildinfo@ files.
1847 findHookedPackageDesc
1850 -- ^ Directory to search
1851 -> IO (Maybe FilePath)
1852 -- ^ /dir/@\/@/pkgname/@.buildinfo@, if present
1853 findHookedPackageDesc verbosity dir
= do
1854 files
<- getDirectoryContents dir
1860 , let (name
, ext
) = splitExtension file
1861 , not (null name
) && ext
== buildInfoExt
1863 case buildInfoFiles
of
1864 [] -> return Nothing
1865 [f
] -> return (Just f
)
1866 _
-> dieWithException verbosity
$ MultipleFilesWithExtension buildInfoExt
1868 buildInfoExt
:: String
1869 buildInfoExt
= ".buildinfo"