import os
import unittest

import mock

from TestBase import TestBase
from RepositorySimulator import PooledRepository, NonPooledRepository

from debpartial_mirror import Backend
from debpartial_mirror import Config
from debpartial_mirror import Controller
from debpartial_mirror import Dists
from debpartial_mirror import Download
from debpartial_mirror import Failures


class EndToEndTests(TestBase):
	def setUp(self):
		TestBase.setUp(self)
		self.mockCommandExecutor = mock.Mock()
		Dists.Dists._commandExecutor = self.mockCommandExecutor.execute


	def test01a(self):
		""" Mirror a pooled repository - basic """
		sourceRepository = PooledRepository()
		self.addPackages(sourceRepository, ["package1", "package2"], distribution="etch", component="main", architecture="i386")
		self.addInstallerPackages(sourceRepository, ["udeb1", "udeb2"], distribution="etch", component="main", architecture="i386")
		sourceDir = self.writeRepository(sourceRepository)
		globalConfiguration, mirrorDir = self.createGlobalConfiguration(
			components="main main/debian-installer",
		)
		configuration = self.loadConfiguration(globalConfiguration + """
[myRepo]
server = file://%s
"""% sourceDir)

		self.doAll(configuration)

		mirroredRepository = self.readMirror(PooledRepository, mirrorDir,multi=True)
		self.checkPackages(
			["package1", "package2"],
			mirroredRepository,
			distribution="etch", component="main", architecture="i386",
		)
		self.checkInstallerPackages(
			["udeb1", "udeb2"],
			mirroredRepository,
			distribution="etch", component="main", architecture="i386"
		)


	def test01b(self):
		""" Mirror a pooled repository - partial archs"""
		sourceRepository = PooledRepository()
		self.addPackages(sourceRepository, ["package1"], distribution="etch", component="main", architecture="i386")
		self.addPackages(sourceRepository, ["package2"], distribution="etch", component="main", architecture="alpha")
		self.addPackages(sourceRepository, ["package3"], distribution="etch", component="main", architecture="arm")
		sourceDir = self.writeRepository(sourceRepository)

		globalConfiguration, mirrorDir = self.createGlobalConfiguration(
			architectures = "i386 arm",
		)
		configuration = self.loadConfiguration(globalConfiguration + """
[myRepo]
server = file://%s
"""% sourceDir)

		self.doAll(configuration)

		mirroredRepository = self.readMirror(PooledRepository, mirrorDir,multi=True)
		self.checkPackages(["package1"], mirroredRepository, distribution="etch", component="main", architecture="i386")
		self.checkPackages([], mirroredRepository, distribution="etch", component="main", architecture="alpha")
		self.checkPackages(["package3"], mirroredRepository, distribution="etch", component="main", architecture="arm")


	def test01c(self):
		""" Mirror a pooled repository - partial components"""
		sourceRepository = PooledRepository()
		self.addPackages(sourceRepository, ["package1"], distribution="etch", component="main", architecture="i386")
		self.addPackages(sourceRepository, ["package2"], distribution="etch", component="contrib", architecture="i386")
		self.addPackages(sourceRepository, ["package3"], distribution="etch", component="non-free", architecture="i386")
		sourceDir = self.writeRepository(sourceRepository)

		globalConfiguration, mirrorDir = self.createGlobalConfiguration(
			components = "main contrib",
		)
		configuration = self.loadConfiguration(globalConfiguration + """
[myRepo]
server = file://%s
"""% sourceDir)

		self.doAll(configuration)

		mirroredRepository = self.readMirror(PooledRepository, mirrorDir,multi=True)
		self.checkPackages(["package1"], mirroredRepository, distribution="etch", component="main", architecture="i386")
		self.checkPackages(["package2"], mirroredRepository, distribution="etch", component="contrib", architecture="i386")
		self.checkPackages([], mirroredRepository, distribution="etch", component="non-free", architecture="i386")


	def test01d(self):
		""" Mirror a pooled repository - partial distributions"""
		sourceRepository = PooledRepository()
		self.addPackages(sourceRepository, ["package1"], distribution="etch", component="main", architecture="i386")
		self.addPackages(sourceRepository, ["package2"], distribution="lenny", component="main", architecture="i386")
		self.addPackages(sourceRepository, ["package3"], distribution="sid", component="main", architecture="i386")
		sourceDir = self.writeRepository(sourceRepository)
		globalConfiguration, mirrorDir = self.createGlobalConfiguration(
			distributions = "etch lenny",
		)
		configuration = self.loadConfiguration(globalConfiguration + """
[myRepo]
server = file://%s
"""% sourceDir)

		self.doAll(configuration)

		mirroredRepository = self.readMirror(PooledRepository, mirrorDir,multi=True)
		self.checkPackages(["package1"], mirroredRepository, distribution="etch", component="main", architecture="i386")
		self.checkPackages(["package2"], mirroredRepository, distribution="lenny", component="main", architecture="i386")
		self.checkPackages([], mirroredRepository, distribution="sid", component="main", architecture="i386")


	def test01e(self):
		""" Mirror a pooled repository - same package in multiple archs"""
		sourceRepository = PooledRepository()
		self.addPackages(sourceRepository, ["package1"], distribution="etch", component="main", architecture="i386")
		self.addPackages(sourceRepository, ["package1", "package3"], distribution="etch", component="main", architecture="arm")
		self.addPackages(sourceRepository, ["package2"], distribution="etch", component="main", architecture="alpha")
		sourceDir = self.writeRepository(sourceRepository)

		globalConfiguration, mirrorDir = self.createGlobalConfiguration(
			architectures = "i386 arm",
		)
		configuration = self.loadConfiguration(globalConfiguration + """
[myRepo]
server = file://%s
"""% sourceDir)

		self.doAll(configuration)

		mirroredRepository = self.readMirror(PooledRepository, mirrorDir,multi=True)
		self.checkPackages(["package1"], mirroredRepository, distribution="etch", component="main", architecture="i386")
		self.checkPackages([], mirroredRepository, distribution="etch", component="main", architecture="alpha")
		self.checkPackages(["package1", "package3"], mirroredRepository, distribution="etch", component="main", architecture="arm")


	def test02a(self):
		""" Mirror a pooled repository - filters """
		sourceRepository = PooledRepository()
		self.addPackages(sourceRepository, ["package1", "package2", "stuff1", "stuff2"], distribution="etch", component="main", architecture="i386")
		sourceDir = self.writeRepository(sourceRepository)
		globalConfiguration, mirrorDir = self.createGlobalConfiguration()
		configuration = self.loadConfiguration(globalConfiguration + """
[myRepo]
server = file://%s
filter = name:.*1
"""% sourceDir)

		self.doAll(configuration)

		mirroredRepository = self.readMirror(PooledRepository, mirrorDir)
		self.checkPackages(
			["package1", "stuff1"],
			mirroredRepository,
			distribution="etch", component="main", architecture="i386"
		)


	def test02b(self):
		""" Mirror a pooled repository - filters with dependencies"""
		sourceRepository = PooledRepository()
		packageList = self.addPackages(sourceRepository,
			["skipped", "depends1", "suggests1", "recommends1", "requiredButExcluded"],
			distribution="etch", component="main", architecture="i386"
		)
		packageList.addPackage("required1", Depends="depends1", Suggests="suggests1", Recommends="recommends1")
		sourceDir = self.writeRepository(sourceRepository)
		globalConfiguration, mirrorDir = self.createGlobalConfiguration()
		configuration = self.loadConfiguration(globalConfiguration + """
[myRepo]
server = file://%s
filter = name:required.* exclude-name:.*Excluded
"""%  sourceDir)

		self.doAll(configuration)

		mirroredRepository = self.readMirror(PooledRepository, mirrorDir)
		self.checkPackages(
			#FIXME: not actually implemented...
			#["required1", "depends1", "recommends1"],
			["required1", "depends1"],
			mirroredRepository,
			distribution="etch", component="main", architecture="i386"
		)


	def test02c(self):
		""" Mirror a pooled repository - filters with unmet dependencies (non standalone)"""
		sourceRepository = PooledRepository()
		packageList = self.addPackages(sourceRepository, ["skipped", "depends1", "depends3"], distribution="etch")
		packageList.addPackage("required1", Depends="depends1, depends2, depends3")
		sourceDir = self.writeRepository(sourceRepository)
		globalConfiguration, mirrorDir = self.createGlobalConfiguration(
			get_recommends = "true",
		)
		configuration = self.loadConfiguration(globalConfiguration + """
[myRepo]
server = file://%s
filter = name:required.*
"""%  sourceDir)

		self.doAll(configuration)

		mirroredRepository = self.readMirror(PooledRepository, mirrorDir)
		self.checkPackages(
			["required1", "depends1", "depends3"],
			mirroredRepository,
			distribution="etch", component="main", architecture="i386"
		)


	def test02d(self):
		""" Mirror a pooled repository - filters with unmet dependencies (standalone)"""
		sourceRepository = PooledRepository()
		packageList = self.addPackages(sourceRepository,
			["skipped", "depends1", "depends3"], distribution="etch"
		)
		packageList.addPackage("required1", Depends="depends1, depends2, depends3, depends4")
		sourceDir = self.writeRepository(sourceRepository)
		globalConfiguration, mirrorDir = self.createGlobalConfiguration()
		configuration = self.loadConfiguration(globalConfiguration + """
[myRepo]
server = file://%s
filter = name:required.*
standalone = true
"""%  sourceDir)

		try :
			self.doAll(configuration)
			self.fail("Exception not raised")
		except Failures.DependencyResolutionFailure, ex:
			print ex.format()
			self.failUnlessEqual("required1 needs [depends2,depends4]", ex.format())


	def test02e(self):
		""" Mirror a pooled repository - filters with architecture specific dependencies"""
		sourceRepository = PooledRepository()
		packageList1 = self.addPackages(sourceRepository,
			["depends1",],
			distribution="etch", component="main", architecture="i386"
		)
		packageList2 = self.addPackages(sourceRepository,
			["depends2",],
			distribution="etch", component="main", architecture="arm"
		)
		packageList1.addPackage("required1", Depends="depends1")
		packageList2.addPackage("required2", Depends="depends2")
		sourceDir = self.writeRepository(sourceRepository)
		globalConfiguration, mirrorDir = self.createGlobalConfiguration(architectures="i386 arm")
		configuration = self.loadConfiguration(globalConfiguration + """
[myRepo]
server = file://%s
filter = name:required.* exclude-name:.*Excluded

"""%  sourceDir)

		self.doAll(configuration)

		mirroredRepository = self.readMirror(PooledRepository, mirrorDir, multi=True)
		self.checkPackages(
			["required1", "depends1"],
			mirroredRepository,
			distribution="etch", component="main", architecture="i386"
		)
		self.checkPackages(
			["required2", "depends2"],
			mirroredRepository,
			distribution="etch", component="main", architecture="arm"
		)

	def test03a(self):
		""" Mirror a source repositroy - basic """
		sourceRepository = PooledRepository()
		# FIXME: pure source repositories not supported even if get_packages=false
		self.addPackages(sourceRepository, ["package1", "package2"], distribution="etch", component="main", architecture="i386")
		packageList = sourceRepository.createSourcePackageList(distribution="etch", component="main")
		packageList.addPackage("srcPackage1")
		packageList.addPackage("srcPackage2")
		sourceDir = self.writeRepository(sourceRepository)
		globalConfiguration, mirrorDir = self.createGlobalConfiguration(
			get_packages = "false",
			get_sources = "true",
		)
		configuration = self.loadConfiguration(globalConfiguration + """
[myRepo]
server = file://%s
"""% sourceDir)

		self.doAll(configuration)

		mirroredRepository = self.readMirror(PooledRepository, mirrorDir)
		return # FIXME: source packages not currently fetched!!
		self.checkSourcePackages(
			["srcPackage1", "srcPackage2"],
			mirroredRepository,
			distribution="etch", component="main",
		)


	def test04a(self):
		""" Merge - ensure all package fields copied """
		sourceRepository = PooledRepository()
		packageList = sourceRepository.createPackageList(distribution="etch", component="main", architecture="i386")
		fields = {
			"Essential":"yes",
			"Priority":"required",
			"Section":"shells",
			"Installed-Size":"1999",
			"Maintainer":"a.n other",
			"Replaces":"old stuff",
			"Depends":"depends1",
			"Pre-Depends":"predepends1",
			"Suggests":"suggests1",
			"Recommends":"recommends1",
			"Size":"123456",
			"MD5sum":"md5 sum",
			"SHA1":"sha1 sum",
			"SHA256":"sha256 sum",
			"Description":"Short description\n line1\ line2",
			"Tag":"tag1",
		}
		packageList.addPackage("package1", **fields)
		packageList.addPackage("depends1")
		packageList.addPackage("suggests1")
		packageList.addPackage("recommends1")

		sourceDir = self.writeRepository(sourceRepository)
		globalConfiguration, mirrorDir = self.createGlobalConfiguration()
		configuration = self.loadConfiguration(globalConfiguration + """
[src1]
server = file://%s

[myRepo]
backends = src1
"""% sourceDir)

		self.doAll(configuration)

		mergedRepository = self.readMirror(PooledRepository, mirrorDir)

		package = mergedRepository.getPackage("package1", distribution="myRepo", component="main", architecture="i386")
		for key, expectedValue in fields.iteritems():
			self.failUnlessEqual(expectedValue, package[key])


	def test04b(self):
		""" Merge two pooled repositories - basic with default signature"""
		sourceRepository1 = PooledRepository()
		self.addPackages(sourceRepository1, ["A", "C"], distribution="etch", component="main", architecture="i386")
		sourceDir1 = self.writeRepository(sourceRepository1)
		sourceRepository2 = PooledRepository()
		self.addPackages(sourceRepository2, ["B", "D"], distribution="etch", component="main", architecture="i386")
		sourceDir2 = self.writeRepository(sourceRepository2)

		globalConfiguration, mirrorDir = self.createGlobalConfiguration()
		configuration = self.loadConfiguration(globalConfiguration + """
[src1]
server = file://%s

[src2]
server = file://%s

[myRepo]
backends = src1 src2
signature_key = default
"""% (sourceDir1, sourceDir2))

		self.mockCommandExecutor.execute.return_value = 0
		self.doAll(configuration)
		self.mockCommandExecutor.execute.assert_called_with(
			"gpg -abs  -o - %s/myRepo/dists/myRepo/Release > %s/myRepo/dists/myRepo/Release.gpg" % (mirrorDir, mirrorDir)
		)
		mergedRepository = self.readMirror(PooledRepository, mirrorDir)
		self.checkPackages(
			["A", "B", "C", "D"],
			mergedRepository,
			distribution="myRepo", component="main", architecture="i386"
		)


	def test04c(self):
		""" Merge two pooled repositories - debian installer and specific signature"""
		sourceRepository1 = PooledRepository()
		self.addInstallerPackages(sourceRepository1, ["udebA", "udebC"], distribution="etch", component="main", architecture="i386")
		sourceDir1 = self.writeRepository(sourceRepository1)
		sourceRepository2 = PooledRepository()
		self.addInstallerPackages(sourceRepository2, ["udebB", "udebD"], distribution="etch", component="main", architecture="i386")
		sourceDir2 = self.writeRepository(sourceRepository2)

		globalConfiguration, mirrorDir = self.createGlobalConfiguration(
			components = "main/debian-installer",
		)
		configuration = self.loadConfiguration(globalConfiguration + """
[src1]
server = file://%s

[src2]
server = file://%s

[myRepo]
backends = src1 src2
signature_key = DEADBEEF
"""% (sourceDir1, sourceDir2))

		self.mockCommandExecutor.execute.return_value = 0
		self.doAll(configuration)
		self.mockCommandExecutor.execute.assert_called_with(
			"gpg -abs -u DEADBEEF -o - %s/myRepo/dists/myRepo/Release > %s/myRepo/dists/myRepo/Release.gpg" % (mirrorDir, mirrorDir)
		)
		mergedRepository = self.readMirror(PooledRepository, mirrorDir)
		self.checkInstallerPackages(
			["udebA", "udebB", "udebC", "udebD"],
			mergedRepository,
			distribution="myRepo", component="main", architecture="i386"
		)


	def test04d(self):
		""" Merge from a dual part components (etch/updates) """
		sourceRepository = PooledRepository()
		self.addPackages(sourceRepository, ["A", "B"], distribution="etch", component="updates/main", architecture="i386")

		sourceDir = self.writeRepository(sourceRepository)
		globalConfiguration, mirrorDir = self.createGlobalConfiguration(
			components = "updates/main",
		)
		configuration = self.loadConfiguration(globalConfiguration + """
[src1]
server = file://%s

[myRepo]
backends = src1
"""% sourceDir)

		self.doAll(configuration)

		mergedRepository = self.readMirror(PooledRepository, mirrorDir)
		self.checkPackages(
			["A", "B"],
			mergedRepository,
			distribution="myRepo", component="updates/main", architecture="i386"
		)


	def test05a(self):
		""" Merge with filter """
		sourceRepository1 = PooledRepository()
		self.addPackages(sourceRepository1, ["inc1", "exc1", "inc2", "exc2"], distribution="etch")
		sourceDir1 = self.writeRepository(sourceRepository1)
		sourceRepository2 = PooledRepository()
		packageList = self.addPackages(sourceRepository2, ["got1", "exc3", "got2", "exc4"], distribution="etch")
		packageList.addPackage("depends1")
		packageList.addPackage("suggests1")
		packageList.addPackage("recommends1")
		packageList.addPackage("gotWithDeps", Depends="depends1", Suggests="suggests1", Recommends="recommends1")

		sourceDir2 = self.writeRepository(sourceRepository2)

		globalConfiguration, mirrorDir = self.createGlobalConfiguration()
		configuration = self.loadConfiguration(globalConfiguration + """
[src1]
server = file://%s

[src2]
server = file://%s

[myRepo]
backends = src1 src2
filter_src1 = name:inc
filter_src2 = name:got
"""% (sourceDir1, sourceDir2))

		self.doAll(configuration)

		mergedRepository = self.readMirror(PooledRepository, mirrorDir)
		self.checkPackages(
			["depends1", "got1", "got2", "gotWithDeps", "inc1", "inc2"],
			mergedRepository,
			distribution="myRepo", component="main", architecture="i386"
		)


	def test06a(self):
		""" Mirror a non pooled repository - basic """
		sourceRepository = NonPooledRepository()
		self.addPackages(sourceRepository, ["package1", "package2"], distribution="etch", component="main", architecture="i386")
		sourceDir = self.writeRepository(sourceRepository)
		globalConfiguration, mirrorDir = self.createGlobalConfiguration()
		configuration = self.loadConfiguration(globalConfiguration + """
[myRepo]
server = file://%s
"""% sourceDir)

		self.doAll(configuration)

		mirroredRepository = self.readMirror(NonPooledRepository, mirrorDir)
		self.checkPackages(["package1", "package2"], mirroredRepository, distribution="etch", component="main", architecture="i386")


	def test06b(self):
		""" Merge two non pooled repositories """
		sourceRepository1 = NonPooledRepository()
		self.addPackages(sourceRepository1, ["A", "C"], distribution="etch", component="main", architecture="i386")
		sourceDir1 = self.writeRepository(sourceRepository1)
		sourceRepository2 = NonPooledRepository()
		self.addPackages(sourceRepository2, ["B", "D"], distribution="etch", component="main", architecture="i386")
		sourceDir2 = self.writeRepository(sourceRepository2)

		globalConfiguration, mirrorDir = self.createGlobalConfiguration()
		configuration = self.loadConfiguration(globalConfiguration + """
[src1]
server = file://%s

[src2]
server = file://%s

[myRepo]
backends = src1 src2
"""% (sourceDir1, sourceDir2))

		self.doAll(configuration)

		mergedRepository = self.readMirror(NonPooledRepository, mirrorDir)
		self.checkPackages(
			["A", "B", "C", "D"],
			mergedRepository,
			distribution="myRepo", component="main", architecture="i386"
		)


	def test07a(self):
		""" Mirror update on filter change """
		sourceRepository = PooledRepository()
		packageList = self.addPackages(sourceRepository, ["skipped1", "skipped2", "depends1"], distribution="etch")

		packageList.addPackage("required1", Depends="depends1")
		sourceDir = self.writeRepository(sourceRepository)
		globalConfiguration, mirrorDir = self.createGlobalConfiguration()
		baseConfigFile = globalConfiguration +"""
[myRepo]
server = file://%s
"""% sourceDir
		self.doAll(self.loadConfiguration(baseConfigFile))

		mirroredRepository = self.readMirror(PooledRepository, mirrorDir)
		self.checkPackages(
			["required1", "depends1", "skipped1", "skipped2"],
			mirroredRepository,
			distribution="etch", component="main", architecture="i386"
		)
		print 80*"="
		Download.Curl.buggy_curl = True  # seems to have problems on my machine even though OK...
		self.doAll(self.loadConfiguration(baseConfigFile + "filter = name:required.*"))
		mirroredRepository = self.readMirror(PooledRepository, mirrorDir)
		self.checkPackages(
			["required1", "depends1"],
			mirroredRepository,
			distribution="etch", component="main", architecture="i386"
		)

		print 80*"="
		self.doAll(self.loadConfiguration(baseConfigFile))

		mirroredRepository = self.readMirror(PooledRepository, mirrorDir)
		self.checkPackages(
			["required1", "depends1", "skipped1", "skipped2"],
			mirroredRepository,
			distribution="etch", component="main", architecture="i386"
		)


	def test07b(self):
		""" Merge mirror update on filter change """
		sourceRepository = PooledRepository()
		packageList = self.addPackages(sourceRepository, ["skipped1", "skipped2", "depends1"], distribution="etch")

		packageList.addPackage("required1", Depends="depends1")
		sourceDir = self.writeRepository(sourceRepository)
		globalConfiguration, mirrorDir = self.createGlobalConfiguration()
		baseConfigFile = globalConfiguration +"""
[myRepo]
backends = source

[source]
server = file://%s
"""% sourceDir
		self.doAll(self.loadConfiguration(baseConfigFile))

		mirroredRepository = self.readMirror(PooledRepository, mirrorDir)
		self.checkPackages(
			["required1", "depends1", "skipped1", "skipped2"],
			mirroredRepository,
			distribution="myRepo", component="main", architecture="i386"
		)
		print 80*"="
		Download.Curl.buggy_curl = True  # seems to have problems on my machine even though OK...
		self.doAll(self.loadConfiguration(baseConfigFile + "filter = name:required.*"))
		mirroredRepository = self.readMirror(PooledRepository, mirrorDir)
		self.checkPackages(
			["required1", "depends1"],
			mirroredRepository,
			distribution="myRepo", component="main", architecture="i386"
		)
		print 80*"="
		self.doAll(self.loadConfiguration(baseConfigFile))

		mirroredRepository = self.readMirror(PooledRepository, mirrorDir)
		self.checkPackages(
			["required1", "depends1", "skipped1", "skipped2"],
			mirroredRepository,
			distribution="myRepo", component="main", architecture="i386"
		)


	def test08a(self):
		""" Dependency resolution from another repository (resolve_deps_using) """
		sourceRepository = PooledRepository(missingReleaseFields=("Version",))
		packageList = self.addPackages(sourceRepository, ["pack1", "pack2",], distribution="etch")
		packageList.addPackage("pack3", Depends="dep1, dep2")
		depRepository = PooledRepository()
		self.addPackages(depRepository, ["dep1", "dep2", "other1"], distribution="etch")
		sourceDir = self.writeRepository(sourceRepository)
		depDir = self.writeRepository(depRepository)

		globalConfiguration, mirrorDir = self.createGlobalConfiguration()
		configuration = self.loadConfiguration(globalConfiguration + """
[dep]
server = file://%s

[myRepo]
server = file://%s
resolve_deps_using = dep
signature_key = default
"""% (depDir, sourceDir))

		self.mockCommandExecutor.execute.return_value = 0
		self.doAll(configuration)
		self.mockCommandExecutor.execute.assert_called_with(
			"gpg -abs  -o - %s/myRepo/dists/etch/Release > %s/myRepo/dists/etch/Release.gpg" % (mirrorDir, mirrorDir)
		)

		myRepository = self.readMirror(PooledRepository, mirrorDir)
		self.checkPackages(
			["pack1", "pack2", "pack3", "dep1", "dep2"],
			myRepository,
			distribution="etch", component="main", architecture="i386"
		)

		for field, value in sourceRepository.getReleaseFields().iteritems():
			if not field in ("Date",):
				self.failUnlessEqual(value, myRepository.getReleaseFields()[field])

