Tests: Add resolver/test_eapi (2 tests disabled)
[portage.git] / pym / portage / tests / resolver / ResolverPlayground.py
1 # Copyright 2010 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3
4 from itertools import chain
5 import tempfile
6 import portage
7 from portage import os
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
15
16 from _emerge.create_depgraph_params import create_depgraph_params
17 from _emerge.depgraph import backtrack_depgraph
18 from _emerge.RootConfig import RootConfig
19
20 class ResolverPlayground(object):
21         """
22         This class help to create the necessary files on disk and
23         the needed settings instances, etc. for the resolver to do
24         it's work.
25         """
26         
27         def __init__(self, ebuilds={}, installed={}, profile={}):
28                 """
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.
33                 """
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)
39                 
40                 self._create_ebuilds(ebuilds)
41                 self._create_installed(installed)
42                 self._create_profile(ebuilds, installed, profile)
43                 
44                 self.settings, self.trees = self._load_config()
45                 
46                 self._create_ebuild_manifests(ebuilds)
47
48         def _create_ebuilds(self, ebuilds):
49                 for cpv in ebuilds:
50                         a = Atom("=" + cpv)
51                         ebuild_dir = os.path.join(self.portdir, a.cp)
52                         ebuild_path = os.path.join(ebuild_dir, a.cpv.split("/")[1] + ".ebuild")
53                         try:
54                                 os.makedirs(ebuild_dir)
55                         except os.error:
56                                 pass
57                         
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)
66
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')
77                         f.close()
78
79         def _create_ebuild_manifests(self, ebuilds):
80                 for cpv in ebuilds:
81                         a = Atom("=" + cpv)
82                         ebuild_dir = os.path.join(self.portdir, a.cp)
83                         ebuild_path = os.path.join(ebuild_dir, a.cpv.split("/")[1] + ".ebuild")
84                         
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
91                 
92         def _create_installed(self, installed):
93                 for cpv in installed:
94                         a = Atom("=" + cpv)
95                         vdb_pkg_dir = os.path.join(self.vdbdir, a.cpv)
96                         try:
97                                 os.makedirs(vdb_pkg_dir)
98                         except os.error:
99                                 pass
100
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)
110                         
111                         def write_key(key, value):
112                                 f = open(os.path.join(vdb_pkg_dir, key), "w")
113                                 f.write(str(value) + "\n")
114                                 f.close()
115                         
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)
126
127         def _create_profile(self, ebuilds, installed, profile):
128                 #Create $PORTDIR/profiles/categories
129                 categories = set()
130                 for cpv in chain(ebuilds.keys(), installed.keys()):
131                         categories.add(catsplit(cpv)[0])
132                 
133                 profile_dir = os.path.join(self.portdir, "profiles")
134                 try:
135                         os.makedirs(profile_dir)
136                 except os.error:
137                         pass
138                 
139                 categories_file = os.path.join(profile_dir, "categories")
140                 
141                 f = open(categories_file, "w")
142                 for cat in categories:
143                         f.write(cat + "\n")
144                 f.close()
145                 
146                 #Create $PORTDIR/eclass (we fail to digest the ebuilds if it's not there)
147                 os.makedirs(os.path.join(self.portdir, "eclass"))
148                 
149                 if profile:
150                         #This is meant to allow the consumer to set up his own profile,
151                         #with package.mask and what not.
152                         raise NotImplentedError()
153
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)
157                 settings.lock()
158
159                 trees = {
160                         self.root: {
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)
165                                 }
166                         }
167
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)
173                 
174                 return settings, trees
175
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                 myopts["--root-deps"] = "rdeps"
182                 
183                 portage.util.noiselimit = -2
184                 myparams = create_depgraph_params(myopts, myaction)
185                 success, mydepgraph, favorites = backtrack_depgraph(
186                         self.settings, self.trees, myopts, myparams, myaction, myfiles, None)
187                 portage.util.noiselimit = 0
188
189                 if success:
190                         mergelist = [x.cpv for x in mydepgraph._dynamic_config._serialized_tasks_cache]
191                         return True, mergelist
192                 else:
193                         #TODO: Use mydepgraph.display_problems() to return a useful error message
194                         return False, None