1 # Copyright 2010 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
4 from itertools import chain
9 from portage.dbapi.vartree import vartree
10 from portage.dbapi.porttree import portagetree
11 from portage.dbapi.bintree import binarytree
12 from portage.dep import Atom
13 from portage.package.ebuild.config import config
14 from portage.sets import load_default_config
15 from portage.versions import catsplit
17 from _emerge.create_depgraph_params import create_depgraph_params
18 from _emerge.depgraph import backtrack_depgraph
19 from _emerge.RootConfig import RootConfig
21 class ResolverPlayground(object):
23 This class help to create the necessary files on disk and
24 the needed settings instances, etc. for the resolver to do
28 def __init__(self, ebuilds={}, installed={}, profile={}):
30 ebuilds: cpv -> metadata mapping simulating avaiable ebuilds.
31 installed: cpv -> metadata mapping simulating installed packages.
32 If a metadata key is missing, it gets a default value.
33 profile: settings defined by the profile.
35 self.root = tempfile.mkdtemp() + os.path.sep
36 self.portdir = os.path.join(self.root, "usr/portage")
37 self.vdbdir = os.path.join(self.root, "var/db/pkg")
38 os.makedirs(self.portdir)
39 os.makedirs(self.vdbdir)
41 self._create_ebuilds(ebuilds)
42 self._create_installed(installed)
43 self._create_profile(ebuilds, installed, profile)
45 self.settings, self.trees = self._load_config()
47 self._create_ebuild_manifests(ebuilds)
49 def _create_ebuilds(self, ebuilds):
52 ebuild_dir = os.path.join(self.portdir, a.cp)
53 ebuild_path = os.path.join(ebuild_dir, a.cpv.split("/")[1] + ".ebuild")
55 os.makedirs(ebuild_dir)
59 metadata = ebuilds[cpv]
60 eapi = metadata.get("EAPI", 0)
61 slot = metadata.get("SLOT", 0)
62 keywords = metadata.get("KEYWORDS", "x86")
63 iuse = metadata.get("IUSE", "")
64 depend = metadata.get("DEPEND", "")
65 rdepend = metadata.get("RDEPEND", None)
66 pdepend = metadata.get("PDEPEND", None)
68 f = open(ebuild_path, "w")
69 f.write('EAPI="' + str(eapi) + '"\n')
70 f.write('SLOT="' + str(slot) + '"\n')
71 f.write('KEYWORDS="' + str(keywords) + '"\n')
72 f.write('IUSE="' + str(iuse) + '"\n')
73 f.write('DEPEND="' + str(depend) + '"\n')
74 if rdepend is not None:
75 f.write('RDEPEND="' + str(rdepend) + '"\n')
76 if rdepend is not None:
77 f.write('PDEPEND="' + str(pdepend) + '"\n')
80 def _create_ebuild_manifests(self, ebuilds):
83 ebuild_dir = os.path.join(self.portdir, a.cp)
84 ebuild_path = os.path.join(ebuild_dir, a.cpv.split("/")[1] + ".ebuild")
86 portage.util.noiselimit = -1
87 tmpsettings = config(clone=self.settings)
88 portdb = self.trees[self.root]["porttree"].dbapi
89 portage.doebuild(ebuild_path, "digest", self.root, tmpsettings,
90 tree="porttree", mydbapi=portdb)
91 portage.util.noiselimit = 0
93 def _create_installed(self, installed):
96 vdb_pkg_dir = os.path.join(self.vdbdir, a.cpv)
98 os.makedirs(vdb_pkg_dir)
102 metadata = installed[cpv]
103 eapi = metadata.get("EAPI", 0)
104 slot = metadata.get("SLOT", 0)
105 keywords = metadata.get("KEYWORDS", "~x86")
106 iuse = metadata.get("IUSE", "")
107 use = metadata.get("USE", "")
108 depend = metadata.get("DEPEND", "")
109 rdepend = metadata.get("RDEPEND", None)
110 pdepend = metadata.get("PDEPEND", None)
112 def write_key(key, value):
113 f = open(os.path.join(vdb_pkg_dir, key), "w")
114 f.write(str(value) + "\n")
117 write_key("EAPI", eapi)
118 write_key("SLOT", slot)
119 write_key("KEYWORDS", keywords)
120 write_key("IUSE", iuse)
121 write_key("USE", use)
122 write_key("DEPEND", depend)
123 if rdepend is not None:
124 write_key("RDEPEND", rdepend)
125 if rdepend is not None:
126 write_key("PDEPEND", pdepend)
128 def _create_profile(self, ebuilds, installed, profile):
129 #Create $PORTDIR/profiles/categories
131 for cpv in chain(ebuilds.keys(), installed.keys()):
132 categories.add(catsplit(cpv)[0])
134 profile_dir = os.path.join(self.portdir, "profiles")
136 os.makedirs(profile_dir)
140 categories_file = os.path.join(profile_dir, "categories")
142 f = open(categories_file, "w")
143 for cat in categories:
147 #Create $PORTDIR/eclass (we fail to digest the ebuilds if it's not there)
148 os.makedirs(os.path.join(self.portdir, "eclass"))
151 #This is meant to allow the consumer to set up his own profile,
152 #with package.mask and what not.
153 raise NotImplentedError()
155 def _load_config(self):
156 env = { "PORTDIR": self.portdir, "ROOT": self.root, "ACCEPT_KEYWORDS": "x86"}
157 settings = config(config_root=self.root, target_root=self.root, local_config=False, env=env)
162 "virtuals": settings.getvirtuals(),
163 "vartree": vartree(self.root, categories=settings.categories, settings=settings),
164 "porttree": portagetree(self.root, settings=settings),
165 "bintree": binarytree(self.root, os.path.join(self.root, "usr/portage/packages"), settings=settings)
169 for root, root_trees in trees.items():
170 settings = root_trees["vartree"].settings
171 settings._init_dirs()
172 setconfig = load_default_config(settings, root_trees)
173 root_trees["root_config"] = RootConfig(settings, root_trees, setconfig)
175 return settings, trees
177 def run(self, myfiles, myopts={}, myaction=None):
178 myopts["--pretend"] = True
179 myopts["--quiet"] = True
180 myopts["--root"] = self.root
181 myopts["--config-root"] = self.root
182 myopts["--root-deps"] = "rdeps"
184 portage.util.noiselimit = -2
185 myparams = create_depgraph_params(myopts, myaction)
186 success, mydepgraph, favorites = backtrack_depgraph(
187 self.settings, self.trees, myopts, myparams, myaction, myfiles, None)
188 portage.util.noiselimit = 0
191 mergelist = [x.cpv for x in mydepgraph._dynamic_config._serialized_tasks_cache]
192 return True, mergelist
194 #TODO: Use mydepgraph.display_problems() to return a useful error message
198 shutil.rmtree(self.root)