/[gentoo-src]/portage/pym/ebuild.py
Gentoo

Contents of /portage/pym/ebuild.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.26 - (show annotations) (download) (as text)
Tue May 10 00:30:47 2005 UTC (9 years, 3 months ago) by ferringb
Branch: MAIN
CVS Tags: HEAD
Branch point for: portage_2_1
Changes since 1.25: +1 -2 lines
File MIME type: text/x-python
testing tweak, should kill off the sandbox debug log issues in /tmp .

1 #!/usr/bin/python
2 # ebuild.py; Ebuild classes/abstraction of phase processing, and communicating with a ebuild-daemon.sh instance
3 # Copyright 2005 Gentoo Foundation
4 # Distributed under the terms of the GNU General Public License v2
5 #$Header: /var/cvsroot/gentoo-src/portage/pym/ebuild.py,v 1.25 2005/05/05 02:12:06 vapier Exp $
6
7
8 import os,sys,traceback
9 import portage_const,types
10 #still needed?
11 from portage_const import *
12 import portage_locks, portage_util
13 import portage_exec
14 import portage_versions
15 import shutil, anydbm
16 import stat
17 import string
18
19 def shutdown_all_processors():
20 """kill off all known processors"""
21 global active_ebp_list, inactive_ebp_list
22 if type(active_ebp_list) != types.ListType:
23 print "warning, ebuild.active_ebp_list wasn't a list."
24 active_ebp_list = []
25 if type(inactive_ebp_list) != types.ListType:
26 print "warning, ebuild.inactive_ebp_list wasn't a list."
27 inactive_ebp_list = []
28 while len(active_ebp_list) > 0:
29 try: active_ebp_list[0].shutdown_processor()
30 except (IOError,OSError):
31 active_ebp_list.pop(0)
32 continue
33 try: active_ebp_list.pop(0)
34 except IndexError: pass
35 while len(inactive_ebp_list) > 0:
36 try:
37 inactive_ebp_list[0].shutdown_processor()
38 except (IOError,OSError):
39 inactive_ebp_list.pop(0)
40 continue
41 try: inactive_ebp_list.pop(0)
42 except IndexError: pass
43
44
45 inactive_ebp_list = []
46 active_ebp_list = []
47
48 def request_ebuild_processor(ebuild_daemon_path=portage_const.EBUILD_DAEMON_PATH,userpriv=False, \
49 sandbox=None,fakeroot=False,save_file=None):
50 """request an ebuild_processor instance from the pool, or create a new one
51 this walks through the requirements, matching a inactive processor if one exists
52 note fakerooted processors are never reused, do to the nature of fakeroot"""
53
54 if sandbox == None:
55 sandbox = portage_exec.sandbox_capable
56
57 global inactive_ebp_list, active_ebp_list
58 if not fakeroot:
59 for x in inactive_ebp_list:
60 if not x.locked() and x.ebd == ebuild_daemon_path and \
61 x.userprived() == userpriv and (x.sandboxed() or not sandbox):
62 inactive_ebp_list.remove(x)
63 active_ebp_list.append(x)
64 return x
65 active_ebp_list.append(ebuild_processor(userpriv=userpriv,sandbox=sandbox,fakeroot=fakeroot,save_file=save_file))
66 return active_ebp_list[-1]
67
68 def release_ebuild_processor(ebp):
69 """the inverse of request_ebuild_processor. Any processor requested via request_ebuild_processor
70 _must_ be released via this function once it's no longer in use.
71 this includes fakerooted processors.
72 Returns True exempting when the processor requested to be released isn't marked as active"""
73
74 global inactive_ebp_list, active_ebp_list
75 try: active_ebp_list.remove(ebp)
76 except ValueError: return False
77
78 try: inactive_ebp_list.index(ebp)
79 except ValueError:
80 # if it's a fakeroot'd process, we throw it away. it's not useful outside of a chain of calls
81 if not ebp.onetime():
82 inactive_ebp_list.append(ebp)
83 else:
84 del ebp
85 return True
86
87 # if it makes it this far, that means ebp was already in the inactive list.
88 # which is indicative of an internal fsck up.
89 import traceback
90 print "ebp was requested to be free'd, yet it already is claimed inactive _and_ was in the active list"
91 print "this means somethings horked, badly"
92 traceback.print_stack()
93 return False
94
95
96
97 class ebuild_processor:
98 """abstraction of a running ebuild.sh instance- the env, functions, etc that ebuilds expect."""
99 def __init__(self, ebuild_daemon_path=portage_const.EBUILD_DAEMON_PATH,userpriv=False, sandbox=True, \
100 fakeroot=False,save_file=None):
101 """ebuild_daemon_path shouldn't be fooled with unless the caller knows what they're doing.
102 sandbox enables a sandboxed processor
103 userpriv enables a userpriv'd processor
104 fakeroot enables a fakeroot'd processor- this is a mutually exclusive option to sandbox, and
105 requires userpriv to be enabled. Violating this will result in nastyness"""
106
107 self.ebd = ebuild_daemon_path
108 from portage_data import portage_uid, portage_gid
109 spawn_opts = {}
110
111 if fakeroot and (sandbox or not userpriv):
112 import traceback
113 traceback.print_stack()
114 print "warning, was asking to enable fakeroot but-"
115 print "sandbox",sandbox,"userpriv",userpriv
116 print "this isn't valid. bailing"
117 raise Exception,"cannot initialize with sandbox and fakeroot"
118
119 if userpriv:
120 self.__userpriv = True
121 spawn_opts.update({"uid":portage_uid,"gid":portage_gid,"groups":[portage_gid],"umask":002})
122 else:
123 if portage_exec.userpriv_capable:
124 spawn_opts.update({"gid":portage_gid,"groups":[0,portage_gid]})
125 self.__userpriv = False
126
127 # open the pipes to be used for chatting with the new daemon
128 cread, cwrite = os.pipe()
129 dread, dwrite = os.pipe()
130 self.__sandbox = False
131 self.__fakeroot = False
132
133 # since it's questionable which spawn method we'll use (if sandbox or fakeroot fex),
134 # we ensure the bashrc is invalid.
135 env={"BASHRC":"/etc/portage/spork/not/valid/ha/ha"}
136 args = []
137 if sandbox:
138 if fakeroot:
139 print "!!! ERROR: fakeroot was on, but sandbox was also on"
140 sys.exit(1)
141 self.__sandbox = True
142 spawn_func = portage_exec.spawn_sandbox
143
144 elif fakeroot:
145 self.__fakeroot = True
146 spawn_func = portage_exec.spawn_fakeroot
147 args.append(save_file)
148 else:
149 spawn_func = portage_exec.spawn
150
151 self.pid = spawn_func(self.ebd+" daemonize", fd_pipes={0:0, 1:1, 2:2, 3:cread, 4:dwrite},
152 returnpid=True,env=env, *args, **spawn_opts)[0]
153
154 os.close(cread)
155 os.close(dwrite)
156 self.ebd_write = os.fdopen(cwrite,"w")
157 self.ebd_read = os.fdopen(dread,"r")
158
159 # basically a quick "yo" to the daemon
160 self.write("dude?")
161 if not self.expect("dude!"):
162 print "error in server coms, bailing."
163 raise Exception("expected 'dude!' response from ebd, which wasn't received. likely a bug")
164 if self.__sandbox:
165 self.write("sandbox_log?")
166 self.__sandbox_log = self.read().split()[0]
167 self.dont_export_vars=self.read().split()
168 # locking isn't used much, but w/ threading this will matter
169 self.unlock()
170
171 def sandboxed(self):
172 """is this instance sandboxed?"""
173 return self.__sandbox
174
175 def userprived(self):
176 """is this instance userprived?"""
177 return self.__userpriv
178
179 def fakerooted(self):
180 """is this instance fakerooted?"""
181 return self.__fakeroot
182
183 def onetime(self):
184 """is this instance going to be discarded after usage; eg is it fakerooted?"""
185 return self.__fakeroot
186
187 def write(self, string,flush=True):
188 """talk to running daemon. Disabling flush is useful when dumping large amounts of data
189 all strings written are automatically \\n terminated"""
190 if string[-1] == "\n":
191 self.ebd_write.write(string)
192 else:
193 self.ebd_write.write(string +"\n")
194 if flush:
195 self.ebd_write.flush()
196
197 def expect(self, want):
198 """read from the daemon, and return true or false if the returned string is what is expected"""
199 got=self.ebd_read.readline()
200 return want==got[:-1]
201
202 def read(self,lines=1):
203 """read data from the daemon. Shouldn't be called except internally"""
204 mydata=''
205 while lines > 0:
206 mydata += self.ebd_read.readline()
207 lines -= 1
208 return mydata
209
210 def sandbox_summary(self, move_log=False):
211 """if the instance is sandboxed, print the sandbox access summary"""
212 if not os.path.exists(self.__sandbox_log):
213 self.write("end_sandbox_summary")
214 return 0
215 violations=portage_util.grabfile(self.__sandbox_log)
216 if len(violations)==0:
217 self.write("end_sandbox_summary")
218 return 0
219 if not move_log:
220 move_log=self.__sandbox_log
221 elif move_log != self.__sandbox_log:
222 myf=open(move_log)
223 for x in violations:
224 myf.write(x+"\n")
225 myf.close()
226 from output import red
227 self.ebd_write.write(red("--------------------------- ACCESS VIOLATION SUMMARY ---------------------------")+"\n")
228 self.ebd_write.write(red("LOG FILE = \"%s\"" % move_log)+"\n\n")
229 for x in violations:
230 self.ebd_write.write(x+"\n")
231 self.write(red("--------------------------------------------------------------------------------")+"\n")
232 self.write("end_sandbox_summary")
233 try:
234 os.remove(self.__sandbox_log)
235 except (IOError, OSError), e:
236 print "exception caught when cleansing sandbox_log=%s" % str(e)
237 return 1
238
239 def preload_eclasses(self, ec_file):
240 """this preloades eclasses into a function, thus avoiding the cost of going to disk.
241 preloading eutils (which is heaviliy inherited) speeds up regen times fex"""
242 if not os.path.exists(ec_file):
243 return 1
244 self.write("preload_eclass %s" % ec_file)
245 if self.expect("preload_eclass succeeded"):
246 self.preloaded_eclasses=True
247 return True
248 return False
249
250 def lock(self):
251 """lock the processor. Currently doesn't block any access, but will"""
252 self.processing_lock = True
253
254 def unlock(self):
255 """unlock the processor"""
256 self.processing_lock = False
257
258 def locked(self):
259 """is the processor locked?"""
260 return self.processing_lock
261
262 def is_alive(self):
263 """returns if it's known if the processor has been shutdown.
264 Currently doesn't check to ensure the pid is still running, yet it should"""
265 return self.pid != None
266
267 def shutdown_processor(self):
268 """tell the daemon to shut itself down, and mark this instance as dead"""
269 try:
270 if self.is_alive():
271 self.write("shutdown_daemon")
272 self.ebd_write.close()
273 self.ebd_read.close()
274
275 # now we wait.
276 os.waitpid(self.pid,0)
277 except (IOError,OSError,ValueError):
278 pass
279
280 # we *really* ought to modify portageatexit so that we can set limits for waitpid.
281 # currently, this assumes all went well.
282 # which isn't always true.
283 self.pid = None
284
285 def set_sandbox_state(self,state):
286 """tell the daemon whether to enable the sandbox, or disable it"""
287 if state:
288 self.write("set_sandbox_state 1")
289 else:
290 self.write("set_sandbox_state 0")
291
292 def send_env(self, mysettings):
293 """essentially transfer the ebuild's desired env to the running daemon
294 accepts a portage.config instance, although it will accept dicts at some point"""
295 be=mysettings.bash_environ()
296 self.write("start_receiving_env\n")
297 exported_keys = ''
298 for x in be.keys():
299 if x not in self.dont_export_vars:
300 self.write("%s=%s\n" % (x,be[x]), flush=False)
301 exported_keys += x+' '
302 self.write("export "+exported_keys,flush=False)
303 self.write("end_receiving_env")
304 return self.expect("env_received")
305
306 def set_logfile(self,logfile=''):
307 """relevant only when the daemon is sandbox'd, set the logfile"""
308 self.write("logging %s" % logfile)
309 return self.expect("logging_ack")
310
311
312 def __del__(self):
313 """simply attempts to notify the daemon to die"""
314 # for this to be reached means we ain't in a list no more.
315 if self.pid:
316 self.shutdown_processor()
317
318
319 class ebuild_handler:
320 """abstraction of ebuild phases, fetching exported keys, fetching srcs, etc"""
321 import portageq
322 def __init__(self, process_limit=5):
323 """process_limit is currently ignored"""
324 self.processed = 0
325 self.__process_limit = process_limit
326 self.preloaded_eclasses = False
327 self.__ebp = None
328
329 def __del__(self):
330 """only ensures any processors this handler has claimed are released"""
331 if self.__ebp:
332 release_ebuild_processor(self.__ebp)
333
334 # this is an implementation of stuart's confcache/sandbox trickery, basically the file/md5 stuff implemented in
335 # python with a basic bash wrapper that calls back to this.
336 # all credit for the approach goes to him, as stated, this is just an implementation of it.
337 # bugs should be thrown at ferringb.
338 def load_confcache(self,transfer_to,confcache=portage_const.CONFCACHE_FILE,
339 confcache_list=portage_const.CONFCACHE_LIST):
340 """verifys a requested conf cache, removing the global cache if it's stale.
341 The handler should be the only one to call this"""
342 from portage_checksum import perform_md5
343 from output import red
344 if not self.__ebp:
345 import traceback
346 traceback.print_stack()
347 print "err... no ebp, yet load_confcache called. invalid"
348 raise Exception,"load_confcache called yet no running processor. bug?"
349
350 valid=True
351 lock=None
352 if not os.path.exists(confcache_list):
353 print "confcache file listing doesn't exist"
354 valid=False
355 elif not os.path.exists(confcache):
356 print "confcache doesn't exist"
357 valid=False
358 else:
359 lock=portage_locks.lockfile(confcache_list,wantnewlockfile=1)
360 try:
361 myf=anydbm.open(confcache_list, "r", 0664)
362 for l in myf.keys():
363 # file, md5
364 if perform_md5(l,calc_prelink=1) != myf[l]:
365 print red("***")+" confcache is stale: %s: recorded md5: %s: actual: %s:" % (l,myf[l],perform_md5(l,calc_prelink=1))
366 raise Exception("md5 didn't match")
367 myf.close()
368 # verify env now.
369 new_cache=[]
370 env_vars=[]
371
372 # guessing on THOST. I'm sure it's wrong...
373
374 env_translate={"build_alias":"CBUILD","host_alias":"CHOST","target_alias":"THOST"}
375 cache=portage_util.grabfile(confcache)
376
377 x=0
378 while x < len(cache):
379 #ac_cv_env
380 if cache[x][0:10] == "ac_cv_env_":
381 f=cache[x][10:].find("_set")
382 if f == -1 or f==11:
383 cache.pop(x)
384 continue
385 env_vars.append(cache[x][10:10 + cache[x][10:].find("_set")])
386 x += 1
387 else:
388 new_cache.append(cache[x])
389 x += 1
390
391 for x in env_vars:
392 self.__ebp.write("request %s" % env_translate.get(x,x))
393 line=self.__ebp.read()
394 if line[-1] == "\n":
395 line=line[:-1]
396 new_cache.append("ac_cv_env_%s_set=%s" % (x, line))
397 if line == "unset":
398 new_cache.append("ac_cv_env_%s_value=" % x)
399 else:
400 line=self.__ebp.read()
401 if line[-1] == "\n":
402 line=line[:-1]
403 if line.split()[0] != line:
404 #quoting... XXX
405 new_cache.append("ac_cv_env_%s_value='%s'" % (x,line))
406 else:
407 new_cache.append("ac_cv_env_%s_value=%s" % (x,line))
408
409 myf=open(confcache,"w")
410 for x in new_cache:
411 myf.write(x+"\n")
412 myf.close()
413
414 except SystemExit, e:
415 raise
416 except Exception,e:
417 print "caught exception: %s" % str(e)
418 try: myf.close()
419 except (IOError, OSError): pass
420 valid=False
421
422 if not valid:
423 print "\nconfcache is invalid\n"
424 try: os.remove(confcache_list)
425 except OSError: pass
426 try: os.remove(confcache)
427 except OSError: pass
428 self.__ebp.write("empty")
429 valid=0
430 else:
431 self.__ebp.write("location: %s" % confcache)
432 valid=1
433 if lock:
434 portage_locks.unlockfile(lock)
435 return valid
436
437 def update_confcache(self,settings,logfile,new_confcache, confcache=portage_const.CONFCACHE_FILE, \
438 confcache_list=portage_const.CONFCACHE_LIST):
439 """internal function called when a processor has finished a configure, and wishes its cache
440 be transferred to the global cache
441 This runs through the sandbox log, storing the md5 of files along with the list of files to check.
442 Finally, it transfers the cache to the global location."""
443
444 if not self.__ebp:
445 import traceback
446 traceback.print_stack()
447 print "err... no ebp, yet load_confcache called. invalid"
448 sys.exit(1)
449
450 import re
451 from portage_checksum import perform_md5
452 if not (os.path.exists(logfile) and os.path.exists(new_confcache)) :
453 # eh? wth?
454 self.__ebp.write("failed")
455 return 0
456 myfiles=portage_util.grabfile(logfile)
457 filter=re.compile('^(%s|/tmp|/dev|.*/\.ccache)/' % os.path.normpath(settings["PORTAGE_TMPDIR"]))
458 l=[]
459 for x in myfiles:
460 # get only read syscalls...
461 if x[0:8] == "open_rd:":
462 l.append(x.split()[1])
463
464 myfiles = portage_util.unique_array(l)
465 l=[]
466 for x in myfiles:
467 if not os.path.exists(x):
468 continue
469 if not filter.match(x):
470 l.append(x)
471 del myfiles
472
473 if not len(l):
474 self.__ebp.write("updated")
475 return 0
476
477 lock=portage_locks.lockfile(confcache_list,wantnewlockfile=1)
478 # update phase.
479 if not os.path.exists(confcache_list):
480 prevmask=os.umask(0)
481 myf=anydbm.open(confcache_list,"n",0664)
482 os.umask(prevmask)
483 else:
484 myf=anydbm.open(confcache_list,"w",0664)
485
486 for x in l:
487 try:
488 if not stat.S_ISDIR(os.stat(x).st_mode) and not myf.has_key(x):
489 myf[x]=str(perform_md5(x,calc_prelink=1))
490 except (IOError, OSError):
491 # exceptions are only possibly (ignoring anydbm horkage) from os.stat
492 pass
493 myf.close()
494 from portage_data import portage_gid
495 os.chown(confcache_list, -1, portage_gid)
496 shutil.move(new_confcache, confcache)
497 os.chown(confcache, -1, portage_gid)
498 m=os.umask(0)
499 os.chmod(confcache, 0664)
500 os.chmod(confcache_list, 0664)
501 os.umask(m)
502 portage_locks.unlockfile(lock)
503 self.__ebp.write("updated")
504 return 0
505
506 def get_keys(self,myebuild,mysettings,myroot="/"):
507 """request the auxdbkeys from an ebuild
508 returns a dict when successful, None when failed"""
509 # print "getting keys for %s" % myebuild
510 # normally,
511 # userpriv'd, minus sandbox. which is odd.
512 # I say both, personally (and I'm writing it, so live with it)
513 if self.__ebp:
514 import traceback
515 traceback.print_stack()
516 print "self.__ebp exists. it shouldn't. this indicates a handler w/ an active ebp never"
517 print "released it, or a bug in the calls"
518 sys.exit(1)
519
520
521 self.__ebp = request_ebuild_processor(userpriv=portage_exec.userpriv_capable)
522
523 if self.__adjust_env("depend",mysettings,myebuild,myroot):
524 return {}
525
526 self.__ebp.write("process_ebuild depend")
527 self.__ebp.send_env(mysettings)
528 self.__ebp.set_sandbox_state(True)
529 self.__ebp.write("start_processing")
530 line=self.__generic_phase(["sending_keys"],mysettings,interpret_results=False)
531 if line != "sending_keys":
532 return None
533 mykeys={}
534 while line != "end_keys":
535 line=self.__ebp.read()
536 line=line[:-1]
537 if line == "failed":
538 self.__ebp.unlock()
539 return {}
540 if line == "end_keys" or not len(line):
541 continue
542 pair = line.split('=',1)
543 mykeys[pair[0]]=pair[1]
544 self.__ebp.expect("phases succeeded")
545 if not release_ebuild_processor(self.__ebp):
546 self.__ebp = None
547 raise Exception,"crud"
548 self.__ebp = None
549 return mykeys
550
551 def __adjust_env(self,mydo,mysettings,myebuild,myroot,debug=0,listonly=0,fetchonly=0,cleanup=0,dbkey=None,\
552 use_cache=1,fetchall=0,tree="porttree",use_info_env=True,verbosity=0):
553 """formerly portage.doebuild, since it's specific to ebuilds, it's now a method of ebuild handling.
554 severely gutted, and in need of cleansing/exorcism"""
555 from portage import db,ExtractKernelVersion,fetch,features, \
556 digestgen,digestcheck,root,flatten, digestParseFile
557 from portage_data import portage_uid,portage_gid,secpass
558 import portage_dep
559 from portage_util import writemsg
560
561 ebuild_path = os.path.abspath(myebuild)
562 pkg_dir = os.path.dirname(ebuild_path)
563
564 if mysettings.configdict["pkg"].has_key("CATEGORY"):
565 cat = mysettings.configdict["pkg"]["CATEGORY"]
566 else:
567 cat = os.path.basename(os.path.normpath(pkg_dir+"/.."))
568 mypv = os.path.basename(ebuild_path)[:-7]
569 mycpv = cat+"/"+mypv
570
571 mysplit=portage_versions.pkgsplit(mypv,silent=0)
572 if mysplit==None:
573 writemsg("!!! Error: PF is null '%s'; exiting.\n" % mypv)
574 return 1
575
576 if mydo == "clean":
577 cleanup=True
578
579 if mydo != "depend":
580 # XXX: We're doing a little hack here to curtain the gvisible locking
581 # XXX: that creates a deadlock... Really need to isolate that.
582 mysettings.reset(use_cache=use_cache)
583
584 mysettings.setcpv(mycpv,use_cache=use_cache)
585
586 if not os.path.exists(myebuild):
587 writemsg("!!! doebuild: "+str(myebuild)+" not found for "+str(mydo)+"\n")
588 return 1
589
590 if debug: # Otherwise it overrides emerge's settings.
591 # We have no other way to set debug... debug can't be passed in
592 # due to how it's coded... Don't overwrite this so we can use it.
593 mysettings["PORTAGE_DEBUG"]=str(debug)
594
595 mysettings["ROOT"] = myroot
596
597 mysettings["EBUILD"] = ebuild_path
598 mysettings["O"] = pkg_dir
599 mysettings["CATEGORY"] = cat
600 mysettings["FILESDIR"] = pkg_dir+"/files"
601 mysettings["PF"] = mypv
602
603 mysettings["ECLASSDIR"] = mysettings["PORTDIR"]+"/eclass"
604
605 mysettings["PROFILE_PATHS"] = PROFILE_PATH+"\n"+CUSTOM_PROFILE_PATH
606 mysettings["P"] = mysplit[0]+"-"+mysplit[1]
607 mysettings["PN"] = mysplit[0]
608 mysettings["PV"] = mysplit[1]
609 mysettings["PR"] = mysplit[2]
610
611 # ensure this is set for all phases, setup included.
612 # Should be ok again to set $T, as sandbox does not depend on it
613 mysettings["BUILD_PREFIX"] = mysettings["PORTAGE_TMPDIR"]+"/portage"
614 mysettings["PORTAGE_BUILDDIR"] = mysettings["BUILD_PREFIX"]+"/"+mysettings["PF"]
615 mysettings["T"] = mysettings["PORTAGE_BUILDDIR"]+"/temp"
616 mysettings["WORKDIR"] = mysettings["PORTAGE_BUILDDIR"]+"/work"
617 mysettings["D"] = mysettings["PORTAGE_BUILDDIR"]+"/image/"
618
619
620 # bailing now, probably horks a few things up, but neh.
621 # got to break a few eggs to make an omelot after all (spelling is wrong, too) :)
622 if mydo=="unmerge":
623 return 0
624
625 if mydo!="depend":
626 try:
627 mysettings["INHERITED"],mysettings["RESTRICT"] = db[root][tree].dbapi.aux_get(
628 mycpv,["INHERITED","RESTRICT"])
629
630 mysettings["PORTAGE_RESTRICT"]=string.join(flatten(portage_dep.use_reduce(
631 portage_dep.paren_reduce(mysettings["RESTRICT"]),
632 uselist=mysettings["USE"].split() )),' ')
633
634 except SystemExit, e:
635 raise
636 except Exception, e:
637 print "caught exception %s in ebd_proc:doebuild" % str(e)
638 mysettings["RESTRICT"] = mysettings["PORTAGE_RESTRICT"] = ""
639 pass
640
641
642 if mysplit[2] == "r0":
643 mysettings["PVR"]=mysplit[1]
644 else:
645 mysettings["PVR"]=mysplit[1]+"-"+mysplit[2]
646
647 mysettings["SLOT"]=""
648
649 if mysettings.has_key("PATH"):
650 mysplit=string.split(mysettings["PATH"],":")
651 else:
652 mysplit=[]
653
654 if PORTAGE_BIN_PATH not in mysplit:
655 mysettings["PATH"]=PORTAGE_BIN_PATH+":"+mysettings["PATH"]
656
657 if tree=="bintree":
658 mysettings["BUILD_PREFIX"] += "-pkg"
659
660 mysettings["HOME"] = mysettings["BUILD_PREFIX"]+"/homedir"
661 mysettings["PKG_TMPDIR"] = mysettings["PORTAGE_TMPDIR"]+"/binpkgs"
662
663 if cleanup and os.path.exists(mysettings["PORTAGE_BUILDDIR"]):
664 print "cleansing builddir"+mysettings["PORTAGE_BUILDDIR"]
665 shutil.rmtree(mysettings["PORTAGE_BUILDDIR"])
666
667 if mydo=="clean":
668 # if clean, just flat out skip the rest of this crap.
669 return 0
670
671 mysettings["PORTAGE_BASHRC"] = EBUILD_SH_ENV_FILE
672
673 #set up KV variable -- DEP SPEEDUP :: Don't waste time. Keep var persistent.
674
675 if mydo not in ["depend","fetch","digest","manifest"]:
676 if not mysettings.has_key("KV"):
677 mykv,err1=ExtractKernelVersion(root+"usr/src/linux")
678 if mykv:
679 # Regular source tree
680 mysettings["KV"]=mykv
681 else:
682 mysettings["KV"]=""
683
684 if (mydo!="depend") or not mysettings.has_key("KVERS"):
685 myso=os.uname()[2]
686 mysettings["KVERS"]=myso[1]
687
688
689 # get possible slot information from the deps file
690 if mydo=="depend":
691 if mysettings.has_key("PORTAGE_DEBUG") and mysettings["PORTAGE_DEBUG"]=="1":
692 # XXX: This needs to use a FD for saving the output into a file.
693 # XXX: Set this up through spawn
694 pass
695 writemsg("!!! DEBUG: dbkey: %s\n" % str(dbkey),2)
696 if dbkey:
697 mysettings["dbkey"] = dbkey
698 else:
699 mysettings["dbkey"] = mysettings.depcachedir+"/aux_db_key_temp"
700
701 return 0
702
703 mysettings["PORTAGE_LOGFILE"]=''
704 logfile=None
705
706
707 #fetch/digest crap
708 if mydo not in ["prerm","postrm","preinst","postinst","config","help","setup","unmerge"]:
709
710 newuris, alist = db["/"]["porttree"].dbapi.getfetchlist(mycpv,mysettings=mysettings)
711 alluris, aalist = db["/"]["porttree"].dbapi.getfetchlist(mycpv,mysettings=mysettings,all=1)
712 mysettings["A"]=string.join(alist," ")
713 mysettings["AA"]=string.join(aalist," ")
714 if ("mirror" in features) or fetchall:
715 fetchme=alluris[:]
716 checkme=aalist[:]
717 elif mydo=="digest":
718 fetchme=alluris[:]
719 checkme=aalist[:]
720 digestfn=mysettings["FILESDIR"]+"/digest-"+mysettings["PF"]
721 if os.path.exists(digestfn):
722 mydigests=digestParseFile(digestfn)
723 if mydigests:
724 for x in mydigests:
725 while x in checkme:
726 i = checkme.index(x)
727 del fetchme[i]
728 del checkme[i]
729 else:
730 fetchme=newuris[:]
731 checkme=alist[:]
732
733 try:
734 if not os.path.exists(mysettings["DISTDIR"]):
735 os.makedirs(mysettings["DISTDIR"])
736 if not os.path.exists(mysettings["DISTDIR"]+"/cvs-src"):
737 os.makedirs(mysettings["DISTDIR"]+"/cvs-src")
738 except OSError, e:
739 print "!!! File system problem. (Bad Symlink?)"
740 print "!!! Fetching may fail:",str(e)
741
742 try:
743 mystat=os.stat(mysettings["DISTDIR"]+"/cvs-src")
744 if ((mystat[stat.ST_GID]!=portage_gid) or ((mystat[stat.ST_MODE]&00775)!=00775)) and not listonly:
745 print "*** Adjusting cvs-src permissions for portage user..."
746 os.chown(mysettings["DISTDIR"]+"/cvs-src",0,portage_gid)
747 os.chmod(mysettings["DISTDIR"]+"/cvs-src",00775)
748 portage_exec.spawn("chgrp -R "+str(portage_gid)+" "+mysettings["DISTDIR"]+"/cvs-src")
749 portage_exec.spawn("chmod -R g+rw "+mysettings["DISTDIR"]+"/cvs-src")
750 except (IOError, OSError):
751 pass
752
753 if not fetch(fetchme, mysettings, listonly=listonly, fetchonly=fetchonly,verbosity=verbosity):
754 return 1
755
756 if mydo=="fetch" and listonly:
757 return 0
758
759 if "digest" in features:
760 #generate digest if it doesn't exist.
761 if mydo=="digest":
762 # exemption to the return rule
763 return (not digestgen(aalist,mysettings,overwrite=1,verbosity=verbosity))
764 else:
765 digestgen(aalist,mysettings,overwrite=0,verbosity=verbosity)
766
767 elif mydo=="digest":
768 #since we are calling "digest" directly, recreate the digest even if it already exists
769 return (not digestgen(aalist,mysettings,overwrite=1,verbosity=verbosity))
770 if mydo=="manifest":
771 return (not digestgen(aalist,mysettings,overwrite=1,manifestonly=1,verbosity=verbosity))
772
773 if mydo=="fetch" or mydo=="unpack":
774 if not digestcheck(checkme, mysettings, ("strict" in features),verbosity=verbosity):
775 return 1
776
777 if mydo=="fetch":
778 return 0
779
780 if not os.path.exists(mysettings["BUILD_PREFIX"]):
781 os.makedirs(mysettings["BUILD_PREFIX"])
782 os.chown(mysettings["BUILD_PREFIX"],portage_uid,portage_gid)
783 os.chmod(mysettings["BUILD_PREFIX"],00775)
784
785 if not os.path.exists(mysettings["T"]):
786 print "creating temp dir"
787 os.makedirs(mysettings["T"])
788 os.chown(mysettings["T"],portage_uid,portage_gid)
789 os.chmod(mysettings["T"],0770)
790
791 logdir = mysettings["T"]+"/logging"
792 if not os.path.exists(logdir):
793 os.makedirs(logdir)
794 os.chown(logdir, portage_uid, portage_gid)
795 os.chmod(logdir, 0770)
796
797 try:
798 #XXX: negative restrict
799 myrestrict = mysettings["PORTAGE_RESTRICT"].split()
800 if ("nouserpriv" not in myrestrict and "userpriv" not in myrestrict):
801 if ("userpriv" in mysettings.features) and (portage_uid and portage_gid):
802 if (secpass==2):
803 if os.path.exists(mysettings["HOME"]):
804 # XXX: Potentially bad, but held down by HOME replacement above.
805 portage_exec.spawn("rm -Rf "+mysettings["HOME"])
806 if not os.path.exists(mysettings["HOME"]):
807 os.makedirs(mysettings["HOME"])
808 elif ("userpriv" in features):
809 print "!!! Disabling userpriv from features... Portage UID/GID not valid."
810 del features[features.index("userpriv")]
811 except (IOError, OSError), e:
812 print "!!! Couldn't empty HOME:",mysettings["HOME"]
813 print "!!!",e
814
815
816 try:
817 # no reason to check for depend since depend returns above.
818 if not os.path.exists(mysettings["BUILD_PREFIX"]):
819 os.makedirs(mysettings["BUILD_PREFIX"])
820 os.chown(mysettings["BUILD_PREFIX"],portage_uid,portage_gid)
821 if not os.path.exists(mysettings["PORTAGE_BUILDDIR"]):
822 os.makedirs(mysettings["PORTAGE_BUILDDIR"])
823 os.chown(mysettings["PORTAGE_BUILDDIR"],portage_uid,portage_gid)
824
825
826 except OSError, e:
827 print "!!! File system problem. (ReadOnly? Out of space?)"
828 print "!!! Perhaps: rm -Rf",mysettings["BUILD_PREFIX"]
829 print "!!!",str(e)
830 return 1
831
832 try:
833 if not os.path.exists(mysettings["HOME"]):
834 os.makedirs(mysettings["HOME"])
835 os.chown(mysettings["HOME"],portage_uid,portage_gid)
836 os.chmod(mysettings["HOME"],02770)
837
838 except OSError, e:
839 print "!!! File system problem. (ReadOnly? Out of space?)"
840 print "!!! Failed to create fake home directory in PORTAGE_BUILDDIR"
841 print "!!!",str(e)
842 return 1
843
844 try:
845 if ("userpriv" in features) and ("ccache" in features):
846 if (not mysettings.has_key("CCACHE_DIR")) or (mysettings["CCACHE_DIR"]==""):
847 mysettings["CCACHE_DIR"]=mysettings["PORTAGE_TMPDIR"]+"/ccache"
848 if not os.path.exists(mysettings["CCACHE_DIR"]):
849 os.makedirs(mysettings["CCACHE_DIR"])
850 os.chown(mysettings["CCACHE_DIR"],portage_uid,portage_gid)
851 os.chmod(mysettings["CCACHE_DIR"],0775)
852 except OSError, e:
853 print "!!! File system problem. (ReadOnly? Out of space?)"
854 print "!!! Perhaps: rm -Rf",mysettings["BUILD_PREFIX"]
855 print "!!!",str(e)
856 return 1
857
858 try:
859 mystat=os.stat(mysettings["CCACHE_DIR"])
860 if (mystat[stat.ST_GID]!=portage_gid) or ((mystat[stat.ST_MODE]&02070)!=02070):
861 print "*** Adjusting ccache permissions for portage user..."
862 os.chown(mysettings["CCACHE_DIR"],portage_uid,portage_gid)
863 os.chmod(mysettings["CCACHE_DIR"],02770)
864 portage_exec.spawn("chown -R "+str(portage_uid)+":"+str(portage_gid)+" "+mysettings["CCACHE_DIR"])
865 portage_exec.spawn("chmod -R g+rw "+mysettings["CCACHE_DIR"])
866 except (OSError, IOError):
867 pass
868
869 if "distcc" in features:
870 try:
871 if (not mysettings.has_key("DISTCC_DIR")) or (mysettings["DISTCC_DIR"]==""):
872 mysettings["DISTCC_DIR"]=mysettings["PORTAGE_TMPDIR"]+"/portage/.distcc"
873 if not os.path.exists(mysettings["DISTCC_DIR"]):
874 os.makedirs(mysettings["DISTCC_DIR"])
875 os.chown(mysettings["DISTCC_DIR"],portage_uid,portage_gid)
876 os.chmod(mysettings["DISTCC_DIR"],02775)
877 for x in ("/lock", "/state"):
878 if not os.path.exists(mysettings["DISTCC_DIR"]+x):
879 os.mkdir(mysettings["DISTCC_DIR"]+x)
880 os.chown(mysettings["DISTCC_DIR"]+x,portage_uid,portage_gid)
881 os.chmod(mysettings["DISTCC_DIR"]+x,02775)
882 except OSError, e:
883 writemsg("\n!!! File system problem when setting DISTCC_DIR directory permissions.\n")
884 writemsg( "!!! DISTCC_DIR="+str(mysettings["DISTCC_DIR"]+"\n"))
885 writemsg( "!!! "+str(e)+"\n\n")
886 time.sleep(5)
887 features.remove("distcc")
888 mysettings["DISTCC_DIR"]=""
889
890 # break off into process_phase
891 if mysettings.has_key("PORT_LOGDIR"):
892 try:
893 st=os.stat(mysettings["PORT_LOGDIR"])
894 if not st.st_gid == portage_gid:
895 os.chown(mysettings["PORT_LOGDIR"], -1, portage_gid)
896 if not st.st_mode & (os.W_OK << 3):
897 os.chmod(mysettings["PORT_LOGDIR"], st.st_mode | (os.W_OK << 3))
898 # by this time, we have write access to the logdir. or it's bailed.
899 try:
900 os.chown(mysettings["BUILD_PREFIX"],portage_uid,portage_gid)
901 os.chmod(mysettings["PORT_LOGDIR"],00770)
902 if not mysettings.has_key("LOG_PF") or (mysettings["LOG_PF"] != mysettings["PF"]):
903 mysettings["LOG_PF"]=mysettings["PF"]
904 mysettings["LOG_COUNTER"]=str(db[myroot]["vartree"].dbapi.get_counter_tick_core("/"))
905 mysettings["PORTAGE_LOGFILE"]="%s/%s-%s.log" % (mysettings["PORT_LOGDIR"],mysettings["LOG_COUNTER"],mysettings["LOG_PF"])
906 if os.path.exists(mysettings["PORTAGE_LOGFILE"]):
907 os.chmod(mysettings["PORTAGE_LOGFILE"], 0664)
908 os.chown(mysettings["PORTAGE_LOGFILE"], -1,portage_gid)
909 except ValueError, e:
910 mysettings["PORT_LOGDIR"]=""
911 print "!!! Unable to chown/chmod PORT_LOGDIR. Disabling logging."
912 print "!!!",e
913 except (OSError, IOError):
914 print "!!! Cannot create log... No write access / Does not exist"
915 print "!!! PORT_LOGDIR:",mysettings["PORT_LOGDIR"]
916 mysettings["PORT_LOGDIR"]=""
917
918 # if any of these are being called, handle them -- running them out of the sandbox -- and stop now.
919 if mydo in ["help","setup"]:
920 return 0
921 # return spawn(EBUILD_SH_BINARY+" "+mydo,mysettings,debug=debug,free=1,logfile=logfile)
922 elif mydo in ["prerm","postrm","preinst","postinst","config"]:
923 mysettings.load_infodir(pkg_dir)
924 if not use_info_env:
925 print "overloading port_env_file setting to %s" % mysettings["T"]+"/environment"
926 mysettings["PORT_ENV_FILE"] = mysettings["T"] + "/environment"
927 if not os.path.exists(mysettings["PORT_ENV_FILE"]):
928 from output import red
929 print red("!!!")+" err.. it doesn't exist. that's bad."
930 sys.exit(1)
931 return 0
932 # return spawn(EBUILD_SH_BINARY+" "+mydo,mysettings,debug=debug,free=1,logfile=logfile)
933
934 try:
935 mysettings["SLOT"], mysettings["RESTRICT"] = db["/"]["porttree"].dbapi.aux_get(mycpv,["SLOT","RESTRICT"])
936 except (IOError,KeyError):
937 print red("doebuild():")+" aux_get() error reading "+mycpv+"; aborting."
938 sys.exit(1)
939
940 #initial dep checks complete; time to process main commands
941
942 nosandbox=(("userpriv" in features) and ("usersandbox" not in features))
943 actionmap={
944 "depend": { "args":(0,1)}, # sandbox / portage
945 "setup": { "args":(1,0)}, # without / root
946 "unpack": {"dep":"setup", "args":(0,1)}, # sandbox / portage
947 "compile": {"dep":"unpack", "args":(nosandbox,1)}, # optional / portage
948 "test": {"dep":"compile", "args":(nosandbox,1)}, # optional / portage
949 "install": {"dep":"test", "args":(0,0)}, # sandbox / root
950 "rpm": {"dep":"install", "args":(0,0)}, # sandbox / root
951 "package": {"dep":"install", "args":(0,0)}, # sandbox / root
952 }
953
954 if mydo in actionmap.keys():
955 if mydo=="package":
956 for x in ["","/"+mysettings["CATEGORY"],"/All"]:
957 if not os.path.exists(mysettings["PKGDIR"]+x):
958 os.makedirs(mysettings["PKGDIR"]+x)
959 # REBUILD CODE FOR TBZ2 --- XXXX
960 return 0
961 # return spawnebuild(mydo,actionmap,mysettings,debug,logfile=logfile)
962 elif mydo=="qmerge":
963 #check to ensure install was run. this *only* pops up when users forget it and are using ebuild
964 bail=False
965 if not os.path.exists(mysettings["PORTAGE_BUILDDIR"]+"/.completed_stages"):
966 bail=True
967 else:
968 myf=open(mysettings["PORTAGE_BUILDDIR"]+"/.completed_stages")
969 myd=myf.readlines()
970 myf.close()
971 if len(myd) == 0:
972 bail = True
973 else:
974 bail = ("install" not in myd[0].split())
975 if bail:
976 print "!!! mydo=qmerge, but install phase hasn't been ran"
977 sys.exit(1)
978
979 #qmerge is specifically not supposed to do a runtime dep check
980 return 0
981 # return merge(mysettings["CATEGORY"],mysettings["PF"],mysettings["D"],mysettings["PORTAGE_BUILDDIR"]+"/build-info",myroot,mysettings)
982 elif mydo=="merge":
983 return 0
984 # retval=spawnebuild("install",actionmap,mysettings,debug,alwaysdep=1,logfile=logfile)
985 if retval:
986 return retval
987
988 # return merge(mysettings["CATEGORY"],mysettings["PF"],mysettings["D"],mysettings["PORTAGE_BUILDDIR"]+"/build-info",myroot,mysettings,myebuild=mysettings["EBUILD"])
989 else:
990 print "!!! Unknown mydo:",mydo
991 sys.exit(1)
992
993 # phases
994 # my... god... this... is... ugly.
995 # we're talking red headed step child of medusa ugly here.
996
997 def process_phase(self,phase,mysettings,myebuild,myroot,allstages=False,**keywords):
998 """the public 'doebuild' interface- all phases are called here, along w/ a valid config
999 allstages is the equivalent of 'do merge, and all needed phases to get to it'
1000 **keywords is options passed on to __adjust_env. It will be removed as __adjust_env is digested"""
1001 from portage import merge,unmerge,features
1002
1003 validcommands = ["help","clean","prerm","postrm","preinst","postinst",
1004 "config","setup","depend","fetch","digest",
1005 "unpack","compile","test","install","rpm","qmerge","merge",
1006 "package","unmerge", "manifest"]
1007
1008 if phase not in validcommands:
1009 validcommands.sort()
1010 writemsg("!!! doebuild: '%s' is not one of the following valid commands:" % phase)
1011 for vcount in range(len(validcommands)):
1012 if vcount%6 == 0:
1013 writemsg("\n!!! ")
1014 writemsg(string.ljust(validcommands[vcount], 11))
1015 writemsg("\n")
1016 return 1
1017
1018 retval=self.__adjust_env(phase,mysettings,myebuild,myroot,**keywords)
1019 if retval:
1020 return retval
1021
1022 if "userpriv" in features:
1023 sandbox = ("usersandbox" in features)
1024 else:
1025 sandbox = ("sandbox" in features)
1026
1027 droppriv=(("userpriv" in features) and \
1028 ("nouserpriv" not in string.split(mysettings["PORTAGE_RESTRICT"])) and portage_exec.userpriv_capable)
1029 use_fakeroot=(("userpriv_fakeroot" in features) and droppriv and portage_exec.fakeroot_capable)
1030
1031 # basically a nasty graph of 'w/ this phase, have it userprived/sandboxed/fakeroot', and run
1032 # these phases prior
1033 actionmap={
1034 "depend": { "sandbox":False, "userpriv":True, "fakeroot":False},
1035 "setup": { "sandbox":True, "userpriv":False, "fakeroot":False},
1036 "unpack": {"dep":"setup", "sandbox":sandbox, "userpriv":True, "fakeroot":False},
1037 "compile": {"dep":"unpack", "sandbox":sandbox,"userpriv":True, "fakeroot":False},
1038 "test": {"dep":"compile","sandbox":sandbox,"userpriv":True, "fakeroot":False},
1039 "install": {"dep":"test", "sandbox":(not use_fakeroot or (not use_fakeroot and sandbox)),
1040 "userpriv":use_fakeroot,"fakeroot":use_fakeroot},
1041 "rpm": {"dep":"install","sandbox":False, "userpriv":use_fakeroot, "fakeroot":use_fakeroot},
1042 "package": {"dep":"install", "sandbox":False, "userpriv":use_fakeroot, "fakeroot":use_fakeroot},
1043 "merge" : {"dep":"install", "sandbox":True, "userpriv":False, "fakeroot":False}
1044 }
1045
1046 merging=False
1047 # this shouldn't technically ever be called, get_keys exists for this.
1048 # left in for compatability while portage.doebuild still exists
1049 if phase=="depend":
1050 return retval
1051 elif phase=="unmerge":
1052 return unmerge(mysettings["CATEGORY"],mysettings["PF"],myroot,mysettings)
1053 elif phase in ["fetch","digest","manifest","clean"]:
1054 return retval
1055 elif phase=="merge":
1056 merging=True
1057 elif phase=="qmerge":
1058 #no phases ran.
1059 phase="merge"
1060 merging=True
1061 # return merge(mysettings["CATEGORY"],mysettings["PF"],mysettings["D"],mysettings["PORTAGE_BUILDDIR"]+"/build-info",myroot,\
1062 # mysettings)
1063
1064 elif phase in ["help","clean","prerm","postrm","preinst","postinst","config"]:
1065 self.__ebp = request_ebuild_processor(userpriv=False)
1066 self.__ebp.write("process_ebuild %s" % phase)
1067 self.__ebp.send_env(mysettings)
1068 self.__ebp.set_sandbox_state(phase in ["help","clean"])
1069 self.__ebp.write("start_processing")
1070 retval = self.__generic_phase([],mysettings)
1071 release_ebuild_processor(self.__ebp)
1072 self.__ebp = None
1073 return not retval
1074
1075 k=phase
1076 # represent the phases to run, grouping each phase based upon if it's sandboxed, fakerooted, and userpriv'd
1077 # ugly at a glance, but remember a processor can run multiple phases now.
1078 # best to not be wasteful in terms of env saving/restoring, and just run all applicable phases in one shot
1079 phases=[[[phase]]]
1080 sandboxed=[[actionmap[phase]["sandbox"]]]
1081 privs=[(actionmap[phase]["userpriv"],actionmap[phase]["fakeroot"])]
1082
1083 if allstages:
1084 while actionmap[k].has_key("dep"):
1085 k=actionmap[k]["dep"]
1086 if actionmap[k]["userpriv"] != privs[-1][0] or actionmap[k]["fakeroot"] != privs[-1][1]:
1087 phases.append([[k]])
1088 sandboxed.append([actionmap[k]["sandbox"]])
1089 privs.append((actionmap[k]["userpriv"],actionmap[k]["fakeroot"]))
1090 elif actionmap[k]["sandbox"] != sandboxed[-1][-1]:
1091 phases[-1].append([k])
1092 sandboxed[-1].extend([actionmap[k]["sandbox"]])
1093 else:
1094 phases[-1][-1].append(k)
1095 privs.reverse()
1096 phases.reverse()
1097 sandboxed.reverse()
1098 for x in phases:
1099 for y in x:
1100 y.reverse()
1101 x.reverse()
1102 # and now we have our phases grouped in parallel to the sandbox/userpriv/fakeroot state.
1103
1104 all_phases = portage_util.flatten(phases)
1105
1106 # print "all_phases=",all_phases
1107 # print "phases=",phases
1108 # print "sandbox=",sandboxed
1109 # print "privs=",privs
1110 # sys.exit(1)
1111 # print "\n\ndroppriv=",droppriv,"use_fakeroot=",use_fakeroot,"\n\n"
1112
1113 #temporary hack until sandbox + fakeroot (if ever) play nice.
1114 while privs:
1115 if self.__ebp == None or (droppriv and self.__ebp.userprived() != privs[0][0]) or \
1116 (use_fakeroot and self.__ebp.fakerooted() != privs[0][1]):
1117 if self.__ebp != None:
1118 print "swapping processors for",phases[0][0]
1119 release_ebuild_processor(self.__ebp)
1120 self.__ebp = None
1121 opts={}
1122
1123 #only engage fakeroot when userpriv'd
1124 if use_fakeroot and privs[0][1]:
1125 opts["save_file"] = mysettings["T"]+"/fakeroot_db"
1126
1127 self.__ebp = request_ebuild_processor(userpriv=(privs[0][0] and droppriv), \
1128 fakeroot=(privs[0][1] and use_fakeroot), \
1129
1130 sandbox=(not (privs[0][1] and use_fakeroot) and portage_exec.sandbox_capable),**opts)
1131
1132 #loop through the instances where the processor must have the same sandboxed state-
1133 #note a sandbox'd process can have it's sandbox disabled.
1134 #this seperation is needed since you can't mix sandbox and fakeroot atm.
1135 for sandbox in sandboxed[0]:
1136 if "merge" in phases[0][0]:
1137 if len(phases[0][0]) == 1:
1138 print "skipping this phase, it's just merge"
1139 continue
1140 phases[0][0].remove("merge")
1141
1142 self.__ebp.write("process_ebuild %s" % string.join(phases[0][0]," "))
1143 self.__ebp.send_env(mysettings)
1144 self.__ebp.set_sandbox_state(sandbox)
1145 self.__ebp.write("start_processing")
1146 phases[0].pop(0)
1147 retval = not self.__generic_phase([],mysettings)
1148 if retval:
1149 release_ebuild_processor(self.__ebp)
1150 self.__ebp = None
1151 return retval
1152 sandboxed.pop(0)
1153 privs.pop(0)
1154 phases.pop(0)
1155 # hey hey. we're done. Now give it back.
1156 release_ebuild_processor(self.__ebp)
1157 self.__ebp = None
1158
1159 # packaging moved out of ebuild.sh, and into this code.
1160 # makes it so ebuild.sh no longer must run as root for the package phase.
1161 if "package" in all_phases:
1162 print "processing package"
1163 #mv "${PF}.tbz2" "${PKGDIR}/All"
1164 if not os.path.exists(mysettings["PKGDIR"]+"/All"):
1165 os.makedirs(mysettings["PKGDIR"]+"/All")
1166 if not os.path.exists(mysettings["PKGDIR"]+"/"+mysettings["CATEGORY"]):
1167 os.makedirs(mysettings["PKGDIR"]+"/"+mysettings["CATEGORY"])
1168 if os.path.exists("%s/All/%s.tbz2" % (mysettings["PKGDIR"],mysettings["PF"])):
1169 os.remove("%s/All/%s.tbz2" % (mysettings["PKGDIR"],mysettings["PF"]))
1170 retval = not portage_util.movefile("%s/%s.tbz2" % (mysettings["PORTAGE_BUILDDIR"],mysettings["PF"]),
1171 mysettings["PKGDIR"]+"/All/"+mysettings["PF"]+".tbz2") > 0
1172 if retval: return False
1173 if os.path.exists("%s/%s/%s.tbz2" % (mysettings["PKGDIR"],mysettings["CATEGORY"],mysettings["PF"])):
1174 os.remove("%s/%s/%s.tbz2" % (mysettings["PKGDIR"],mysettings["CATEGORY"],mysettings["PF"]))
1175 os.symlink("%s/All/%s.tbz2" % (mysettings["PKGDIR"],mysettings["PF"]),
1176 "%s/%s/%s.tbz2" % (mysettings["PKGDIR"],mysettings["CATEGORY"],mysettings["PF"]))
1177
1178 #same as the package phase above, removes the root requirement for the rpm phase.
1179 if "rpm" in all_phases:
1180 rpm_name="%s-%s-%s" % (mysettings["PN"],mysettings["PV"],mysettings["PR"])
1181
1182 retval = not portage_util.movefile("%s/%s.tar.gz" % (mysettings["T"],mysettings["PF"]),
1183 "/usr/src/redhat/SOURCES/%s.tar.gz" % mysettings["PF"]) > 0
1184 if retval:
1185 print "moving src for rpm failed, retval=",retval
1186 return False
1187
1188 retval=portage_exec.spawn(("rpmbuild","-bb","%s/%s.spec" % \
1189 (mysettings["PORTAGE_BUILDDIR"],mysettings["PF"])))
1190 if retval:
1191 print "Failed to integrate rpm spec file"
1192 return retval
1193
1194 if not os.path.exists(mysettings["RPMDIR"]+"/"+mysettings["CATEGORY"]):
1195 os.makedirs(mysettings["RPMDIR"]+"/"+mysettings["CATEGORY"])
1196
1197 retval = not portage_util.movefile("/usr/src/redhat/RPMS/i386/%s.i386.rpm" % rpm_name,
1198 "%s/%s/%s.rpm" % (mysettings["RPMDIR"],mysettings["CATEGORY"],rpm_name)) > 0
1199 if retval:
1200 print "rpm failed"
1201 return retval
1202
1203
1204 # not great check, but it works.
1205 # basically, if FEATURES="-buildpkg" emerge package was called, the files in the current
1206 # image directory don't have their actual perms. so we use an ugly bit of bash
1207 # to make the fakeroot (claimed) permissions/owners a reality.
1208 if use_fakeroot and os.path.exists(mysettings["T"]+"/fakeroot_db") and merging:
1209 print "correcting fakeroot privs"
1210 retval=portage_exec.spawn(("/usr/lib/portage/bin/affect-fakeroot-perms.sh", \
1211 mysettings["T"]+"/fakeroot_db", \
1212 mysettings["D"]),env={"BASHRC":portage_const.INVALID_ENV_FILE})
1213 if retval or retval == None:
1214 print red("!!!")+"affecting fakeroot perms after the fact failed"
1215 return retval
1216
1217 if merging:
1218 print "processing merge"
1219 retval = merge(mysettings["CATEGORY"],mysettings["PF"],mysettings["D"],mysettings["PORTAGE_BUILDDIR"]+"/build-info",myroot,\
1220 mysettings,myebuild=mysettings["EBUILD"])
1221 return retval
1222
1223 # this basically handles all hijacks from the daemon, whether confcache or portageq.
1224 def __generic_phase(self,breakers,mysettings,interpret_results=True):
1225 """internal function that responds to the running ebuild processor's requests
1226 this enables portageq hijack, sandbox summaries, confcache among other things
1227 interpret_results controls whether this returns true/false, or the string the
1228 processor spoke that caused this to release control
1229 breaks is list of strings that cause this loop/interpretter to relinquish control"""
1230 b = breakers[:]
1231 b.extend(["prob","phases failed","phases succeeded","env_receiving_failed"])
1232 line=''
1233 while line not in b:
1234 line=self.__ebp.read()
1235 line=line[:-1]
1236
1237 if line[0:23] == "request_sandbox_summary":
1238 self.__ebp.sandbox_summary(line[24:])
1239 elif line[0:17] == "request_confcache":
1240 self.load_confcache(line[18:])
1241 elif line[0:16] == "update_confcache":
1242 k=line[17:].split()
1243 # sandbox_debug_log, local_cache
1244 self.update_confcache(mysettings,k[0],k[1])
1245 elif line[0:8] == "portageq":
1246 keys=line[8:].split()
1247 try:
1248 e,s=getattr(self.portageq,keys[0])(keys[1:])
1249 except SystemExit, e:
1250 raise
1251 except Exception, ex:
1252 sys.stderr.write("caught exception %s\n" % str(ex))
1253 e=2
1254 s="ERROR: insufficient paramters!"
1255 self.__ebp.write("return_code="+str(e))
1256 if len(s):
1257 self.__ebp.write(s)
1258 self.__ebp.write("stop_text")
1259 self.processed += 1
1260 if interpret_results:
1261 return (line=="phases succeeded")
1262 return line

  ViewVC Help
Powered by ViewVC 1.1.20