#TODO: trivial repositories



	def createGlobalConfiguration(self, **kw):
		configMap = {
			"architectures" :"i386",
			"components" : "main",
			"distributions" : "etch",
			"get_suggests" : "false",
			"get_recommends" : "false",
			"get_provides" : "false",
			"get_sources" : "false",
			"get_packages" : "true",
		}
		configMap.update(kw)
		mirrorDir = self.createTempDirectory()
		configMap["mirror_dir"] = mirrorDir

		configLines = ["[GLOBAL]"]
		for key, value in configMap.iteritems():
			configLines.append("%s = %s" % (key, value))
		configLines.append("")
		return "\n".join(configLines),  mirrorDir

	def readMirror(self, class_, mirrorDir, name="myRepo", multi=False):
		mirroredRepository = class_(multi=multi)
		mirroredRepository.readFromFilesystem(os.path.join(mirrorDir, name))
		return mirroredRepository


	def addPackages(self, repository, packageNames, distribution, component="main", architecture="i386"):
		return self._addPackages(repository.createPackageList(distribution, component, architecture), packageNames)

	def addInstallerPackages(self, repository, packageNames, distribution, component="main", architecture="i386"):
		return self._addPackages(repository.createInstallerPackageList(distribution, component, architecture), packageNames)

	def _addPackages(self, packageList, packageNames):
		for name in packageNames:
			packageList.addPackage(name)
		return packageList

	def writeRepository(self, repository):
		directory = os.path.abspath(self.createTempDirectory()) # always absolute for use in file:// urls
		repository.writeToFilesystem(directory)
		return directory

	def loadConfiguration(self, configString):
		configFile = self.createTempFile()
		f = open(configFile, "w")
		try:
			f.write(configString)
		finally:
			f.close()
		return Config.Config(configFile)

	def doAll(self, configuration):
		Backend.Backend.backends = [] #TODO: fix static
		Download.Download.d_fetchers_list = {}
		controller = Controller.Controller(configuration, [])
		controller.executeCommand("all")


	def checkPackages(self, expectedPackageNames, repository, distribution, component="main", architecture="i386"):
		self.failUnlessEqual(
			sorted(expectedPackageNames),
			sorted(repository.getAvailablePackageNames(distribution, component, architecture)),
		)
		if not repository.isMulti(): # Cannot tell which files for which arch,component etc just by looking at filenames
			self.failUnlessEqual(
				sorted(expectedPackageNames),
				sorted(repository.getPackageNamesForPresentFiles()),
			)

	def checkInstallerPackages(self, expectedPackageNames, repository, distribution, component="main", architecture="i386"):
		self.failUnlessEqual(
			sorted(expectedPackageNames),
			sorted(repository.getAvailableInstallerPackageNames(distribution, component, architecture)),
		)

	def checkSourcePackages(self, expectedPackageNames, repository, distribution, component="main"):
		self.failUnlessEqual(
			sorted(expectedPackageNames),
			sorted(repository.getAvailableSourcePackageNames(distribution, component)),
		)




def suite():
	suite = unittest.TestSuite()
	suite.addTest(unittest.makeSuite(EndToEndTests, 'test'))
	return suite


if __name__ == '__main__':
	unittest.main()
