]>
Commit | Line | Data |
---|---|---|
47a4cb89 MT |
1 | #!/usr/bin/python |
2 | ||
3 | import fcntl | |
4 | import grp | |
5 | import logging | |
d59bde4c | 6 | import math |
47a4cb89 MT |
7 | import os |
8 | import re | |
9 | import shutil | |
fc4d4177 | 10 | import socket |
47a4cb89 MT |
11 | import stat |
12 | import time | |
f02283bb | 13 | import uuid |
47a4cb89 | 14 | |
7c8f2953 | 15 | import base |
93bd0aa4 | 16 | import chroot |
47a4cb89 MT |
17 | import depsolve |
18 | import packages | |
fa6d335b | 19 | import repository |
47a4cb89 MT |
20 | import transaction |
21 | import util | |
22 | ||
23 | from constants import * | |
4496b160 | 24 | from i18n import _ |
e9c20259 | 25 | from errors import BuildError, BuildRootLocked, Error |
47a4cb89 MT |
26 | |
27 | ||
28 | class Builder(object): | |
29 | # The version of the kernel this machine is running. | |
30 | kernel_version = os.uname()[2] | |
31 | ||
50f96897 | 32 | def __init__(self, pkg=None, distro_config=None, build_id=None, **pakfire_args): |
7c8f2953 MT |
33 | pakfire_args.update({ |
34 | "builder" : True, | |
35 | }) | |
47a4cb89 | 36 | |
7c8f2953 MT |
37 | # Create pakfire instance. |
38 | self.pakfire = base.Pakfire(distro_config=distro_config, **pakfire_args) | |
39 | self.distro = self.pakfire.distro | |
40 | self.path = self.pakfire.path | |
41 | ||
42 | # Open the package. | |
50f96897 | 43 | self.pkg = pkg |
7c8f2953 MT |
44 | |
45 | # XXX need to make this configureable | |
47a4cb89 MT |
46 | self.settings = { |
47 | "enable_loop_devices" : True, | |
33f4679b | 48 | "enable_ccache" : True, |
8c716255 | 49 | "enable_icecream" : False, |
47a4cb89 | 50 | } |
7c8f2953 | 51 | #self.settings.update(settings) |
47a4cb89 MT |
52 | |
53 | self.buildroot = "/buildroot" | |
54 | ||
55 | # Lock the buildroot | |
56 | self._lock = None | |
57 | self.lock() | |
58 | ||
fc4d4177 MT |
59 | # Save the build time. |
60 | self.build_time = int(time.time()) | |
f02283bb MT |
61 | |
62 | # Save the build id and generate one if no build id was provided. | |
63 | if not build_id: | |
64 | build_id = uuid.uuid4() | |
65 | ||
fc4d4177 MT |
66 | self.build_id = build_id |
67 | ||
50f96897 MT |
68 | def get_pkg(self): |
69 | return getattr(self, "_pkg", None) | |
70 | ||
71 | def set_pkg(self, pkg): | |
72 | if pkg is None: | |
73 | self.__pkg = None | |
74 | return | |
75 | ||
76 | self._pkg = packages.open(self.pakfire, None, pkg) | |
77 | ||
78 | # Log the package information. | |
79 | if not isinstance(self._pkg, packages.Makefile): | |
80 | dump = self._pkg.dump(long=True) | |
81 | self.log.info(dump) | |
82 | ||
83 | assert self.pkg | |
84 | ||
85 | pkg = property(get_pkg, set_pkg) | |
86 | ||
7c8f2953 MT |
87 | @property |
88 | def arch(self): | |
89 | """ | |
90 | Inherit architecture from distribution configuration. | |
91 | """ | |
92 | return self.distro.arch | |
93 | ||
fc4d4177 MT |
94 | @property |
95 | def info(self): | |
96 | return { | |
97 | "build_date" : time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime(self.build_time)), | |
98 | "build_host" : socket.gethostname(), | |
99 | "build_id" : self.build_id, | |
100 | "build_time" : self.build_time, | |
101 | } | |
102 | ||
47a4cb89 MT |
103 | def lock(self): |
104 | filename = os.path.join(self.path, ".lock") | |
105 | ||
106 | try: | |
107 | self._lock = open(filename, "a+") | |
108 | except IOError, e: | |
109 | return 0 | |
110 | ||
111 | try: | |
112 | fcntl.lockf(self._lock.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB) | |
113 | except IOError, e: | |
114 | raise BuildRootLocked, "Buildroot is locked" | |
115 | ||
116 | return 1 | |
117 | ||
118 | def unlock(self): | |
119 | if self._lock: | |
120 | self._lock.close() | |
121 | self._lock = None | |
122 | ||
123 | def copyin(self, file_out, file_in): | |
124 | if file_in.startswith("/"): | |
125 | file_in = file_in[1:] | |
126 | ||
127 | file_in = self.chrootPath(file_in) | |
128 | ||
129 | #if not os.path.exists(file_out): | |
130 | # return | |
131 | ||
132 | dir_in = os.path.dirname(file_in) | |
133 | if not os.path.exists(dir_in): | |
134 | os.makedirs(dir_in) | |
135 | ||
136 | logging.debug("%s --> %s" % (file_out, file_in)) | |
137 | ||
138 | shutil.copy2(file_out, file_in) | |
139 | ||
140 | def copyout(self, file_in, file_out): | |
141 | if file_in.startswith("/"): | |
142 | file_in = file_in[1:] | |
143 | ||
144 | file_in = self.chrootPath(file_in) | |
145 | ||
146 | #if not os.path.exists(file_in): | |
147 | # return | |
148 | ||
149 | dir_out = os.path.dirname(file_out) | |
150 | if not os.path.exists(dir_out): | |
151 | os.makedirs(dir_out) | |
152 | ||
153 | logging.debug("%s --> %s" % (file_in, file_out)) | |
154 | ||
155 | shutil.copy2(file_in, file_out) | |
156 | ||
157 | def copy_result(self, resultdir): | |
158 | dir_in = self.chrootPath("result") | |
159 | ||
160 | for dir, subdirs, files in os.walk(dir_in): | |
161 | basename = os.path.basename(dir) | |
162 | dir = dir[len(self.chrootPath()):] | |
163 | for file in files: | |
164 | file_in = os.path.join(dir, file) | |
165 | ||
166 | file_out = os.path.join( | |
167 | resultdir, | |
168 | basename, | |
169 | file, | |
170 | ) | |
171 | ||
172 | self.copyout(file_in, file_out) | |
173 | ||
9c2ad426 | 174 | def extract(self, requires=None, build_deps=True): |
47a4cb89 MT |
175 | """ |
176 | Gets a dependency set and extracts all packages | |
177 | to the environment. | |
178 | """ | |
9c2ad426 MT |
179 | if not requires: |
180 | requires = [] | |
5be98997 | 181 | |
9c2ad426 MT |
182 | # Add neccessary build dependencies. |
183 | requires += BUILD_PACKAGES | |
3d960a21 | 184 | |
33f4679b MT |
185 | # If we have ccache enabled, we need to extract it |
186 | # to the build chroot. | |
187 | if self.settings.get("enable_ccache"): | |
9c2ad426 | 188 | requires.append("ccache") |
33f4679b | 189 | |
5be98997 MT |
190 | # If we have icecream enabled, we need to extract it |
191 | # to the build chroot. | |
192 | if self.settings.get("enable_icecream"): | |
9c2ad426 | 193 | requires.append("icecream") |
47a4cb89 MT |
194 | |
195 | # Get build dependencies from source package. | |
196 | if isinstance(self.pkg, packages.SourcePackage): | |
197 | for req in self.pkg.requires: | |
9c2ad426 | 198 | requires.append(req) |
47a4cb89 | 199 | |
9c2ad426 MT |
200 | # Install all packages. |
201 | self.install(requires) | |
47a4cb89 MT |
202 | |
203 | # Copy the makefile and load source tarballs. | |
204 | if isinstance(self.pkg, packages.Makefile): | |
205 | self.pkg.extract(self) | |
206 | ||
4496b160 MT |
207 | elif isinstance(self.pkg, packages.SourcePackage): |
208 | self.pkg.extract(_("Extracting: %s (source)") % self.pkg.name, | |
209 | prefix=os.path.join(self.path, "build")) | |
210 | ||
47a4cb89 MT |
211 | # If we have a makefile, we can only get the build dependencies |
212 | # after we have extracted all the rest. | |
213 | if build_deps and isinstance(self.pkg, packages.Makefile): | |
214 | requires = self.make_requires() | |
215 | if not requires: | |
216 | return | |
217 | ||
9c2ad426 | 218 | self.install(requires) |
47a4cb89 | 219 | |
9c2ad426 MT |
220 | def install(self, requires): |
221 | """ | |
222 | Install everything that is required in requires. | |
223 | """ | |
c9ec78ca MT |
224 | # If we got nothing to do, we quit immediately. |
225 | if not requires: | |
226 | return | |
227 | ||
9c2ad426 MT |
228 | ds = depsolve.DependencySet(self.pakfire) |
229 | for r in requires: | |
c9ec78ca MT |
230 | if isinstance(r, packages.BinaryPackage): |
231 | ds.add_package(r) | |
232 | else: | |
233 | ds.add_requires(r) | |
9c2ad426 MT |
234 | ds.resolve() |
235 | ds.dump() | |
236 | ||
237 | ts = transaction.Transaction(self.pakfire, ds) | |
238 | ts.run() | |
47a4cb89 | 239 | |
c9ec78ca MT |
240 | def install_test(self): |
241 | pkgs = [] | |
242 | ||
243 | # Connect packages to the FS repository. | |
244 | r = repository.FileSystemRepository(self.pakfire) | |
245 | ||
246 | for dir, subdirs, files in os.walk(self.chrootPath("result")): | |
247 | for file in files: | |
248 | file = os.path.join(dir, file) | |
249 | ||
250 | if not file.endswith(PACKAGE_EXTENSION): | |
251 | continue | |
252 | ||
253 | p = packages.BinaryPackage(self.pakfire, r, file) | |
254 | pkgs.append(p) | |
255 | ||
256 | self.install(pkgs) | |
257 | ||
47a4cb89 MT |
258 | @property |
259 | def log(self): | |
260 | # XXX for now, return the root logger | |
261 | return logging.getLogger() | |
262 | ||
263 | def chrootPath(self, *args): | |
264 | # Remove all leading slashes | |
265 | _args = [] | |
266 | for arg in args: | |
267 | if arg.startswith("/"): | |
268 | arg = arg[1:] | |
269 | _args.append(arg) | |
270 | args = _args | |
271 | ||
272 | ret = os.path.join(self.path, *args) | |
273 | ret = ret.replace("//", "/") | |
274 | ||
275 | assert ret.startswith(self.path) | |
276 | ||
277 | return ret | |
278 | ||
279 | def prepare(self): | |
677ff42a MT |
280 | prepared_tag = ".prepared" |
281 | ||
282 | if os.path.exists(self.chrootPath(prepared_tag)): | |
283 | return | |
284 | ||
47a4cb89 MT |
285 | # Create directory. |
286 | if not os.path.exists(self.path): | |
287 | os.makedirs(self.path) | |
288 | ||
289 | # Create important directories. | |
290 | dirs = [ | |
291 | "build", | |
292 | self.buildroot, | |
293 | "dev", | |
294 | "dev/pts", | |
295 | "dev/shm", | |
296 | "etc", | |
297 | "proc", | |
298 | "result", | |
299 | "sys", | |
300 | "tmp", | |
301 | "usr/src", | |
302 | ] | |
33f4679b MT |
303 | |
304 | # Create cache dir if ccache is enabled. | |
305 | if self.settings.get("enable_ccache"): | |
306 | dirs.append("var/cache/ccache") | |
307 | ||
308 | if not os.path.exists(CCACHE_CACHE_DIR): | |
309 | os.makedirs(CCACHE_CACHE_DIR) | |
310 | ||
47a4cb89 MT |
311 | for dir in dirs: |
312 | dir = self.chrootPath(dir) | |
313 | if not os.path.exists(dir): | |
314 | os.makedirs(dir) | |
315 | ||
6378690e MT |
316 | # Create neccessary files like /etc/fstab and /etc/mtab. |
317 | files = ( | |
318 | "etc/fstab", | |
677ff42a MT |
319 | "etc/mtab", |
320 | prepared_tag, | |
6378690e MT |
321 | ) |
322 | ||
323 | for file in files: | |
324 | file = self.chrootPath(file) | |
325 | dir = os.path.dirname(file) | |
326 | if not os.path.exists(dir): | |
327 | os.makedirs(dir) | |
328 | f = open(file, "w") | |
329 | f.close() | |
330 | ||
47a4cb89 | 331 | self._prepare_dev() |
47a4cb89 MT |
332 | self._prepare_dns() |
333 | ||
334 | def _prepare_dev(self): | |
335 | prevMask = os.umask(0000) | |
336 | ||
337 | nodes = [ | |
338 | ("dev/null", stat.S_IFCHR | 0666, os.makedev(1, 3)), | |
339 | ("dev/full", stat.S_IFCHR | 0666, os.makedev(1, 7)), | |
340 | ("dev/zero", stat.S_IFCHR | 0666, os.makedev(1, 5)), | |
341 | ("dev/random", stat.S_IFCHR | 0666, os.makedev(1, 8)), | |
342 | ("dev/urandom", stat.S_IFCHR | 0444, os.makedev(1, 9)), | |
343 | ("dev/tty", stat.S_IFCHR | 0666, os.makedev(5, 0)), | |
344 | ("dev/console", stat.S_IFCHR | 0600, os.makedev(5, 1)), | |
345 | ] | |
346 | ||
347 | # If we need loop devices (which are optional) we create them here. | |
348 | if self.settings["enable_loop_devices"]: | |
349 | for i in range(0, 7): | |
350 | nodes.append(("dev/loop%d" % i, stat.S_IFBLK | 0660, os.makedev(7, i))) | |
351 | ||
352 | # Create all the nodes. | |
353 | for node in nodes: | |
354 | self._create_node(*node) | |
355 | ||
356 | os.symlink("/proc/self/fd/0", self.chrootPath("dev", "stdin")) | |
357 | os.symlink("/proc/self/fd/1", self.chrootPath("dev", "stdout")) | |
358 | os.symlink("/proc/self/fd/2", self.chrootPath("dev", "stderr")) | |
359 | os.symlink("/proc/self/fd", self.chrootPath("dev", "fd")) | |
360 | ||
361 | # make device node for el4 and el5 | |
362 | if self.kernel_version < "2.6.19": | |
363 | self._make_node("dev/ptmx", stat.S_IFCHR | 0666, os.makedev(5, 2)) | |
364 | else: | |
365 | os.symlink("/dev/pts/ptmx", self.chrootPath("dev", "ptmx")) | |
366 | ||
367 | os.umask(prevMask) | |
368 | ||
47a4cb89 | 369 | def _prepare_dns(self): |
18973967 MT |
370 | """ |
371 | Add DNS resolution facility to chroot environment by copying | |
372 | /etc/resolv.conf and /etc/hosts. | |
373 | """ | |
374 | for i in ("/etc/resolv.conf", "/etc/hosts"): | |
375 | self.copyin(i, i) | |
47a4cb89 MT |
376 | |
377 | def _create_node(self, filename, mode, device): | |
378 | logging.debug("Create node: %s (%s)" % (filename, mode)) | |
379 | ||
380 | filename = self.chrootPath(filename) | |
381 | ||
382 | # Create parent directory if it is missing. | |
383 | dirname = os.path.dirname(filename) | |
384 | if not os.path.exists(dirname): | |
385 | os.makedirs(dirname) | |
386 | ||
387 | os.mknod(filename, mode, device) | |
388 | ||
526c3e7f | 389 | def destroy(self): |
e412b8dc | 390 | logging.debug("Destroying environment %s" % self.path) |
47a4cb89 MT |
391 | |
392 | if os.path.exists(self.path): | |
393 | util.rm(self.path) | |
394 | ||
e412b8dc MT |
395 | def cleanup(self): |
396 | logging.debug("Cleaning environemnt.") | |
397 | ||
398 | # Run make clean and let it cleanup its stuff. | |
399 | self.make("clean") | |
400 | ||
401 | # Remove the build directory and buildroot. | |
402 | dirs = ("build", self.buildroot, "result") | |
403 | ||
404 | for d in dirs: | |
405 | d = self.chrootPath(d) | |
406 | if not os.path.exists(d): | |
407 | continue | |
408 | ||
409 | util.rm(d) | |
410 | os.makedirs(d) | |
411 | ||
412 | # Clear make_info cache. | |
413 | if hasattr(self, "_make_info"): | |
414 | del self._make_info | |
415 | ||
47a4cb89 MT |
416 | def _mountall(self): |
417 | self.log.debug("Mounting environment") | |
418 | for cmd, mountpoint in self.mountpoints: | |
419 | cmd = "%s %s" % (cmd, self.chrootPath(mountpoint)) | |
93bd0aa4 | 420 | chroot.do(cmd, shell=True) |
47a4cb89 MT |
421 | |
422 | def _umountall(self): | |
423 | self.log.debug("Umounting environment") | |
424 | for cmd, mountpoint in self.mountpoints: | |
425 | cmd = "umount -n %s" % self.chrootPath(mountpoint) | |
93bd0aa4 | 426 | chroot.do(cmd, raiseExc=0, shell=True) |
47a4cb89 MT |
427 | |
428 | @property | |
429 | def mountpoints(self): | |
430 | ret = [ | |
431 | ("mount -n -t proc pakfire_chroot_proc", "proc"), | |
432 | ("mount -n -t sysfs pakfire_chroot_sysfs", "sys"), | |
433 | ] | |
434 | ||
435 | mountopt = "gid=%d,mode=0620,ptmxmode=0666" % grp.getgrnam("tty").gr_gid | |
436 | if self.kernel_version >= "2.6.29": | |
437 | mountopt += ",newinstance" | |
438 | ||
439 | ret.extend([ | |
440 | ("mount -n -t devpts -o %s pakfire_chroot_devpts" % mountopt, "dev/pts"), | |
441 | ("mount -n -t tmpfs pakfire_chroot_shmfs", "dev/shm"), | |
442 | ]) | |
443 | ||
33f4679b MT |
444 | if self.settings.get("enable_ccache"): |
445 | ret.append(("mount -n --bind %s" % CCACHE_CACHE_DIR, "var/cache/ccache")) | |
446 | ||
47a4cb89 MT |
447 | return ret |
448 | ||
d59bde4c MT |
449 | @staticmethod |
450 | def calc_parallelism(): | |
451 | """ | |
452 | Calculate how many processes to run | |
453 | at the same time. | |
454 | ||
455 | We take the log10(number of processors) * factor | |
456 | """ | |
457 | num = os.sysconf("SC_NPROCESSORS_CONF") | |
458 | if num == 1: | |
459 | return 2 | |
460 | else: | |
461 | return int(round(math.log10(num) * 26)) | |
462 | ||
47a4cb89 MT |
463 | @property |
464 | def environ(self): | |
465 | env = { | |
0cf10c2d MT |
466 | # Add HOME manually, because it is occasionally not set |
467 | # and some builds get in trouble then. | |
468 | "HOME" : "/root", | |
89ebac67 MT |
469 | "TERM" : os.environ.get("TERM", "dumb"), |
470 | "PS1" : "\u:\w\$ ", | |
0cf10c2d | 471 | |
47a4cb89 | 472 | "BUILDROOT" : self.buildroot, |
d59bde4c | 473 | "PARALLELISMFLAGS" : "-j%s" % self.calc_parallelism(), |
47a4cb89 MT |
474 | } |
475 | ||
476 | # Inherit environment from distro | |
477 | env.update(self.pakfire.distro.environ) | |
478 | ||
5be98997 MT |
479 | # Icecream environment settings |
480 | if self.settings.get("enable_icecream", None): | |
481 | # Set the toolchain path | |
482 | if self.settings.get("icecream_toolchain", None): | |
483 | env["ICECC_VERSION"] = self.settings.get("icecream_toolchain") | |
484 | ||
485 | # Set preferred host if configured. | |
486 | if self.settings.get("icecream_preferred_host", None): | |
487 | env["ICECC_PREFERRED_HOST"] = \ | |
488 | self.settings.get("icecream_preferred_host") | |
489 | ||
47a4cb89 MT |
490 | # XXX what do we need else? |
491 | ||
492 | return env | |
493 | ||
494 | def do(self, command, shell=True, personality=None, *args, **kwargs): | |
495 | ret = None | |
496 | try: | |
497 | # Environment variables | |
498 | env = self.environ | |
499 | ||
500 | if kwargs.has_key("env"): | |
501 | env.update(kwargs.pop("env")) | |
502 | ||
15398910 MT |
503 | logging.debug("Environment:") |
504 | for k, v in sorted(env.items()): | |
505 | logging.debug(" %s=%s" % (k, v)) | |
506 | ||
e360ea59 MT |
507 | # Update personality it none was set |
508 | if not personality: | |
7c8f2953 | 509 | personality = self.distro.personality |
e360ea59 | 510 | |
5be98997 MT |
511 | # Make every shell to a login shell because we set a lot of |
512 | # environment things there. | |
513 | if shell: | |
514 | command = ["bash", "--login", "-c", command] | |
515 | ||
47a4cb89 MT |
516 | self._mountall() |
517 | ||
518 | if not kwargs.has_key("chrootPath"): | |
519 | kwargs["chrootPath"] = self.chrootPath() | |
520 | ||
c96185e9 | 521 | ret = chroot.do( |
47a4cb89 MT |
522 | command, |
523 | personality=personality, | |
5be98997 | 524 | shell=False, |
47a4cb89 MT |
525 | env=env, |
526 | logger=self.log, | |
527 | *args, | |
528 | **kwargs | |
529 | ) | |
530 | ||
531 | finally: | |
532 | self._umountall() | |
533 | ||
534 | return ret | |
535 | ||
536 | def make(self, *args, **kwargs): | |
4496b160 MT |
537 | if isinstance(self.pkg, packages.Makefile): |
538 | filename = os.path.basename(self.pkg.filename) | |
539 | elif isinstance(self.pkg, packages.SourcePackage): | |
540 | filename = "%s.%s" % (self.pkg.name, MAKEFILE_EXTENSION) | |
541 | ||
542 | return self.do("make -f /build/%s %s" % (filename, " ".join(args)), | |
5be98997 | 543 | **kwargs) |
47a4cb89 MT |
544 | |
545 | @property | |
546 | def make_info(self): | |
547 | if not hasattr(self, "_make_info"): | |
548 | info = {} | |
549 | ||
550 | output = self.make("buildinfo", returnOutput=True) | |
551 | ||
552 | for line in output.splitlines(): | |
553 | # XXX temporarily | |
554 | if not line: | |
555 | break | |
556 | ||
557 | m = re.match(r"^(\w+)=(.*)$", line) | |
558 | if not m: | |
559 | continue | |
560 | ||
561 | info[m.group(1)] = m.group(2).strip("\"") | |
562 | ||
563 | self._make_info = info | |
564 | ||
565 | return self._make_info | |
566 | ||
567 | @property | |
568 | def packages(self): | |
569 | if hasattr(self, "_packages"): | |
570 | return self._packages | |
571 | ||
572 | pkgs = [] | |
573 | output = self.make("packageinfo", returnOutput=True) | |
574 | ||
575 | pkg = {} | |
576 | for line in output.splitlines(): | |
577 | if not line: | |
578 | pkgs.append(pkg) | |
579 | pkg = {} | |
580 | ||
581 | m = re.match(r"^(\w+)=(.*)$", line) | |
582 | if not m: | |
583 | continue | |
584 | ||
585 | k, v = m.groups() | |
586 | pkg[k] = v.strip("\"") | |
587 | ||
3723913b MT |
588 | # Create a dummy repository to link the virtual packages to |
589 | repo = repository.DummyRepository(self.pakfire) | |
590 | ||
47a4cb89 MT |
591 | self._packages = [] |
592 | for pkg in pkgs: | |
fa6d335b | 593 | pkg = packages.VirtualPackage(self.pakfire, pkg) # XXX had to remove repo here?! |
47a4cb89 MT |
594 | self._packages.append(pkg) |
595 | ||
596 | return self._packages | |
597 | ||
598 | def make_requires(self): | |
599 | return self.make_info.get("PKG_BUILD_DEPS", "").split() | |
600 | ||
601 | def make_sources(self): | |
602 | return self.make_info.get("PKG_FILES", "").split() | |
603 | ||
5be98997 MT |
604 | def create_icecream_toolchain(self): |
605 | if not self.settings.get("enable_icecream", None): | |
606 | return | |
607 | ||
608 | out = self.do("icecc --build-native", returnOutput=True) | |
609 | ||
610 | for line in out.splitlines(): | |
611 | m = re.match(r"^creating ([a-z0-9]+\.tar\.gz)", line) | |
612 | if m: | |
613 | self.settings["icecream_toolchain"] = "/%s" % m.group(1) | |
614 | ||
47a4cb89 | 615 | def build(self): |
5be98997 MT |
616 | self.create_icecream_toolchain() |
617 | ||
e9c20259 MT |
618 | try: |
619 | self.make("build") | |
620 | ||
621 | except Error: | |
622 | raise BuildError, "The build command failed." | |
47a4cb89 MT |
623 | |
624 | for pkg in reversed(self.packages): | |
d507be4d | 625 | packager = packages.BinaryPackager(self.pakfire, pkg, self) |
47a4cb89 MT |
626 | packager() |
627 | ||
628 | def dist(self): | |
629 | self.pkg.dist(self) | |
630 | ||
631 | def shell(self, args=[]): | |
e9c20259 MT |
632 | if not util.cli_is_interactive(): |
633 | logging.warning("Cannot run shell on non-interactive console.") | |
634 | return | |
635 | ||
9c2ad426 MT |
636 | # Install all packages that are needed to run a shell. |
637 | self.install(SHELL_PACKAGES) | |
638 | ||
47a4cb89 | 639 | # XXX need to set CFLAGS here |
a7596ccf | 640 | command = "/usr/sbin/chroot %s /usr/bin/chroot-shell %s" % \ |
47a4cb89 MT |
641 | (self.chrootPath(), " ".join(args)) |
642 | ||
e360ea59 MT |
643 | # Add personality if we require one |
644 | if self.pakfire.distro.personality: | |
a7596ccf MT |
645 | command = "%s %s" % (self.pakfire.distro.personality, command) |
646 | ||
647 | for key, val in self.environ.items(): | |
648 | command = "%s=\"%s\" " % (key, val) + command | |
e360ea59 | 649 | |
47a4cb89 | 650 | # Empty the environment |
a7596ccf | 651 | command = "env -i - %s" % command |
47a4cb89 MT |
652 | |
653 | logging.debug("Shell command: %s" % command) | |
654 | ||
655 | try: | |
656 | self._mountall() | |
657 | ||
658 | shell = os.system(command) | |
659 | return os.WEXITSTATUS(shell) | |
660 | ||
661 | finally: | |
662 | self._umountall() |