Gentoo Archives: gentoo-commits

From: Brian Dolbec <dolsen@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/catalyst:master commit in: catalyst/
Date: Thu, 26 Feb 2015 04:12:07
Message-Id: 1420091885.0b3a26d733ea8e8b3fce044be1d2c872138d74d5.dolsen@gentoo
1 commit: 0b3a26d733ea8e8b3fce044be1d2c872138d74d5
2 Author: Brian Dolbec <dolsen <AT> gentoo <DOT> org>
3 AuthorDate: Sun Jan 20 19:22:27 2013 +0000
4 Commit: Brian Dolbec <dolsen <AT> gentoo <DOT> org>
5 CommitDate: Thu Jan 1 05:58:05 2015 +0000
6 URL: http://sources.gentoo.org/gitweb/?p=proj/catalyst.git;a=commit;h=0b3a26d7
7
8 Some spacing, comment and indent cleanup
9
10 ---
11 catalyst/support.py | 405 +++++++++++++++++++++++++++-------------------------
12 1 file changed, 213 insertions(+), 192 deletions(-)
13
14 diff --git a/catalyst/support.py b/catalyst/support.py
15 index feaa645..e2d64a1 100644
16 --- a/catalyst/support.py
17 +++ b/catalyst/support.py
18 @@ -1,12 +1,19 @@
19
20 -import sys,string,os,types,re,signal,traceback,time
21 -#import md5,sha
22 +import sys
23 +import string
24 +import os
25 +import types
26 +import re
27 +import signal
28 +import traceback
29 +import time
30
31 from catalyst.defaults import verbosity, valid_config_file_values
32
33 selinux_capable = False
34 #userpriv_capable = (os.getuid() == 0)
35 #fakeroot_capable = False
36 +
37 BASH_BINARY = "/bin/bash"
38
39 # set it to 0 for the soft limit, 1 for the hard limit
40 @@ -25,35 +32,35 @@ spawned_pids = []
41
42
43 def cleanup(pids,block_exceptions=True):
44 - """function to go through and reap the list of pids passed to it"""
45 - global spawned_pids
46 - if type(pids) == int:
47 - pids = [pids]
48 - for x in pids:
49 - try:
50 - os.kill(x,signal.SIGTERM)
51 - if os.waitpid(x,os.WNOHANG)[1] == 0:
52 - # feisty bugger, still alive.
53 - os.kill(x,signal.SIGKILL)
54 - os.waitpid(x,0)
55 -
56 - except OSError, oe:
57 - if block_exceptions:
58 - pass
59 - if oe.errno not in (10,3):
60 - raise oe
61 - except SystemExit:
62 - raise
63 - except Exception:
64 - if block_exceptions:
65 - pass
66 - try: spawned_pids.remove(x)
67 - except IndexError: pass
68 -
69 -
70 -
71 -# a function to turn a string of non-printable characters into a string of
72 -# hex characters
73 + """function to go through and reap the list of pids passed to it"""
74 + global spawned_pids
75 + if type(pids) == int:
76 + pids = [pids]
77 + for x in pids:
78 + try:
79 + os.kill(x,signal.SIGTERM)
80 + if os.waitpid(x,os.WNOHANG)[1] == 0:
81 + # feisty bugger, still alive.
82 + os.kill(x,signal.SIGKILL)
83 + os.waitpid(x,0)
84 + except OSError, oe:
85 + if block_exceptions:
86 + pass
87 + if oe.errno not in (10,3):
88 + raise oe
89 + except SystemExit:
90 + raise
91 + except Exception:
92 + if block_exceptions:
93 + pass
94 + try:
95 + spawned_pids.remove(x)
96 + except IndexError:
97 + pass
98 +
99 +
100 +# a function to turn a string of non-printable characters
101 +# into a string of hex characters
102 def hexify(str):
103 hexStr = string.hexdigits
104 r = ''
105 @@ -61,7 +68,6 @@ def hexify(str):
106 i = ord(ch)
107 r = r + hexStr[(i >> 4) & 0xF] + hexStr[i & 0xF]
108 return r
109 -# hexify()
110
111
112 def read_from_clst(file):
113 @@ -77,7 +83,6 @@ def read_from_clst(file):
114 myline = myline + line
115 myf.close()
116 return myline
117 -# read_from_clst
118
119
120 def list_bashify(mylist):
121 @@ -92,6 +97,7 @@ def list_bashify(mylist):
122 mypack=string.join(mypack)
123 return mypack
124
125 +
126 def list_to_string(mylist):
127 if type(mylist)==types.StringType:
128 mypack=[mylist]
129 @@ -104,6 +110,7 @@ def list_to_string(mylist):
130 mypack=string.join(mypack)
131 return mypack
132
133 +
134 class CatalystError(Exception):
135 def __init__(self, message):
136 if message:
137 @@ -115,84 +122,83 @@ class CatalystError(Exception):
138 print "!!! catalyst: "+message
139 print
140
141 +
142 def die(msg=None):
143 warn(msg)
144 sys.exit(1)
145
146 +
147 def warn(msg):
148 print "!!! catalyst: "+msg
149
150 +
151 def find_binary(myc):
152 """look through the environmental path for an executable file named whatever myc is"""
153 - # this sucks. badly.
154 - p=os.getenv("PATH")
155 - if p == None:
156 - return None
157 - for x in p.split(":"):
158 - #if it exists, and is executable
159 - if os.path.exists("%s/%s" % (x,myc)) and os.stat("%s/%s" % (x,myc))[0] & 0x0248:
160 - return "%s/%s" % (x,myc)
161 - return None
162 + # this sucks. badly.
163 + p=os.getenv("PATH")
164 + if p == None:
165 + return None
166 + for x in p.split(":"):
167 + #if it exists, and is executable
168 + if os.path.exists("%s/%s" % (x,myc)) and os.stat("%s/%s" % (x,myc))[0] & 0x0248:
169 + return "%s/%s" % (x,myc)
170 + return None
171 +
172
173 def spawn_bash(mycommand,env={},debug=False,opt_name=None,**keywords):
174 """spawn mycommand as an arguement to bash"""
175 args=[BASH_BINARY]
176 if not opt_name:
177 - opt_name=mycommand.split()[0]
178 + opt_name=mycommand.split()[0]
179 if "BASH_ENV" not in env:
180 - env["BASH_ENV"] = "/etc/spork/is/not/valid/profile.env"
181 + env["BASH_ENV"] = "/etc/spork/is/not/valid/profile.env"
182 if debug:
183 - args.append("-x")
184 + args.append("-x")
185 args.append("-c")
186 args.append(mycommand)
187 return spawn(args,env=env,opt_name=opt_name,**keywords)
188
189 -#def spawn_get_output(mycommand,spawn_type=spawn,raw_exit_code=False,emulate_gso=True, \
190 -# collect_fds=[1],fd_pipes=None,**keywords):
191
192 def spawn_get_output(mycommand,raw_exit_code=False,emulate_gso=True, \
193 - collect_fds=[1],fd_pipes=None,**keywords):
194 - """call spawn, collecting the output to fd's specified in collect_fds list
195 - emulate_gso is a compatability hack to emulate commands.getstatusoutput's return, minus the
196 - requirement it always be a bash call (spawn_type controls the actual spawn call), and minus the
197 - 'lets let log only stdin and let stderr slide by'.
198 -
199 - emulate_gso was deprecated from the day it was added, so convert your code over.
200 - spawn_type is the passed in function to call- typically spawn_bash, spawn, spawn_sandbox, or spawn_fakeroot"""
201 - global selinux_capable
202 - pr,pw=os.pipe()
203 -
204 - #if type(spawn_type) not in [types.FunctionType, types.MethodType]:
205 - # s="spawn_type must be passed a function, not",type(spawn_type),spawn_type
206 - # raise Exception,s
207 -
208 - if fd_pipes==None:
209 - fd_pipes={}
210 - fd_pipes[0] = 0
211 -
212 - for x in collect_fds:
213 - fd_pipes[x] = pw
214 - keywords["returnpid"]=True
215 -
216 - mypid=spawn_bash(mycommand,fd_pipes=fd_pipes,**keywords)
217 - os.close(pw)
218 - if type(mypid) != types.ListType:
219 - os.close(pr)
220 - return [mypid, "%s: No such file or directory" % mycommand.split()[0]]
221 -
222 - fd=os.fdopen(pr,"r")
223 - mydata=fd.readlines()
224 - fd.close()
225 - if emulate_gso:
226 - mydata=string.join(mydata)
227 - if len(mydata) and mydata[-1] == "\n":
228 - mydata=mydata[:-1]
229 - retval=os.waitpid(mypid[0],0)[1]
230 - cleanup(mypid)
231 - if raw_exit_code:
232 - return [retval,mydata]
233 - retval=process_exit_code(retval)
234 - return [retval, mydata]
235 + collect_fds=[1],fd_pipes=None,**keywords):
236 + """call spawn, collecting the output to fd's specified in collect_fds list
237 + emulate_gso is a compatability hack to emulate commands.getstatusoutput's return, minus the
238 + requirement it always be a bash call (spawn_type controls the actual spawn call), and minus the
239 + 'lets let log only stdin and let stderr slide by'.
240 +
241 + emulate_gso was deprecated from the day it was added, so convert your code over.
242 + spawn_type is the passed in function to call- typically spawn_bash, spawn, spawn_sandbox, or spawn_fakeroot"""
243 + global selinux_capable
244 + pr,pw=os.pipe()
245 +
246 + if fd_pipes==None:
247 + fd_pipes={}
248 + fd_pipes[0] = 0
249 +
250 + for x in collect_fds:
251 + fd_pipes[x] = pw
252 + keywords["returnpid"]=True
253 +
254 + mypid=spawn_bash(mycommand,fd_pipes=fd_pipes,**keywords)
255 + os.close(pw)
256 + if type(mypid) != types.ListType:
257 + os.close(pr)
258 + return [mypid, "%s: No such file or directory" % mycommand.split()[0]]
259 +
260 + fd=os.fdopen(pr,"r")
261 + mydata=fd.readlines()
262 + fd.close()
263 + if emulate_gso:
264 + mydata=string.join(mydata)
265 + if len(mydata) and mydata[-1] == "\n":
266 + mydata=mydata[:-1]
267 + retval=os.waitpid(mypid[0],0)[1]
268 + cleanup(mypid)
269 + if raw_exit_code:
270 + return [retval,mydata]
271 + retval=process_exit_code(retval)
272 + return [retval, mydata]
273 +
274
275 # base spawn function
276 def spawn(mycommand,env={},raw_exit_code=False,opt_name=None,fd_pipes=None,returnpid=False,\
277 @@ -230,8 +236,8 @@ def spawn(mycommand,env={},raw_exit_code=False,opt_name=None,fd_pipes=None,retur
278 return None
279 myc = find_binary(myc)
280 if myc == None:
281 - return None
282 - mypid=[]
283 + return None
284 + mypid=[]
285 if logfile:
286 pr,pw=os.pipe()
287 mypid.extend(spawn(('tee','-i','-a',logfile),returnpid=True,fd_pipes={0:pr,1:1,2:2}))
288 @@ -295,77 +301,77 @@ def spawn(mycommand,env={},raw_exit_code=False,opt_name=None,fd_pipes=None,retur
289 if x not in trg_fd:
290 try:
291 os.close(x)
292 - except SystemExit, e:
293 - raise
294 - except:
295 - pass
296 -
297 - # note this order must be preserved- can't change gid/groups if you change uid first.
298 - if selinux_capable and selinux_context:
299 - import selinux
300 - selinux.setexec(selinux_context)
301 - if gid:
302 - os.setgid(gid)
303 - if groups:
304 - os.setgroups(groups)
305 - if uid:
306 - os.setuid(uid)
307 - if umask:
308 - os.umask(umask)
309 - else:
310 - os.umask(022)
311 -
312 - try:
313 - #print "execing", myc, myargs
314 - if func_call:
315 - # either use a passed in func for interpretting the results, or return if no exception.
316 - # note the passed in list, and dict are expanded.
317 - if len(mycommand) == 4:
318 - os._exit(mycommand[3](mycommand[0](*mycommand[1],**mycommand[2])))
319 - try:
320 - mycommand[0](*mycommand[1],**mycommand[2])
321 - except Exception,e:
322 - print "caught exception",e," in forked func",mycommand[0]
323 - sys.exit(0)
324 -
325 - #os.execvp(myc,myargs)
326 - os.execve(myc,myargs,env)
327 - except SystemExit, e:
328 - raise
329 - except Exception, e:
330 - if not func_call:
331 - raise str(e)+":\n "+myc+" "+string.join(myargs)
332 - print "func call failed"
333 -
334 - # If the execve fails, we need to report it, and exit
335 - # *carefully* --- report error here
336 - os._exit(1)
337 - sys.exit(1)
338 - return # should never get reached
339 -
340 - # if we were logging, kill the pipes.
341 - if logfile:
342 - os.close(pr)
343 - os.close(pw)
344 -
345 - if returnpid:
346 - return mypid
347 -
348 - # loop through pids (typically one, unless logging), either waiting on their death, or waxing them
349 - # if the main pid (mycommand) returned badly.
350 - while len(mypid):
351 - retval=os.waitpid(mypid[-1],0)[1]
352 - if retval != 0:
353 - cleanup(mypid[0:-1],block_exceptions=False)
354 - # at this point we've killed all other kid pids generated via this call.
355 - # return now.
356 - if raw_exit_code:
357 - return retval
358 - return process_exit_code(retval,throw_signals=raise_signals)
359 - else:
360 - mypid.pop(-1)
361 - cleanup(mypid)
362 - return 0
363 + except SystemExit, e:
364 + raise
365 + except:
366 + pass
367 +
368 + # note this order must be preserved- can't change gid/groups if you change uid first.
369 + if selinux_capable and selinux_context:
370 + import selinux
371 + selinux.setexec(selinux_context)
372 + if gid:
373 + os.setgid(gid)
374 + if groups:
375 + os.setgroups(groups)
376 + if uid:
377 + os.setuid(uid)
378 + if umask:
379 + os.umask(umask)
380 + else:
381 + os.umask(022)
382 +
383 + try:
384 + #print "execing", myc, myargs
385 + if func_call:
386 + # either use a passed in func for interpretting the results, or return if no exception.
387 + # note the passed in list, and dict are expanded.
388 + if len(mycommand) == 4:
389 + os._exit(mycommand[3](mycommand[0](*mycommand[1],**mycommand[2])))
390 + try:
391 + mycommand[0](*mycommand[1],**mycommand[2])
392 + except Exception,e:
393 + print "caught exception",e," in forked func",mycommand[0]
394 + sys.exit(0)
395 +
396 + os.execve(myc,myargs,env)
397 + except SystemExit, e:
398 + raise
399 + except Exception, e:
400 + if not func_call:
401 + raise str(e)+":\n "+myc+" "+string.join(myargs)
402 + print "func call failed"
403 +
404 + # If the execve fails, we need to report it, and exit
405 + # *carefully* --- report error here
406 + os._exit(1)
407 + sys.exit(1)
408 + return # should never get reached
409 +
410 + # if we were logging, kill the pipes.
411 + if logfile:
412 + os.close(pr)
413 + os.close(pw)
414 +
415 + if returnpid:
416 + return mypid
417 +
418 + # loop through pids (typically one, unless logging), either waiting on their death, or waxing them
419 + # if the main pid (mycommand) returned badly.
420 + while len(mypid):
421 + retval=os.waitpid(mypid[-1],0)[1]
422 + if retval != 0:
423 + cleanup(mypid[0:-1],block_exceptions=False)
424 + # at this point we've killed all other kid pids generated via this call.
425 + # return now.
426 + if raw_exit_code:
427 + return retval
428 + return process_exit_code(retval,throw_signals=raise_signals)
429 + else:
430 + mypid.pop(-1)
431 + cleanup(mypid)
432 + return 0
433 +
434
435 def cmd(mycmd,myexc="",env={}):
436 try:
437 @@ -376,19 +382,21 @@ def cmd(mycmd,myexc="",env={}):
438 except:
439 raise
440
441 +
442 def process_exit_code(retval,throw_signals=False):
443 - """process a waitpid returned exit code, returning exit code if it exit'd, or the
444 - signal if it died from signalling
445 - if throw_signals is on, it raises a SystemExit if the process was signaled.
446 - This is intended for usage with threads, although at the moment you can't signal individual
447 - threads in python, only the master thread, so it's a questionable option."""
448 - if (retval & 0xff)==0:
449 - return retval >> 8 # return exit code
450 - else:
451 - if throw_signals:
452 - #use systemexit, since portage is stupid about exception catching.
453 - raise SystemExit()
454 - return (retval & 0xff) << 8 # interrupted by signal
455 + """process a waitpid returned exit code, returning exit code if it exit'd, or the
456 + signal if it died from signalling
457 + if throw_signals is on, it raises a SystemExit if the process was signaled.
458 + This is intended for usage with threads, although at the moment you can't signal individual
459 + threads in python, only the master thread, so it's a questionable option."""
460 + if (retval & 0xff)==0:
461 + return retval >> 8 # return exit code
462 + else:
463 + if throw_signals:
464 + #use systemexit, since portage is stupid about exception catching.
465 + raise SystemExit()
466 + return (retval & 0xff) << 8 # interrupted by signal
467 +
468
469 def file_locate(settings,filelist,expand=1):
470 #if expand=1, non-absolute paths will be accepted and
471 @@ -398,15 +406,18 @@ def file_locate(settings,filelist,expand=1):
472 #filenames such as cdtar are optional, so we don't assume the variable is defined.
473 pass
474 else:
475 - if len(settings[myfile])==0:
476 - raise CatalystError, "File variable \""+myfile+"\" has a length of zero (not specified.)"
477 - if settings[myfile][0]=="/":
478 - if not os.path.exists(settings[myfile]):
479 - raise CatalystError, "Cannot locate specified "+myfile+": "+settings[myfile]
480 - elif expand and os.path.exists(os.getcwd()+"/"+settings[myfile]):
481 - settings[myfile]=os.getcwd()+"/"+settings[myfile]
482 - else:
483 - raise CatalystError, "Cannot locate specified "+myfile+": "+settings[myfile]+" (2nd try)"
484 + if len(settings[myfile])==0:
485 + raise CatalystError("File variable \"" + myfile +
486 + "\" has a length of zero (not specified.)")
487 + if settings[myfile][0]=="/":
488 + if not os.path.exists(settings[myfile]):
489 + raise CatalystError("Cannot locate specified " + myfile +
490 + ": "+settings[myfile])
491 + elif expand and os.path.exists(os.getcwd()+"/"+settings[myfile]):
492 + settings[myfile]=os.getcwd()+"/"+settings[myfile]
493 + else:
494 + raise CatalystError("Cannot locate specified " + myfile +
495 + ": "+settings[myfile]+" (2nd try)" +
496 """
497 Spec file format:
498
499 @@ -427,6 +438,8 @@ that the order of multiple-value items is preserved, but the order that the item
500 defined are not preserved. In other words, "foo", "bar", "oni" ordering is preserved but "item1"
501 "item2" "item3" ordering is not, as the item strings are stored in a dictionary (hash).
502 """
503 + )
504 +
505
506 def parse_makeconf(mylines):
507 mymakeconf={}
508 @@ -450,6 +463,7 @@ def parse_makeconf(mylines):
509 mymakeconf[mobj.group(1)]=clean_string
510 return mymakeconf
511
512 +
513 def read_makeconf(mymakeconffile):
514 if os.path.exists(mymakeconffile):
515 try:
516 @@ -475,10 +489,12 @@ def read_makeconf(mymakeconffile):
517 makeconf={}
518 return makeconf
519
520 +
521 def msg(mymsg,verblevel=1):
522 if verbosity>=verblevel:
523 print mymsg
524
525 +
526 def pathcompare(path1,path2):
527 # Change double slashes to slash
528 path1 = re.sub(r"//",r"/",path1)
529 @@ -491,6 +507,7 @@ def pathcompare(path1,path2):
530 return 1
531 return 0
532
533 +
534 def ismount(path):
535 "enhanced to handle bind mounts"
536 if os.path.ismount(path):
537 @@ -504,6 +521,7 @@ def ismount(path):
538 return 1
539 return 0
540
541 +
542 def addl_arg_parse(myspec,addlargs,requiredspec,validspec):
543 "helper function to help targets parse additional arguments"
544 global valid_config_file_values
545 @@ -522,6 +540,7 @@ def addl_arg_parse(myspec,addlargs,requiredspec,validspec):
546 if messages:
547 raise CatalystError, '\n\tAlso: '.join(messages)
548
549 +
550 def touch(myfile):
551 try:
552 myf=open(myfile,"w")
553 @@ -529,8 +548,9 @@ def touch(myfile):
554 except IOError:
555 raise CatalystError, "Could not touch "+myfile+"."
556
557 +
558 def countdown(secs=5, doing="Starting"):
559 - if secs:
560 + if secs:
561 print ">>> Waiting",secs,"seconds before starting..."
562 print ">>> (Control-C to abort)...\n"+doing+" in: ",
563 ticks=range(secs)
564 @@ -541,14 +561,15 @@ def countdown(secs=5, doing="Starting"):
565 time.sleep(1)
566 print
567
568 +
569 def normpath(mypath):
570 TrailingSlash=False
571 - if mypath[-1] == "/":
572 - TrailingSlash=True
573 - newpath = os.path.normpath(mypath)
574 - if len(newpath) > 1:
575 - if newpath[:2] == "//":
576 - newpath = newpath[1:]
577 + if mypath[-1] == "/":
578 + TrailingSlash=True
579 + newpath = os.path.normpath(mypath)
580 + if len(newpath) > 1:
581 + if newpath[:2] == "//":
582 + newpath = newpath[1:]
583 if TrailingSlash:
584 - newpath=newpath+'/'
585 - return newpath
586 + newpath=newpath+'/'
587 + return newpath