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.Blocker import Blocker
18 from _emerge.create_depgraph_params import create_depgraph_params
19 from _emerge.depgraph import backtrack_depgraph
20 from _emerge.RootConfig import RootConfig
22 class ResolverPlayground(object):
24 This class help to create the necessary files on disk and
25 the needed settings instances, etc. for the resolver to do
29 def __init__(self, ebuilds={}, installed={}, profile={}):
31 ebuilds: cpv -> metadata mapping simulating avaiable ebuilds.
32 installed: cpv -> metadata mapping simulating installed packages.
33 If a metadata key is missing, it gets a default value.
34 profile: settings defined by the profile.
36 self.root = tempfile.mkdtemp() + os.path.sep
37 self.portdir = os.path.join(self.root, "usr/portage")
38 self.vdbdir = os.path.join(self.root, "var/db/pkg")
39 os.makedirs(self.portdir)
40 os.makedirs(self.vdbdir)
42 self._create_ebuilds(ebuilds)
43 self._create_installed(installed)
44 self._create_profile(ebuilds, installed, profile)
46 self.settings, self.trees = self._load_config()
48 self._create_ebuild_manifests(ebuilds)
50 def _create_ebuilds(self, ebuilds):
53 ebuild_dir = os.path.join(self.portdir, a.cp)
54 ebuild_path = os.path.join(ebuild_dir, a.cpv.split("/")[1] + ".ebuild")
56 os.makedirs(ebuild_dir)
60 metadata = ebuilds[cpv]
61 eapi = metadata.get("EAPI", 0)
62 slot = metadata.get("SLOT", 0)
63 keywords = metadata.get("KEYWORDS", "x86")
64 iuse = metadata.get("IUSE", "")
65 depend = metadata.get("DEPEND", "")
66 rdepend = metadata.get("RDEPEND", None)
67 pdepend = metadata.get("PDEPEND", None)
69 f = open(ebuild_path, "w")
70 f.write('EAPI="' + str(eapi) + '"\n')
71 f.write('SLOT="' + str(slot) + '"\n')
72 f.write('KEYWORDS="' + str(keywords) + '"\n')
73 f.write('IUSE="' + str(iuse) + '"\n')
74 f.write('DEPEND="' + str(depend) + '"\n')
75 if rdepend is not None:
76 f.write('RDEPEND="' + str(rdepend) + '"\n')
77 if rdepend is not None:
78 f.write('PDEPEND="' + str(pdepend) + '"\n')
81 def _create_ebuild_manifests(self, ebuilds):
84 ebuild_dir = os.path.join(self.portdir, a.cp)
85 ebuild_path = os.path.join(ebuild_dir, a.cpv.split("/")[1] + ".ebuild")
87 portage.util.noiselimit = -1
88 tmpsettings = config(clone=self.settings)
89 portdb = self.trees[self.root]["porttree"].dbapi
90 portage.doebuild(ebuild_path, "digest", self.root, tmpsettings,
91 tree="porttree", mydbapi=portdb)
92 portage.util.noiselimit = 0
94 def _create_installed(self, installed):
97 vdb_pkg_dir = os.path.join(self.vdbdir, a.cpv)
99 os.makedirs(vdb_pkg_dir)
103 metadata = installed[cpv]
104 eapi = metadata.get("EAPI", 0)
105 slot = metadata.get("SLOT", 0)
106 keywords = metadata.get("KEYWORDS", "~x86")
107 iuse = metadata.get("IUSE", "")
108 use = metadata.get("USE", "")
109 depend = metadata.get("DEPEND", "")
110 rdepend = metadata.get("RDEPEND", None)
111 pdepend = metadata.get("PDEPEND", None)
113 def write_key(key, value):
114 f = open(os.path.join(vdb_pkg_dir, key), "w")
115 f.write(str(value) + "\n")
118 write_key("EAPI", eapi)
119 write_key("SLOT", slot)
120 write_key("KEYWORDS", keywords)
121 write_key("IUSE", iuse)
122 write_key("USE", use)
123 write_key("DEPEND", depend)
124 if rdepend is not None:
125 write_key("RDEPEND", rdepend)
126 if rdepend is not None:
127 write_key("PDEPEND", pdepend)
129 def _create_profile(self, ebuilds, installed, profile):
130 #Create $PORTDIR/profiles/categories
132 for cpv in chain(ebuilds.keys(), installed.keys()):
133 categories.add(catsplit(cpv)[0])
135 profile_dir = os.path.join(self.portdir, "profiles")
137 os.makedirs(profile_dir)
141 categories_file = os.path.join(profile_dir, "categories")
143 f = open(categories_file, "w")
144 for cat in categories:
148 #Create $PORTDIR/eclass (we fail to digest the ebuilds if it's not there)
149 os.makedirs(os.path.join(self.portdir, "eclass"))
152 #This is meant to allow the consumer to set up his own profile,
153 #with package.mask and what not.
154 raise NotImplentedError()
156 def _load_config(self):
157 env = { "PORTDIR": self.portdir, "ROOT": self.root, "ACCEPT_KEYWORDS": "x86"}
158 settings = config(config_root=self.root, target_root=self.root, local_config=False, env=env)
163 "virtuals": settings.getvirtuals(),
164 "vartree": vartree(self.root, categories=settings.categories, settings=settings),
165 "porttree": portagetree(self.root, settings=settings),
166 "bintree": binarytree(self.root, os.path.join(self.root, "usr/portage/packages"), settings=settings)
170 for root, root_trees in trees.items():
171 settings = root_trees["vartree"].settings
172 settings._init_dirs()
173 setconfig = load_default_config(settings, root_trees)
174 root_trees["root_config"] = RootConfig(settings, root_trees, setconfig)
176 return settings, trees
178 def run(self, myfiles, myopts={}, myaction=None):
179 myopts["--pretend"] = True
180 myopts["--quiet"] = True
181 myopts["--root"] = self.root
182 myopts["--config-root"] = self.root
183 myopts["--root-deps"] = "rdeps"
184 # Add a fake _test_ option that can be used for
185 # conditional test code.
186 myopts["_test_"] = True
188 portage.util.noiselimit = -2
189 myparams = create_depgraph_params(myopts, myaction)
190 success, mydepgraph, favorites = backtrack_depgraph(
191 self.settings, self.trees, myopts, myparams, myaction, myfiles, None)
192 result = ResolverPlaygroundResult(success, mydepgraph, favorites)
193 portage.util.noiselimit = 0
198 shutil.rmtree(self.root)
200 class ResolverPlaygroundResult(object):
201 def __init__(self, success, mydepgraph, favorites):
202 self.success = success
203 self.depgraph = mydepgraph
204 self.favorites = favorites
205 self.mergelist = None
207 if self.depgraph._dynamic_config._serialized_tasks_cache is not None:
209 for x in self.depgraph._dynamic_config._serialized_tasks_cache:
210 if isinstance(x, Blocker):
211 self.mergelist.append(x.atom)
213 self.mergelist.append(x.cpv)