module-management-0.20.2: testdata/debian/Debian/Repo/PackageIndex.hs
-- | The 'PackageIndex' type is the result of parsing a file
-- containing control information about debian packages, either source
-- or binary. Examples of such files include
-- @http://ftp.debian.org/debian/dists/sid/main/source/Sources.bz2@ or
-- @http://ftp.debian.org/debian/dists/sid/main/binary-amd64/Packages.bz2@.
{-# LANGUAGE FlexibleInstances, OverloadedStrings, StandaloneDeriving #-}
module Debian.Repo.PackageIndex
( PackageIndex(..)
, BinaryPackage(..)
, prettyBinaryPackage
, SourcePackage(..)
, SourceControl(..)
, SourceFileSpec(..)
, packageIndexName
, packageIndexPath
, packageIndexDir
, packageIndexPaths
, packageIndexDirs
, packageIndexes
, sourceIndexes
, binaryIndexes
, releaseDir
, sortSourcePackages
, sortBinaryPackages
) where
import Data.List as List (sortBy, map, filter)
import Data.Monoid ((<>))
import Data.Set as Set (map, filter, toList, unions)
import Data.Text (Text)
import Debian.Arch (Arch(..), ArchOS(..), ArchCPU(..), prettyArch)
import qualified Debian.Control.Text as T
import Debian.Relation (BinPkgName(..), SrcPkgName(..))
import qualified Debian.Relation as B (Relations)
import Debian.Pretty (PP(..), ppPrint)
import Debian.Release (releaseName', Section(..), sectionName')
import Debian.Repo.PackageID (PackageID(packageName, packageVersion), prettyPackageID)
import Debian.Repo.Release (Release(..))
import System.FilePath ((</>))
import System.Posix.Types (FileOffset)
import Text.PrettyPrint.HughesPJClass (Doc, Pretty(pPrint), text)
-- | A package index is identified by Section (e.g. main, contrib,
-- non-free) and architecture (e.g. source, i386, amd64.)
data PackageIndex
= PackageIndex { packageIndexComponent :: Section
, packageIndexArch :: Arch
} deriving (Eq, Ord, Show)
instance Pretty (PP PackageIndex) where
pPrint (PP x) = ppPrint (packageIndexComponent x) <> text "_" <> ppPrint (packageIndexArch x)
instance Pretty (PP Section) where
pPrint (PP (Section x)) = pPrint x
instance Pretty (PP Arch) where
pPrint (PP Source) = text "source"
pPrint (PP All) = text "all"
pPrint (PP (Binary ArchOSAny ArchCPUAny)) = text "any"
pPrint (PP (Binary (ArchOS os) ArchCPUAny)) = ppPrint os
pPrint (PP (Binary ArchOSAny (ArchCPU cpu))) = ppPrint cpu
pPrint (PP (Binary (ArchOS os) (ArchCPU cpu))) = ppPrint (os <> "-" <> cpu)
{-
instance PackageVersion BinaryPackage where
pkgName = binaryPackageName
pkgVersion = packageVersion . packageID
-}
-- | The 'BinaryPackage' type adds to the 'PackageID' type the control
-- information obtained from the package index.
data BinaryPackage
= BinaryPackage
{ packageID :: PackageID BinPkgName
, packageInfo :: T.Paragraph
, pDepends :: B.Relations
, pPreDepends :: B.Relations
, pConflicts ::B.Relations
, pReplaces :: B.Relations
, pProvides :: B.Relations
} deriving (Show)
-- In a perfect world these would be valid Eq and Ord instances, but
-- they are not because different builds of the same version can occur
-- on different machines that are unaware of each other. These should
-- be removed. But they are currently in use.
instance Ord BinaryPackage where
compare a b = compare (packageID a) (packageID b)
instance Eq BinaryPackage where
a == b = (packageID a) == (packageID b)
prettyBinaryPackage :: BinaryPackage -> Doc
prettyBinaryPackage = prettyPackageID . packageID
data SourcePackage
= SourcePackage
{ sourcePackageID :: PackageID SrcPkgName
, sourceParagraph :: T.Paragraph
, sourceControl :: SourceControl
, sourceDirectory :: String
, sourcePackageFiles :: [SourceFileSpec]
} deriving (Show, Eq, Ord)
-- |Source package information derived from the control paragraph.
data SourceControl
= SourceControl
{ source :: Text
, maintainer :: NameAddr
, uploaders :: [NameAddr]
, packageSection :: Maybe Section' -- Should this be the same type as the Section field in a .changes file?
, packagePriority :: Maybe Priority
, buildDepends :: [Package]
, buildDependsIndep :: [Package]
, buildConflicts :: [Package]
, buildConflictsIndep :: [Package]
, standardsVersion :: Maybe StandardsVersion -- There are packages that don't have this
, homepage :: Maybe Text -- There are packages that don't have this
} deriving (Show, Eq, Ord)
type NameAddr = Text
type StandardsVersion = Text
type Section' = Text
type Priority = Text
type Package = Text
data SourceFileSpec
= SourceFileSpec
{ sourceFileMD5sum :: String
, sourceFileSize :: FileOffset
, sourceFileName :: FilePath
}
deriving (Show, Eq, Ord)
packageIndexName :: PackageIndex -> FilePath
packageIndexName index =
case packageIndexArch index of
Source -> "Sources"
_ -> "Packages"
packageIndexPath :: Release -> PackageIndex -> FilePath
packageIndexPath release index = packageIndexDir release index </> packageIndexName index
packageIndexDir :: Release -> PackageIndex -> FilePath
packageIndexDir release index =
case packageIndexArch index of
Source -> releaseDir release </> sectionName' (packageIndexComponent index) </> "source"
_ -> (releaseDir release </> sectionName' (packageIndexComponent index) </>
-- Will prettyArch give us linux-amd64 when we just want amd64?
"binary-" ++ show (prettyArch (packageIndexArch index)))
releaseDir :: Release -> String
releaseDir release = "dists" </> (releaseName' . releaseName $ release)
packageIndexPaths :: Release -> [FilePath]
packageIndexPaths release = List.map (packageIndexPath release) . packageIndexes $ release
packageIndexDirs :: Release -> [FilePath]
packageIndexDirs release = List.map (packageIndexDir release) . packageIndexes $ release
packageIndexes :: Release -> [PackageIndex]
packageIndexes release = sourceIndexes release ++ binaryIndexes release
sourceIndexes :: Release -> [PackageIndex]
sourceIndexes release =
List.map componentIndex (releaseComponents $ release)
where componentIndex component = PackageIndex { packageIndexComponent = component
, packageIndexArch = Source }
binaryIndexes :: Release -> [PackageIndex]
binaryIndexes release =
toList . unions . List.map componentIndexes $ releaseComponents release
where
--componentIndexes :: Section -> [PackageIndex]
componentIndexes component =
Set.map archIndex (Set.filter (/= Source) (releaseArchitectures release))
where
--archIndex :: Arch -> PackageIndex
archIndex arch = PackageIndex { packageIndexComponent = component
, packageIndexArch = arch }
-- | Return a sorted list of available source packages, newest version first.
sortSourcePackages :: [SrcPkgName] -> [SourcePackage] -> [SourcePackage]
sortSourcePackages names pkgs =
sortBy cmp . filterNames $ pkgs
where
filterNames :: [SourcePackage] -> [SourcePackage]
filterNames packages =
List.filter (flip elem names . packageName . sourcePackageID) packages
cmp p1 p2 =
compare v2 v1 -- Flip args to get newest first
where
v1 = packageVersion . sourcePackageID $ p1
v2 = packageVersion . sourcePackageID $ p2
sortBinaryPackages :: [BinPkgName] -> [BinaryPackage] -> [BinaryPackage]
sortBinaryPackages names pkgs =
sortBy cmp . filterNames $ pkgs
where
filterNames :: [BinaryPackage] -> [BinaryPackage]
filterNames packages =
List.filter (flip elem names . packageName . packageID) packages
cmp p1 p2 =
compare v2 v1 -- Flip args to get newest first
where
v1 = packageVersion . packageID $ p1
v2 = packageVersion . packageID $ p2