
module FilenameDescr where

import Data.Char
import Data.Either
import Data.List

import BuildInfo
import Utils
import Tar

-- We can't just compare plain filenames, because versions numbers of GHC
-- and the libraries will vary. So we use FilenameDescr instead, which
-- abstracts out the version numbers.
type FilenameDescr = [FilenameDescrBit]
data FilenameDescrBit = VersionOf String
                      | HashOf String
                      | FP String
                      | Ways
    deriving (Show, Eq, Ord)

normaliseDescr :: FilenameDescr -> FilenameDescr
normaliseDescr [] = []
normaliseDescr [x] = [x]
normaliseDescr (FP x1 : FP x2 : xs) = normaliseDescr (FP (x1 ++ x2) : xs)
normaliseDescr (x : xs) = x : normaliseDescr xs

-- Sanity check that the FilenameDescr matches the filename in the tar line
checkContent :: BuildInfo -> (FilenameDescr, TarLine) -> Errors
checkContent buildInfo (fd, tl)
 = let fn = tlFileName tl
   in case flattenFilenameDescr buildInfo fd of
      Right fn' ->
          if fn' == fn
          then []
          else if all isAscii fn
               then ["checkContent: Can't happen: filename mismatch: "
                  ++ show fn]
               else [] -- Ugly kludge; don't worry too much if filepaths
                       -- containing non-ASCII chars have gone wrong
      Left errs ->
          errs

flattenFilenameDescr :: BuildInfo -> FilenameDescr
                     -> Either Errors FilePath
flattenFilenameDescr buildInfo fd = case partitionEithers (map f fd) of
                                    ([], strs) -> Right (concat strs)
                                    (errs, _) -> Left (concat errs)
    where f (FP fp) = Right fp
          f (VersionOf thing)
           = case lookup thing (biThingVersionMap buildInfo) of
             Just v -> Right v
             Nothing -> Left ["Can't happen: thing has no version in mapping"]
          f (HashOf thing)
           = case lookup thing (biThingHashMap buildInfo) of
             Just v -> Right v
             Nothing -> Left ["Can't happen: thing has no hash in mapping"]
          f Ways = case biMaybeWays buildInfo of
                   Just ways -> Right $ intercalate "-" ways
                   Nothing   -> Left ["Can't happen: No ways, but Ways is used"]

