A large and somewhat miscellaneous collection of utility functions used
throughout the rest of the Cabal lib and in other tools that use the Cabal
lib like cabal-install. It has a very simple set of logging actions. It
has low level functions for running programs, a bunch of wrappers for
various directory and file functions that do extra logging.

Given a block of IO code that may raise an exception, annotate
it with the metadata from the current scope. Use this as close
to external code that raises IO exceptions as possible, since
this function unconditionally wraps the error message with a trace
(so it is NOT idempotent.)

Like the Unix xargs program. Useful for when we've got very long command
lines that might overflow an OS limit on command line length and so you
need to invoke a command multiple times to get all the args in.

This would copy "src/Foo.hs" to "dist/src/src/Foo.hs" and
copy "dist/build/src/Bar.hs" to "dist/src/src/Bar.hs".

This operation is not atomic. Any IO failure during the copy (including any
missing source files) leaves the target in an unknown state so it is best to
use it with a freshly created directory so that it can be simply deleted if
anything goes wrong.

Install an ordinary file. This is like a file copy but the permissions
are set appropriately for an installed file. On Unix it is "-rw-r--r--"
while on Windows it uses the default permissions for the target directory.

Install an executable file. This is like a file copy but the permissions
are set appropriately for an installed file. On Unix it is "-rwxr-xr-x"
while on Windows it uses the default permissions for the target directory.

Find a file by looking in a search path with one of a list of possible
file extensions. The file base name should be given and it will be tried
with each of the extensions in each element of the search path.

The order places files in sub-directories after all the files in their
parent directories. The list is generated lazily so is not well defined if
the source directory structure changes before the list is used.

Compare the modification times of two files to see if the first is newer
than the second. The first file must exist but the second need not.
The expected use case is when the second file is generated using the first.
In this use case, if the result is True then the second file is out of date.

dropWhileEndLE p is equivalent to reverse . dropWhile p . reverse, but
quite a bit faster. The difference between "Data.List.dropWhileEnd" and this
version is that the one in Data.List is strict in elements, but spine-lazy,
while this one is spine-strict but lazy in elements. That's what LE stands
for - "lazy in elements".

isAbsoluteOnAnyPlatform and isRelativeOnAnyPlatform are like
isAbsolute and isRelative but have
platform independent heuristics.
The System.FilePath exists in two versions, Windows and Posix. The two
versions don't agree on what is a relative path and we don't know if we're
given Windows or Posix paths.
This results in false positives when running on Posix and inspecting
Windows paths, like the hackage server does.
System.FilePath.Posix.isAbsolute "C:\hello" == False
System.FilePath.Windows.isAbsolute "/hello" == False
This means that we would treat paths that start with "/" to be absolute.
On Posix they are indeed absolute, while on Windows they are not.

The portable versions should be used when we might deal with paths that
are from another OS than the host OS. For example, the Hackage Server
deals with both Windows and Posix paths while performing the
PackageDescription checks. In contrast, when we run 'cabal configure' we
do expect the paths to be correct for our OS and we should not have to use
the platform independent heuristics.