-- |The AptImage object represents a partial OS image which is capable-- of running apt-get, and thus obtaining repository info and source-- code packages.moduleDebian.Repo.AptImage(prepareAptEnv,updateAptEnv,aptGetSource)whereimportDebian.ShellimportDebian.Repo.CacheimportDebian.Repo.ChangesimportDebian.Repo.PackageimportDebian.Repo.IOimportDebian.Repo.SliceimportDebian.Repo.SourceTreeimportDebian.Repo.TypesimportDebian.RelationimportDebian.VersionimportControl.ExceptionimportControl.Monad.State(get,put)importControl.Monad.TransimportExtra.CIOimportData.ListimportData.MaybeimportExtra.FilesimportExtra.ListimportSystem.Unix.DirectoryimportSystem.Unix.ProcessimportSystem.CmdimportSystem.DirectoryinstanceShowAptImagewhereshowapt="AptImage "++relName(aptImageReleaseNameapt)instanceAptCacheAptImagewhereglobalCacheDir=aptGlobalCacheDirrootDir=aptImageRootaptArch=aptImageArchaptBaseSliceList=aptImageSliceListaptSourcePackages=aptImageSourcePackagesaptBinaryPackages=aptImageBinaryPackagesaptReleaseName=aptImageReleaseNameinstanceOrdAptImagewherecompareab=compare(aptImageReleaseNamea)(aptImageReleaseNameb)instanceEqAptImagewherea==b=compareab==EQprepareAptEnv::CIOm=>FilePath-- Put environment in a subdirectory of this->SourcesChangedAction-- What to do if environment already exists and sources.list is different->NamedSliceList-- The sources.list->AptIOTmAptImage-- The resulting environmentprepareAptEnvcacheDirsourcesChangedActionsources=get>>=return.lookupAptImage(sliceListNamesources)>>=maybe(prepareAptEnv'cacheDirsourcesChangedActionsources)return-- |Create a skeletal enviroment sufficient to run apt-get.{-# NOINLINE prepareAptEnv' #-}prepareAptEnv'::CIOm=>FilePath->SourcesChangedAction->NamedSliceList->AptIOTmAptImageprepareAptEnv'cacheDirsourcesChangedActionsources=doletroot=rootPath(cacheRootDircacheDir(ReleaseName(sliceName(sliceListNamesources))))--vPutStrLn 2 $ "prepareAptEnv " ++ sliceName (sliceListName sources)io$createDirectoryIfMissingTrue(root++"/var/lib/apt/lists/partial")io$createDirectoryIfMissingTrue(root++"/var/lib/apt/lists/partial")io$createDirectoryIfMissingTrue(root++"/var/cache/apt/archives/partial")io$createDirectoryIfMissingTrue(root++"/var/lib/dpkg")io$createDirectoryIfMissingTrue(root++"/etc/apt")io$writeFileIfMissingTrue(root++"/var/lib/dpkg/status")""io$writeFileIfMissingTrue(root++"/var/lib/dpkg/diversions")""-- We need to create the local pool before updating so the-- sources.list will be valid.letsourceListText=show(sliceListsources)-- ePut ("writeFile " ++ (root ++ "/etc/apt/sources.list") ++ "\n" ++ sourceListText)io$replaceFile(root++"/etc/apt/sources.list")sourceListTextarch<-io$buildArchOfRootletos=AptImage{aptGlobalCacheDir=cacheDir,aptImageRoot=EnvRootroot,aptImageArch=arch,aptImageReleaseName=ReleaseName.sliceName.sliceListName$sources,aptImageSliceList=sliceListsources,aptImageSourcePackages=[],aptImageBinaryPackages=[]}os'<-updateCacheSourcessourcesChangedActionos>>=updateAptEnvget>>=put.insertAptImage(sliceListNamesources)os'returnos'-- |Run apt-get update and then retrieve all the packages referenced-- by the sources.list. The source packages are sorted so that-- packages with the same name are together with the newest first.{-# NOINLINE updateAptEnv #-}updateAptEnv::CIOm=>AptImage->AptIOTmAptImageupdateAptEnvos=doio$system("apt-get"++aptOptsos++" update >/dev/null 2>&1")-- Make the loading of the package indexes lazy.sourcePackages<-getSourcePackagesos>>=return.sortBycmpbinaryPackages<-getBinaryPackagesosreturn$os{aptImageSourcePackages=sourcePackages,aptImageBinaryPackages=binaryPackages}wherecmpp1p2=comparev2v1-- Flip args to get newest firstwherev1=packageVersion.sourcePackageID$p1v2=packageVersion.sourcePackageID$p2getSourcePackages::CIOm=>AptImage->AptIOTm[SourcePackage]getSourcePackagesos=mapM(sourcePackagesOfIndex'os)indexes>>=return.concatwhereindexes=concat.map(sliceIndexesos).slices.sourceSlices.aptImageSliceList$osgetBinaryPackages::CIOm=>AptImage->AptIOTm[BinaryPackage]getBinaryPackagesos=mapM(binaryPackagesOfIndex'os)indexes>>=return.concatwhereindexes=concat.map(sliceIndexesos).slices.binarySlices.aptImageSliceList$os-- |Retrieve a source package via apt-get.aptGetSource::(AptCachet,CIOm)=>FilePath-- Where to put the source->t-- Where to apt-get from->PkgName-- The name of the package->MaybeDebianVersion-- The desired version, if Nothing get newest->mDebianBuildTree-- The resulting source treeaptGetSourcedirospackageversion=doliftIO$createDirectoryIfMissingTruedirready<-findDebianBuildTreesdirletnewest=listToMaybe.map(packageVersion.sourcePackageID).filter((==package).packageName.sourcePackageID).aptSourcePackages$osletversion'=maybenewestJustversioncase(version',ready)of(Nothing,_)->error("No available versions of "++package++" in "++rootPath(rootDiros))(Justrequested,[tree])|requested==(logVersion.entry$tree)->returntree(Justrequested,[])->dorunAptGetosdir"source"[(package,Justrequested)]trees<-findDebianBuildTreesdircasetreesof[tree]->returntree_->error"apt-get source failed"(Justrequested,_)->do-- One or more incorrect versions are available, remove themliftIO$removeRecursiveSafelydirvBOL0vEPutStr0$"Retrieving APT source for "++packagerunAptGetosdir"source"[(package,Justrequested)]trees<-findDebianBuildTreesdircasetreesof[tree]->returntree_->error"apt-get source failed"{-
where
_availableStyle = setStyle (setStart (Just ("Finding available versions of " ++ package ++ " in APT pool")))
aptGetStyle = setStyle (setStart (Just ("Retrieving APT source for " ++ package)))
-}runAptGet::(AptCachet,CIOm)=>t->FilePath->String->[(PkgName,MaybeDebianVersion)]->m(EitherString[Output])runAptGetosdircommandpackages=mkdir>>=aptgetwheremkdir=liftIO.try.createDirectoryIfMissingTrue$diraptget(Lefte)=return.Left.show$eaptget(Right_)=runTaskAndTest(SimpleTask0cmd)cmd=(consperse" "("cd":dir:"&&":"apt-get":aptOptsos:command:mapformatPackagepackages))formatPackage(name,Nothing)=nameformatPackage(name,Justversion)=name++"="++showversionaptOpts::AptCachet=>t->StringaptOptsos=(" -o=Dir::State::status="++root++"/var/lib/dpkg/status"++" -o=Dir::State::Lists="++root++"/var/lib/apt/lists"++" -o=Dir::Cache::Archives="++root++"/var/cache/apt/archives"++" -o=Dir::Etc::SourceList="++root++"/etc/apt/sources.list")whereroot=rootPath.rootDir$os