debian-1.0: Linspire/Debian/DistroCache.hs
-- |A DistroCache is a distribution (a list of DebSource) with a name
-- and a directory which it can use to download and store files. It
-- is the basis for several of the other Debian modules.
--
-- Author: David Fox <david.fox@linspire.com>
module Linspire.Debian.DistroCache
(DistroCache,
-- * Constructors
distroFromConfig, -- FilePath -> String -> IO DistroCache
distroFromConfig', -- FilePath -> String -> DistroCache
makeDistro, -- FilePath -> String -> [DebSource] -> DistroCache
-- * Accessors
dist, -- DistroCache -> String
aptDir, -- DistroCache -> String -> FilePath
aptRootDir, -- DistroCache -> FilePath
sources, -- DistroCache -> [DebSource],
sourcesPath, -- DistroCache -> FilePath
poolRoot, -- DistroCache -> FilePath
localPool, -- DistroCache -> FilePath -> [DebSource]
cleanRoot, -- DistroCache -> String -> FilePath
dirtyRoot) -- DistroCache -> String -> FilePath
where
import Control.Monad
import Data.List
import Data.Maybe
import System.Directory
import System.IO
import Text.Regex
import Linspire.Unix.FilePath
import Linspire.Debian.SourcesList
-- FIXME: we should have a flag to indicate whether we have
-- verified the files that distroFromConfig creates.
data DistroCache =
Distro {top :: FilePath, -- ^ The autobuilder cache directory
dist :: String, -- ^ Name of the distro.
sources :: [DebSource]} -- ^ The contents of the sources.list file.
instance Eq DistroCache where
Distro a b _ == Distro c d _ = a == c && b == d
distDir :: DistroCache -> FilePath
distDir (Distro top dist _) = top ++ "/dists/" ++ dist
-- |The directory where package's source deb is downloaded to.
aptDir :: DistroCache -> String -> FilePath
aptDir distro package = distDir distro ++ "/apt/" ++ package
-- |The partial environment for performing apt-gets
aptRootDir :: DistroCache -> FilePath
aptRootDir distro = distDir distro ++ "/aptEnv"
sourcesPath :: DistroCache -> FilePath
sourcesPath distro = distDir distro ++ "/sources"
localPool :: DistroCache -> FilePath -> [DebSource]
localPool distro dir =
parseSourcesList ("\ndeb file://" ++ dir ++ " " ++ dist distro ++ " main" ++
"\ndeb-src file://" ++ dir ++ " " ++ dist distro ++ " main\n")
poolRoot :: DistroCache -> FilePath
poolRoot distro = distDir distro ++ "/upload-env"
dirtyRoot :: DistroCache -> String -> FilePath
dirtyRoot distro strictness = distDir distro ++ "/build-" ++ strictness
cleanRoot :: DistroCache -> String -> FilePath
cleanRoot distro strictness = distDir distro ++ "/clean-" ++ strictness
-- |Given the text for a source list in the config file, return
-- a Distro object. This is an IO operation because we may
-- need to create the sources.list files.
distroFromConfig :: FilePath -> String -> IO DistroCache
distroFromConfig top text =
do
let distro@(Distro _ dist _) = distroFromConfig' top text
let dir = distDir distro
distExists <- doesFileExist (sourcesPath distro)
case distExists of
True ->
do
fileSources <- readFile (sourcesPath distro) >>= return . parseSourcesList
case fileSources == (sources distro) of
True -> return distro
False ->
do
ePut ("Sources for '" ++ dist ++ "' don't match sources from the configuration file" ++
":\n\n" ++ sourcesPath distro ++ ":\n\n" ++
consperse "\n" (map show fileSources) ++
"\n\nConfiguration file:\n\n" ++
consperse "\n" (map show (sources distro)) ++ "\n\n" ++
"This means it is possible that everything in\n" ++
dir ++ " is invalid.")
-- removeRecursiveSafely dir
error ("Please remove " ++ dir ++ " and restart.")
False ->
do
createDirectoryIfMissing True dir
writeFile (sourcesPath distro) (consperse "\n" (map show (sources distro)) ++ "\n")
return distro
-- |Create Distro info from an entry in the config file, which
-- includes a dist name and the lines of the sources.list file.
-- This also creates the basic
distroFromConfig' :: FilePath -> String -> DistroCache
distroFromConfig' top text =
-- FIXME: This regexp is too permissive - it will match almost anything
let re = mkRegex "^[ \t\n]*([^ \t\n]+)[ \t\n]+(.*)$" in
case matchRegex re text of
Just [dist, sources] -> Distro top dist (parseSourcesList sources)
_ -> error "Syntax error in sources text"
-- |This is unsafe in the sense that we don't know that the
-- directories have been created and the sources.list files
-- have been written.
makeDistro :: FilePath -> String -> [DebSource] -> DistroCache
makeDistro top dist sources = Distro top dist sources
ePut :: String -> IO ()
ePut s = hPutStrLn stderr s
-- |The mighty consperse function
consperse :: [a] -> [[a]] -> [a]
consperse sep items = concat (intersperse sep items)