1 # Copyright 2010 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
4 from itertools import chain
8 from portage.dbapi.vartree import vartree
9 from portage.dbapi.porttree import portagetree
10 from portage.dbapi.bintree import binarytree
11 from portage.dep import Atom
12 from portage.package.ebuild.config import config
13 from portage.sets import load_default_config
14 from portage.versions import catsplit
16 from _emerge.create_depgraph_params import create_depgraph_params
17 from _emerge.depgraph import backtrack_depgraph
18 from _emerge.RootConfig import RootConfig
20 class ResolverPlayground(object):
22 This class help to create the necessary files on disk and
23 the needed settings instances, etc. for the resolver to do
27 def __init__(self, ebuilds={}, installed={}, profile={}):
29 ebuilds: cpv -> metadata mapping simulating avaiable ebuilds.
30 installed: cpv -> metadata mapping simulating installed packages.
31 If a metadata key is missing, it gets a default value.
32 profile: settings defined by the profile.
34 self.root = tempfile.mkdtemp() + os.path.sep
35 self.portdir = os.path.join(self.root, "usr/portage")
36 self.vdbdir = os.path.join(self.root, "var/db/pkg")
37 os.makedirs(self.portdir)
38 os.makedirs(self.vdbdir)
40 self._create_ebuilds(ebuilds)
41 self._create_installed(installed)
42 self._create_profile(ebuilds, installed, profile)
44 self.settings, self.trees = self._load_config()
46 self._create_ebuild_manifests(ebuilds)
48 def _create_ebuilds(self, ebuilds):
51 ebuild_dir = os.path.join(self.portdir, a.cp)
52 ebuild_path = os.path.join(ebuild_dir, a.cpv.split("/")[1] + ".ebuild")
54 os.makedirs(ebuild_dir)
58 metadata = ebuilds[cpv]
59 eapi = metadata.get("EAPI", 0)
60 slot = metadata.get("SLOT", 0)
61 keywords = metadata.get("KEYWORDS", "x86")
62 iuse = metadata.get("IUSE", "")
63 depend = metadata.get("DEPEND", "")
64 rdepend = metadata.get("RDEPEND", None)
65 pdepend = metadata.get("PDEPEND", None)
67 f = open(ebuild_path, "w")
68 f.write('EAPI="' + str(eapi) + '"\n')
69 f.write('SLOT="' + str(slot) + '"\n')
70 f.write('KEYWORDS="' + str(keywords) + '"\n')
71 f.write('IUSE="' + str(iuse) + '"\n')
72 f.write('DEPEND="' + str(depend) + '"\n')
73 if rdepend is not None:
74 f.write('RDEPEND="' + str(rdepend) + '"\n')
75 if rdepend is not None:
76 f.write('PDEPEND="' + str(pdepend) + '"\n')
79 def _create_ebuild_manifests(self, ebuilds):
82 ebuild_dir = os.path.join(self.portdir, a.cp)
83 ebuild_path = os.path.join(ebuild_dir, a.cpv.split("/")[1] + ".ebuild")
85 portage.util.noiselimit = -1
86 tmpsettings = config(clone=self.settings)
87 portdb = self.trees[self.root]["porttree"].dbapi
88 portage.doebuild(ebuild_path, "digest", self.root, tmpsettings,
89 tree="porttree", mydbapi=portdb)
90 portage.util.noiselimit = 0
92 def _create_installed(self, installed):
95 vdb_pkg_dir = os.path.join(self.vdbdir, a.cpv)
97 os.makedirs(vdb_pkg_dir)
101 metadata = installed[cpv]
102 eapi = metadata.get("EAPI", 0)
103 slot = metadata.get("SLOT", 0)
104 keywords = metadata.get("KEYWORDS", "~x86")
105 iuse = metadata.get("IUSE", "")
106 use = metadata.get("USE", "")
107 depend = metadata.get("DEPEND", "")
108 rdepend = metadata.get("RDEPEND", None)
109 pdepend = metadata.get("PDEPEND", None)
111 def write_key(key, value):
112 f = open(os.path.join(vdb_pkg_dir, key), "w")
113 f.write(str(value) + "\n")
116 write_key("EAPI", eapi)
117 write_key("SLOT", slot)
118 write_key("KEYWORDS", keywords)
119 write_key("IUSE", iuse)
120 write_key("USE", use)
121 write_key("DEPEND", depend)
122 if rdepend is not None:
123 write_key("RDEPEND", rdepend)
124 if rdepend is not None:
125 write_key("PDEPEND", pdepend)
127 def _create_profile(self, ebuilds, installed, profile):
128 #Create $PORTDIR/profiles/categories
130 for cpv in chain(ebuilds.keys(), installed.keys()):
131 categories.add(catsplit(cpv)[0])
133 profile_dir = os.path.join(self.portdir, "profiles")
135 os.makedirs(profile_dir)
139 categories_file = os.path.join(profile_dir, "categories")
141 f = open(categories_file, "w")
142 for cat in categories:
146 #Create $PORTDIR/eclass (we fail to digest the ebuilds if it's not there)
147 os.makedirs(os.path.join(self.portdir, "eclass"))
150 #This is meant to allow the consumer to set up his own profile,
151 #with package.mask and what not.
152 raise NotImplentedError()
154 def _load_config(self):
155 env = { "PORTDIR": self.portdir, "ROOT": self.root, "ACCEPT_KEYWORDS": "x86"}
156 settings = config(config_root=self.root, target_root=self.root, local_config=False, env=env)
161 "virtuals": settings.getvirtuals(),
162 "vartree": vartree(self.root, categories=settings.categories, settings=settings),
163 "porttree": portagetree(self.root, settings=settings),
164 "bintree": binarytree(self.root, os.path.join(self.root, "usr/portage/packages"), settings=settings)
168 for root, root_trees in trees.items():
169 settings = root_trees["vartree"].settings
170 settings._init_dirs()
171 setconfig = load_default_config(settings, root_trees)
172 root_trees["root_config"] = RootConfig(settings, root_trees, setconfig)
174 return settings, trees
176 def run(self, myfiles, myopts={}, myaction=None):
177 myopts["--pretend"] = True
178 myopts["--quiet"] = True
179 myopts["--root"] = self.root
180 myopts["--config-root"] = self.root
181 myparams = create_depgraph_params(myopts, myaction)
182 success, mydepgraph, favorites = backtrack_depgraph(
183 self.settings, self.trees, myopts, myparams, myaction, myfiles, None)
186 mergelist = [x.cpv for x in mydepgraph._dynamic_config._serialized_tasks_cache]
187 return True, mergelist
189 #TODO: Use mydepgraph.display_problems() to return a useful error message