]> git.ipfire.org Git - people/stevee/pakfire.git/blame - pakfire/base.py
Fix grouplist command.
[people/stevee/pakfire.git] / pakfire / base.py
CommitLineData
47a4cb89
MT
1#!/usr/bin/python
2
7c8f2953
MT
3import logging
4import os
5import random
6import string
7
18edfe75 8import builder
53bb7960 9import config
7c8f2953
MT
10import distro
11import logger
53bb7960 12import repository
ae20b05f 13import packages
c605d735 14import satsolver
7c8f2953
MT
15import util
16
7c8f2953 17from constants import *
7c8f2953
MT
18from i18n import _
19
7c8f2953 20class Pakfire(object):
018127aa
MT
21 RELATIONS = (
22 (">=", satsolver.REL_GE,),
23 ("<=", satsolver.REL_LE,),
24 ("=" , satsolver.REL_EQ,),
25 ("<" , satsolver.REL_LT,),
26 (">" , satsolver.REL_GT,),
27 )
28
ae20b05f
MT
29 def __init__(self, builder=False, configs=[], enable_repos=None,
30 disable_repos=None, distro_config=None):
7c8f2953
MT
31 # Check if we are operating as the root user.
32 self.check_root_user()
33
3ad4bb5a
MT
34 config_type = None
35
7c8f2953
MT
36 # The path where we are operating in.
37 if builder:
3ad4bb5a 38 config_type = "builder"
7c8f2953
MT
39 self.builder = True
40 self.path = os.path.join(BUILD_ROOT, util.random_string())
41 else:
42 self.builder = False
43 self.path = "/"
44
45 # XXX check if we are actually running on an ipfire system.
46
47 # Read configuration file(s)
3ad4bb5a 48 self.config = config.Config(type=config_type)
7c8f2953
MT
49 for filename in configs:
50 self.config.read(filename)
51
52 # Setup the logger
53 logger.setup_logging(self.config)
54 self.config.dump()
55
56 # Get more information about the distribution we are running
57 # or building
53bb7960 58 self.distro = distro.Distribution(self, distro_config)
c605d735 59 self.pool = satsolver.Pool(self.distro.arch)
ae20b05f
MT
60 self.repos = repository.Repositories(self,
61 enable_repos=enable_repos, disable_repos=disable_repos)
7c8f2953 62
c605d735
MT
63 # Create the solver of this pakfire instance.
64 # XXX maybe we can only create it when we need it?
65 #self.solver = satsolver.Solver(self, self.pool)
66
67 def create_solver(self):
68 return satsolver.Solver(self, self.pool)
69
70 def create_request(self):
71 return satsolver.Request(self.pool)
7c8f2953 72
018127aa
MT
73 def create_relation(self, s):
74 assert s
75
76 if s.startswith("/"):
77 return satsolver.Relation(self.pool, s)
78
79 for pattern, type in self.RELATIONS:
80 if not pattern in s:
81 continue
82
83 name, version = s.split(pattern, 1)
84
85 return satsolver.Relation(self.pool, name, version, type)
86
87 return satsolver.Relation(self.pool, s)
88
7c8f2953
MT
89 def destroy(self):
90 if not self.path == "/":
91 util.rm(self.path)
92
93 @property
94 def supported_arches(self):
3ad4bb5a 95 return self.config.supported_arches
7c8f2953
MT
96
97 def check_root_user(self):
98 if not os.getuid() == 0 or not os.getgid() == 0:
99 raise Exception, "You must run pakfire as the root user."
100
101 def check_build_mode(self):
102 """
103 Check if we are running in build mode.
104 Otherwise, raise an exception.
105 """
106 if not self.builder:
107 raise BuildError, "Cannot build when not in build mode."
108
109 def check_host_arch(self, arch):
110 """
111 Check if we can build for arch.
112 """
7c8f2953
MT
113 # If no arch was given on the command line we build for our
114 # own arch which should always work.
115 if not arch:
116 return True
117
3ad4bb5a 118 if not self.config.host_supports_arch(arch):
7c8f2953
MT
119 raise BuildError, "Cannot build for the target architecture: %s" % arch
120
121 raise BuildError, arch
18edfe75
MT
122
123 def install(self, requires):
ae20b05f
MT
124 # Create a new request.
125 request = self.solver.create_request()
18edfe75 126 for req in requires:
ae20b05f 127 request.install(req)
18edfe75 128
ae20b05f
MT
129 # Do the solving.
130 t = self.solver.solve(request)
18edfe75 131
ae20b05f 132 if not t:
18edfe75
MT
133 return
134
c0fd807c
MT
135 # Ask if the user acknowledges the transaction.
136 if not t.cli_yesno():
137 return
138
139 # Run the transaction.
ae20b05f 140 t.run()
18edfe75 141
e0b99370
MT
142 def localinstall(self, files):
143 repo_name = "localinstall"
144
145 # Create a new repository that holds all packages we passed on
146 # the commandline.
147 repo = self.solver.pool.create_repo(repo_name)
148
149 # Open all passed files and try to open them.
150 for file in files:
151 pkg = packages.open(self, None, file)
152
153 if not isinstance(pkg, packages.BinaryPackage):
154 logging.warning("Skipping package which is a wrong format: %s" % file)
155 continue
156
157 # Add the package information to the solver.
158 self.solver.add_package(pkg, repo_name)
159
160 # Break if no packages were added at all.
161 if not repo.size():
162 logging.critical("There are no packages to install.")
163 return
164
165 # Create a new request which contains all solvabled from the CLI and
166 # try to solve it.
167 request = self.solver.create_request()
168 for solvable in repo:
e0b99370
MT
169 request.install(solvable)
170
171 t = self.solver.solve(request)
172
173 # If solving was not possible, we exit here.
174 if not t:
175 return
176
c0fd807c 177 # Ask the user if this is okay.
3ad4bb5a
MT
178 #if not t.cli_yesno():
179 # return
c0fd807c
MT
180
181 # If okay, run the transcation.
e0b99370
MT
182 t.run()
183
18edfe75 184 def update(self, pkgs):
0c1a80b8
MT
185 request = self.solver.create_request()
186
187 repo_installed = self.solver.get_repo("installed")
188 assert repo_installed
189
190 for solvable in repo_installed:
191 request.update(solvable)
192
193 t = self.solver.solve(request, update=True)
194
195 if not t:
196 return
197
c0fd807c
MT
198 # Ask the user if the transaction is okay.
199 if not t.cli_yesno():
200 return
0c1a80b8 201
c0fd807c 202 # Run the transaction.
0c1a80b8 203 t.run()
18edfe75 204
a39fd08b
MT
205 def remove(self, pkgs):
206 # Create a new request.
207 request = self.solver.create_request()
208 for pkg in pkgs:
209 request.remove(pkg)
210
211 # Solve the request.
212 t = self.solver.solve(request)
213
214 if not t:
215 return
216
c0fd807c
MT
217 # Ask the user if okay.
218 if not t.cli_yesno():
219 return
220
221 # Process the transaction.
a39fd08b
MT
222 t.run()
223
c1e7f927 224 def info(self, patterns):
18edfe75
MT
225 pkgs = []
226
1f27e8fe
MT
227 # For all patterns we run a single search which returns us a bunch
228 # of solvables which are transformed into Package objects.
18edfe75 229 for pattern in patterns:
1f27e8fe
MT
230 solvs = self.pool.search(pattern, satsolver.SEARCH_GLOB, "solvable:name")
231
232 for solv in solvs:
233 pkgs.append(packages.SolvPackage(self, solv))
18edfe75
MT
234
235 return packages.PackageListing(pkgs)
236
237 def search(self, pattern):
238 # Do the search.
f1ab3110 239 pkgs = []
884cd2fb 240 for solv in self.pool.search(pattern, satsolver.SEARCH_STRING|satsolver.SEARCH_FILES):
f1ab3110 241 pkgs.append(packages.SolvPackage(self, solv))
18edfe75
MT
242
243 # Return the output as a package listing.
244 return packages.PackageListing(pkgs)
245
246 def groupinstall(self, group):
247 pkgs = self.grouplist(group)
248
249 self.install(pkgs)
250
251 def grouplist(self, group):
fec9a917
MT
252 pkgs = []
253
254 for solv in self.pool.search(group, satsolver.SEARCH_SUBSTRING, "solvable:group"):
255 pkg = packages.SolvPackage(self, solv)
18edfe75 256
fec9a917
MT
257 if group in pkg.groups and not pkg.name in pkgs:
258 pkgs.append(pkg.name)
18edfe75 259
fec9a917 260 return sorted(pkgs)
18edfe75
MT
261
262 @staticmethod
dacaa18b 263 def build(pkg, resultdirs=None, shell=False, **kwargs):
18edfe75
MT
264 if not resultdirs:
265 resultdirs = []
266
267 b = builder.Builder(pkg, **kwargs)
268 p = b.pakfire
269
270 # Always include local repository.
271 resultdirs.append(p.repos.local_build.path)
272
273 try:
274 b.prepare()
275 b.extract()
276 b.build()
277 b.install_test()
278
279 # Copy-out all resultfiles
280 for resultdir in resultdirs:
281 if not resultdir:
282 continue
283
284 b.copy_result(resultdir)
285
286 except BuildError:
dacaa18b
MT
287 if shell:
288 b.shell()
289 else:
290 raise
18edfe75
MT
291
292 finally:
293 b.destroy()
294
295 @staticmethod
296 def shell(pkg, **kwargs):
297 b = builder.Builder(pkg, **kwargs)
298
299 try:
300 b.prepare()
301 b.extract()
302 b.shell()
303 finally:
304 b.destroy()
305
306 @staticmethod
50f96897
MT
307 def dist(pkgs, resultdirs=None, **pakfire_args):
308 # Create a builder with empty package.
309 b = builder.Builder(None, **pakfire_args)
18edfe75
MT
310 p = b.pakfire
311
312 if not resultdirs:
313 resultdirs = []
314
315 # Always include local repository
316 resultdirs.append(p.repos.local_build.path)
317
318 try:
319 b.prepare()
18edfe75 320
50f96897
MT
321 for pkg in pkgs:
322 b.pkg = pkg
18edfe75 323
50f96897 324 b.extract(build_deps=False)
18edfe75 325
50f96897
MT
326 # Run the actual dist.
327 b.dist()
328
329 # Copy-out all resultfiles
330 for resultdir in resultdirs:
331 if not resultdir:
332 continue
333
334 b.copy_result(resultdir)
335
336 # Cleanup the stuff that the package left.
337 b.cleanup()
18edfe75
MT
338 finally:
339 b.destroy()
340
341 def provides(self, patterns):
342 pkgs = []
343 for pattern in patterns:
c605d735 344 pkgs += self.repos.whatprovides(pattern)
18edfe75
MT
345
346 pkgs = packages.PackageListing(pkgs)
347 #pkgs.unique()
348
349 return pkgs
350
351 def requires(self, patterns):
352 pkgs = []
353 for pattern in patterns:
ae20b05f 354 pkgs += self.repos.get_by_requires(pattern)
18edfe75
MT
355
356 pkgs = packages.PackageListing(pkgs)
357 #pkgs.unique()
358
359 return pkgs
360
361 def repo_create(self, path, input_paths):
c605d735 362 repo = repository.RepositoryDir(
18edfe75
MT
363 self,
364 name="new",
365 description="New repository.",
366 path=path,
367 )
368
369 for input_path in input_paths:
c605d735 370 repo.collect_packages(input_path)
18edfe75
MT
371
372 repo.save()
373
374 def repo_list(self):
c605d735 375 return [r for r in self.repos]