Baffled by Distribution.Simple.BuildTarget.checkTargetExistsAsFile

Echo Nolan echo at
Wed Nov 11 06:17:25 UTC 2015

I'm finding this function very confusing. I think it's supposed to
determine if a user build target is a file, and whether that file exists,
but it does some real weird stuff. I'm not sure if I've found a bug or I
just don't understand what it's supposed to do. Here's the source:

checkTargetExistsAsFile :: UserBuildTarget -> IO (UserBuildTarget, Bool)
checkTargetExistsAsFile t = do
    fexists <- existsAsFile (fileComponentOfTarget t)
    return (t, fexists)

    existsAsFile f = do
      exists <- doesFileExist f
      case splitPath f of
        (d:_)   | hasTrailingPathSeparator d -> doesDirectoryExist d
        (d:_:_) | not exists                 -> doesDirectoryExist d
        _                                    -> return exists

    fileComponentOfTarget (UserBuildTargetSingle     s1) = s1
    fileComponentOfTarget (UserBuildTargetDouble _   s2) = s2
    fileComponentOfTarget (UserBuildTargetTriple _ _ s3) = s3

So... UserBuildTargets can be components, modules or files and can be
qualified at three levels of specificity. It takes the last part of the
qualified build target - which is either a module (Main), a component
(cabal), or a file (Main.hs), then runs the existsAsFile function on it. It
returns a 2-tuple of its input and the result of existsAsFile.

existsAsFile checks whether its parameter is an existing file, then splits
its parameter on directory separators i.e. / or \. If the resulting list is
nonempty and first element ends in a directory separator it returns whether
that first element is an existing directory. This case is entered any time
the parameter begins with a directory, e.g. "foo/bar.hs" but not "bar.hs".
Shouldn't we just return exists here?

existsAsFile's second case is where the split path has at least two
elements and the parameter is not an existing file. It returns whether the
first component of the split path is an existing directory. I have no idea.

The last case is where splitPath f is []. This can only be true if f is [].
In that case we return whether the file named "" exists. This is
impossible, so it's always false.

I can't imagine what happened to make this function this way. From my
perspective, existsAsFile should equal doesFileExist. I must be missing
something right?

Best regards,
Echo Nolan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the cabal-devel mailing list