summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/__init__.py
diff options
context:
space:
mode:
authorChris Larson <clarson@kergoth.com>2009-07-19 10:05:52 -0700
committerRichard Purdie <rpurdie@linux.intel.com>2010-03-22 14:54:42 +0000
commitf8c6db95d7734e3f4fc7eaf82eda6d59721b3fbb (patch)
tree18e1882916586b69460252a3465cce9ccdbbbb04 /bitbake/lib/bb/__init__.py
parentb7d175a18a0fab65ff4022e15c68e079296c8e82 (diff)
downloadpoky-f8c6db95d7734e3f4fc7eaf82eda6d59721b3fbb.tar.gz
Move most utility functions from bb into bb.utils.
(Bitbake rev: ff720ec59b30671c951dbf3b96df10ef56b8b505) Signed-off-by: Chris Larson <clarson@kergoth.com> Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
Diffstat (limited to 'bitbake/lib/bb/__init__.py')
-rw-r--r--bitbake/lib/bb/__init__.py914
1 files changed, 5 insertions, 909 deletions
diff --git a/bitbake/lib/bb/__init__.py b/bitbake/lib/bb/__init__.py
index 84116f4f6a..92749d56f2 100644
--- a/bitbake/lib/bb/__init__.py
+++ b/bitbake/lib/bb/__init__.py
@@ -66,11 +66,7 @@ __all__ = [
66 "providers", 66 "providers",
67 ] 67 ]
68 68
69whitespace = '\t\n\x0b\x0c\r '
70lowercase = 'abcdefghijklmnopqrstuvwxyz'
71
72import sys, os, types, re, string, bb 69import sys, os, types, re, string, bb
73from bb import msg
74 70
75#projectdir = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0]))) 71#projectdir = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0])))
76projectdir = os.getcwd() 72projectdir = os.getcwd()
@@ -109,914 +105,14 @@ def fatal(*args):
109 bb.msg.fatal(None, ''.join(args)) 105 bb.msg.fatal(None, ''.join(args))
110 106
111 107
112#######################################################################
113#######################################################################
114#
115# SECTION: File
116#
117# PURPOSE: Basic file and directory tree related functions
118#
119#######################################################################
120#######################################################################
121
122def mkdirhier(dir):
123 """Create a directory like 'mkdir -p', but does not complain if
124 directory already exists like os.makedirs
125 """
126
127 debug(3, "mkdirhier(%s)" % dir)
128 try:
129 os.makedirs(dir)
130 debug(2, "created " + dir)
131 except OSError, e:
132 if e.errno != 17: raise e
133
134
135#######################################################################
136
137import stat
138
139def movefile(src,dest,newmtime=None,sstat=None):
140 """Moves a file from src to dest, preserving all permissions and
141 attributes; mtime will be preserved even when moving across
142 filesystems. Returns true on success and false on failure. Move is
143 atomic.
144 """
145
146 #print "movefile("+src+","+dest+","+str(newmtime)+","+str(sstat)+")"
147 try:
148 if not sstat:
149 sstat=os.lstat(src)
150 except Exception, e:
151 print "movefile: Stating source file failed...", e
152 return None
153
154 destexists=1
155 try:
156 dstat=os.lstat(dest)
157 except:
158 dstat=os.lstat(os.path.dirname(dest))
159 destexists=0
160
161 if destexists:
162 if stat.S_ISLNK(dstat[stat.ST_MODE]):
163 try:
164 os.unlink(dest)
165 destexists=0
166 except Exception, e:
167 pass
168
169 if stat.S_ISLNK(sstat[stat.ST_MODE]):
170 try:
171 target=os.readlink(src)
172 if destexists and not stat.S_ISDIR(dstat[stat.ST_MODE]):
173 os.unlink(dest)
174 os.symlink(target,dest)
175 #os.lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
176 os.unlink(src)
177 return os.lstat(dest)
178 except Exception, e:
179 print "movefile: failed to properly create symlink:", dest, "->", target, e
180 return None
181
182 renamefailed=1
183 if sstat[stat.ST_DEV]==dstat[stat.ST_DEV]:
184 try:
185 ret=os.rename(src,dest)
186 renamefailed=0
187 except Exception, e:
188 import errno
189 if e[0]!=errno.EXDEV:
190 # Some random error.
191 print "movefile: Failed to move", src, "to", dest, e
192 return None
193 # Invalid cross-device-link 'bind' mounted or actually Cross-Device
194
195 if renamefailed:
196 didcopy=0
197 if stat.S_ISREG(sstat[stat.ST_MODE]):
198 try: # For safety copy then move it over.
199 shutil.copyfile(src,dest+"#new")
200 os.rename(dest+"#new",dest)
201 didcopy=1
202 except Exception, e:
203 print 'movefile: copy', src, '->', dest, 'failed.', e
204 return None
205 else:
206 #we don't yet handle special, so we need to fall back to /bin/mv
207 a=getstatusoutput("/bin/mv -f "+"'"+src+"' '"+dest+"'")
208 if a[0]!=0:
209 print "movefile: Failed to move special file:" + src + "' to '" + dest + "'", a
210 return None # failure
211 try:
212 if didcopy:
213 missingos.lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
214 os.chmod(dest, stat.S_IMODE(sstat[stat.ST_MODE])) # Sticky is reset on chown
215 os.unlink(src)
216 except Exception, e:
217 print "movefile: Failed to chown/chmod/unlink", dest, e
218 return None
219
220 if newmtime:
221 os.utime(dest,(newmtime,newmtime))
222 else:
223 os.utime(dest, (sstat[stat.ST_ATIME], sstat[stat.ST_MTIME]))
224 newmtime=sstat[stat.ST_MTIME]
225 return newmtime
226
227def copyfile(src,dest,newmtime=None,sstat=None):
228 """
229 Copies a file from src to dest, preserving all permissions and
230 attributes; mtime will be preserved even when moving across
231 filesystems. Returns true on success and false on failure.
232 """
233 import os, stat, shutil
234
235 #print "copyfile("+src+","+dest+","+str(newmtime)+","+str(sstat)+")"
236 try:
237 if not sstat:
238 sstat=os.lstat(src)
239 except Exception, e:
240 print "copyfile: Stating source file failed...", e
241 return False
242
243 destexists=1
244 try:
245 dstat=os.lstat(dest)
246 except:
247 dstat=os.lstat(os.path.dirname(dest))
248 destexists=0
249
250 if destexists:
251 if stat.S_ISLNK(dstat[stat.ST_MODE]):
252 try:
253 os.unlink(dest)
254 destexists=0
255 except Exception, e:
256 pass
257
258 if stat.S_ISLNK(sstat[stat.ST_MODE]):
259 try:
260 target=os.readlink(src)
261 if destexists and not stat.S_ISDIR(dstat[stat.ST_MODE]):
262 os.unlink(dest)
263 os.symlink(target,dest)
264 #os.lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
265 return os.lstat(dest)
266 except Exception, e:
267 print "copyfile: failed to properly create symlink:", dest, "->", target, e
268 return False
269
270 if stat.S_ISREG(sstat[stat.ST_MODE]):
271 try: # For safety copy then move it over.
272 shutil.copyfile(src,dest+"#new")
273 os.rename(dest+"#new",dest)
274 except Exception, e:
275 print 'copyfile: copy', src, '->', dest, 'failed.', e
276 return False
277 else:
278 #we don't yet handle special, so we need to fall back to /bin/mv
279 a=getstatusoutput("/bin/cp -f "+"'"+src+"' '"+dest+"'")
280 if a[0]!=0:
281 print "copyfile: Failed to copy special file:" + src + "' to '" + dest + "'", a
282 return False # failure
283 try:
284 os.lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
285 os.chmod(dest, stat.S_IMODE(sstat[stat.ST_MODE])) # Sticky is reset on chown
286 except Exception, e:
287 print "copyfile: Failed to chown/chmod/unlink", dest, e
288 return False
289
290 if newmtime:
291 os.utime(dest,(newmtime,newmtime))
292 else:
293 os.utime(dest, (sstat[stat.ST_ATIME], sstat[stat.ST_MTIME]))
294 newmtime=sstat[stat.ST_MTIME]
295 return newmtime
296
297#######################################################################
298
299def which(path, item, direction = 0):
300 """
301 Locate a file in a PATH
302 """
303
304 paths = (path or "").split(':')
305 if direction != 0:
306 paths.reverse()
307
308 for p in (path or "").split(':'):
309 next = os.path.join(p, item)
310 if os.path.exists(next):
311 return next
312
313 return ""
314
315#######################################################################
316
317
318
319
320#######################################################################
321#######################################################################
322#
323# SECTION: Dependency
324#
325# PURPOSE: Compare build & run dependencies
326#
327#######################################################################
328#######################################################################
329
330def tokenize(mystring):
331 """Breaks a string like 'foo? (bar) oni? (blah (blah))' into (possibly embedded) lists:
332
333 >>> tokenize("x")
334 ['x']
335 >>> tokenize("x y")
336 ['x', 'y']
337 >>> tokenize("(x y)")
338 [['x', 'y']]
339 >>> tokenize("(x y) b c")
340 [['x', 'y'], 'b', 'c']
341 >>> tokenize("foo? (bar) oni? (blah (blah))")
342 ['foo?', ['bar'], 'oni?', ['blah', ['blah']]]
343 >>> tokenize("sys-apps/linux-headers nls? (sys-devel/gettext)")
344 ['sys-apps/linux-headers', 'nls?', ['sys-devel/gettext']]
345 """
346
347 newtokens = []
348 curlist = newtokens
349 prevlists = []
350 level = 0
351 accum = ""
352 for x in mystring:
353 if x=="(":
354 if accum:
355 curlist.append(accum)
356 accum=""
357 prevlists.append(curlist)
358 curlist=[]
359 level=level+1
360 elif x==")":
361 if accum:
362 curlist.append(accum)
363 accum=""
364 if level==0:
365 print "!!! tokenizer: Unmatched left parenthesis in:\n'"+mystring+"'"
366 return None
367 newlist=curlist
368 curlist=prevlists.pop()
369 curlist.append(newlist)
370 level=level-1
371 elif x in whitespace:
372 if accum:
373 curlist.append(accum)
374 accum=""
375 else:
376 accum=accum+x
377 if accum:
378 curlist.append(accum)
379 if (level!=0):
380 print "!!! tokenizer: Exiting with unterminated parenthesis in:\n'"+mystring+"'"
381 return None
382 return newtokens
383
384
385#######################################################################
386
387def evaluate(tokens,mydefines,allon=0):
388 """Removes tokens based on whether conditional definitions exist or not.
389 Recognizes !
390
391 >>> evaluate(['sys-apps/linux-headers', 'nls?', ['sys-devel/gettext']], {})
392 ['sys-apps/linux-headers']
393
394 Negate the flag:
395
396 >>> evaluate(['sys-apps/linux-headers', '!nls?', ['sys-devel/gettext']], {})
397 ['sys-apps/linux-headers', ['sys-devel/gettext']]
398
399 Define 'nls':
400
401 >>> evaluate(['sys-apps/linux-headers', 'nls?', ['sys-devel/gettext']], {"nls":1})
402 ['sys-apps/linux-headers', ['sys-devel/gettext']]
403
404 Turn allon on:
405
406 >>> evaluate(['sys-apps/linux-headers', 'nls?', ['sys-devel/gettext']], {}, True)
407 ['sys-apps/linux-headers', ['sys-devel/gettext']]
408 """
409
410 if tokens == None:
411 return None
412 mytokens = tokens + [] # this copies the list
413 pos = 0
414 while pos < len(mytokens):
415 if type(mytokens[pos]) == types.ListType:
416 evaluate(mytokens[pos], mydefines)
417 if not len(mytokens[pos]):
418 del mytokens[pos]
419 continue
420 elif mytokens[pos][-1] == "?":
421 cur = mytokens[pos][:-1]
422 del mytokens[pos]
423 if allon:
424 if cur[0] == "!":
425 del mytokens[pos]
426 else:
427 if cur[0] == "!":
428 if (cur[1:] in mydefines) and (pos < len(mytokens)):
429 del mytokens[pos]
430 continue
431 elif (cur not in mydefines) and (pos < len(mytokens)):
432 del mytokens[pos]
433 continue
434 pos = pos + 1
435 return mytokens
436
437
438#######################################################################
439
440def flatten(mytokens):
441 """Converts nested arrays into a flat arrays:
442
443 >>> flatten([1,[2,3]])
444 [1, 2, 3]
445 >>> flatten(['sys-apps/linux-headers', ['sys-devel/gettext']])
446 ['sys-apps/linux-headers', 'sys-devel/gettext']
447 """
448
449 newlist=[]
450 for x in mytokens:
451 if type(x)==types.ListType:
452 newlist.extend(flatten(x))
453 else:
454 newlist.append(x)
455 return newlist
456
457
458#######################################################################
459
460_package_weights_ = {"pre":-2,"p":0,"alpha":-4,"beta":-3,"rc":-1} # dicts are unordered
461_package_ends_ = ["pre", "p", "alpha", "beta", "rc", "cvs", "bk", "HEAD" ] # so we need ordered list
462
463def relparse(myver):
464 """Parses the last elements of a version number into a triplet, that can
465 later be compared:
466
467 >>> relparse('1.2_pre3')
468 [1.2, -2, 3.0]
469 >>> relparse('1.2b')
470 [1.2, 98, 0]
471 >>> relparse('1.2')
472 [1.2, 0, 0]
473 """
474
475 number = 0
476 p1 = 0
477 p2 = 0
478 mynewver = myver.split('_')
479 if len(mynewver)==2:
480 # an _package_weights_
481 number = float(mynewver[0])
482 match = 0
483 for x in _package_ends_:
484 elen = len(x)
485 if mynewver[1][:elen] == x:
486 match = 1
487 p1 = _package_weights_[x]
488 try:
489 p2 = float(mynewver[1][elen:])
490 except:
491 p2 = 0
492 break
493 if not match:
494 # normal number or number with letter at end
495 divider = len(myver)-1
496 if myver[divider:] not in "1234567890":
497 # letter at end
498 p1 = ord(myver[divider:])
499 number = float(myver[0:divider])
500 else:
501 number = float(myver)
502 else:
503 # normal number or number with letter at end
504 divider = len(myver)-1
505 if myver[divider:] not in "1234567890":
506 #letter at end
507 p1 = ord(myver[divider:])
508 number = float(myver[0:divider])
509 else:
510 number = float(myver)
511 return [number,p1,p2]
512
513
514#######################################################################
515
516__ververify_cache__ = {}
517
518def ververify(myorigval,silent=1):
519 """Returns 1 if given a valid version string, els 0. Valid versions are in the format
520
521 <v1>.<v2>...<vx>[a-z,_{_package_weights_}[vy]]
522
523 >>> ververify('2.4.20')
524 1
525 >>> ververify('2.4..20') # two dots
526 0
527 >>> ververify('2.x.20') # 'x' is not numeric
528 0
529 >>> ververify('2.4.20a')
530 1
531 >>> ververify('2.4.20cvs') # only one trailing letter
532 0
533 >>> ververify('1a')
534 1
535 >>> ververify('test_a') # no version at all
536 0
537 >>> ververify('2.4.20_beta1')
538 1
539 >>> ververify('2.4.20_beta')
540 1
541 >>> ververify('2.4.20_wrongext') # _wrongext is no valid trailer
542 0
543 """
544
545 # Lookup the cache first
546 try:
547 return __ververify_cache__[myorigval]
548 except KeyError:
549 pass
550
551 if len(myorigval) == 0:
552 if not silent:
553 error("package version is empty")
554 __ververify_cache__[myorigval] = 0
555 return 0
556 myval = myorigval.split('.')
557 if len(myval)==0:
558 if not silent:
559 error("package name has empty version string")
560 __ververify_cache__[myorigval] = 0
561 return 0
562 # all but the last version must be a numeric
563 for x in myval[:-1]:
564 if not len(x):
565 if not silent:
566 error("package version has two points in a row")
567 __ververify_cache__[myorigval] = 0
568 return 0
569 try:
570 foo = int(x)
571 except:
572 if not silent:
573 error("package version contains non-numeric '"+x+"'")
574 __ververify_cache__[myorigval] = 0
575 return 0
576 if not len(myval[-1]):
577 if not silent:
578 error("package version has trailing dot")
579 __ververify_cache__[myorigval] = 0
580 return 0
581 try:
582 foo = int(myval[-1])
583 __ververify_cache__[myorigval] = 1
584 return 1
585 except:
586 pass
587
588 # ok, our last component is not a plain number or blank, let's continue
589 if myval[-1][-1] in lowercase:
590 try:
591 foo = int(myval[-1][:-1])
592 return 1
593 __ververify_cache__[myorigval] = 1
594 # 1a, 2.0b, etc.
595 except:
596 pass
597 # ok, maybe we have a 1_alpha or 1_beta2; let's see
598 ep=string.split(myval[-1],"_")
599 if len(ep)!= 2:
600 if not silent:
601 error("package version has more than one letter at then end")
602 __ververify_cache__[myorigval] = 0
603 return 0
604 try:
605 foo = string.atoi(ep[0])
606 except:
607 # this needs to be numeric, i.e. the "1" in "1_alpha"
608 if not silent:
609 error("package version must have numeric part before the '_'")
610 __ververify_cache__[myorigval] = 0
611 return 0
612
613 for mye in _package_ends_:
614 if ep[1][0:len(mye)] == mye:
615 if len(mye) == len(ep[1]):
616 # no trailing numeric is ok
617 __ververify_cache__[myorigval] = 1
618 return 1
619 else:
620 try:
621 foo = string.atoi(ep[1][len(mye):])
622 __ververify_cache__[myorigval] = 1
623 return 1
624 except:
625 # if no _package_weights_ work, *then* we return 0
626 pass
627 if not silent:
628 error("package version extension after '_' is invalid")
629 __ververify_cache__[myorigval] = 0
630 return 0
631
632
633def isjustname(mypkg):
634 myparts = string.split(mypkg,'-')
635 for x in myparts:
636 if ververify(x):
637 return 0
638 return 1
639
640
641_isspecific_cache_={}
642
643def isspecific(mypkg):
644 "now supports packages with no category"
645 try:
646 return __isspecific_cache__[mypkg]
647 except:
648 pass
649
650 mysplit = string.split(mypkg,"/")
651 if not isjustname(mysplit[-1]):
652 __isspecific_cache__[mypkg] = 1
653 return 1
654 __isspecific_cache__[mypkg] = 0
655 return 0
656
657
658#######################################################################
659
660__pkgsplit_cache__={}
661
662def pkgsplit(mypkg, silent=1):
663
664 """This function can be used as a package verification function. If
665 it is a valid name, pkgsplit will return a list containing:
666 [pkgname, pkgversion(norev), pkgrev ].
667
668 >>> pkgsplit('')
669 >>> pkgsplit('x')
670 >>> pkgsplit('x-')
671 >>> pkgsplit('-1')
672 >>> pkgsplit('glibc-1.2-8.9-r7')
673 >>> pkgsplit('glibc-2.2.5-r7')
674 ['glibc', '2.2.5', 'r7']
675 >>> pkgsplit('foo-1.2-1')
676 >>> pkgsplit('Mesa-3.0')
677 ['Mesa', '3.0', 'r0']
678 """
679
680 try:
681 return __pkgsplit_cache__[mypkg]
682 except KeyError:
683 pass
684
685 myparts = string.split(mypkg,'-')
686 if len(myparts) < 2:
687 if not silent:
688 error("package name without name or version part")
689 __pkgsplit_cache__[mypkg] = None
690 return None
691 for x in myparts:
692 if len(x) == 0:
693 if not silent:
694 error("package name with empty name or version part")
695 __pkgsplit_cache__[mypkg] = None
696 return None
697 # verify rev
698 revok = 0
699 myrev = myparts[-1]
700 ververify(myrev, silent)
701 if len(myrev) and myrev[0] == "r":
702 try:
703 string.atoi(myrev[1:])
704 revok = 1
705 except:
706 pass
707 if revok:
708 if ververify(myparts[-2]):
709 if len(myparts) == 2:
710 __pkgsplit_cache__[mypkg] = None
711 return None
712 else:
713 for x in myparts[:-2]:
714 if ververify(x):
715 __pkgsplit_cache__[mypkg]=None
716 return None
717 # names can't have versiony looking parts
718 myval=[string.join(myparts[:-2],"-"),myparts[-2],myparts[-1]]
719 __pkgsplit_cache__[mypkg]=myval
720 return myval
721 else:
722 __pkgsplit_cache__[mypkg] = None
723 return None
724
725 elif ververify(myparts[-1],silent):
726 if len(myparts)==1:
727 if not silent:
728 print "!!! Name error in",mypkg+": missing name part."
729 __pkgsplit_cache__[mypkg]=None
730 return None
731 else:
732 for x in myparts[:-1]:
733 if ververify(x):
734 if not silent: error("package name has multiple version parts")
735 __pkgsplit_cache__[mypkg] = None
736 return None
737 myval = [string.join(myparts[:-1],"-"), myparts[-1],"r0"]
738 __pkgsplit_cache__[mypkg] = myval
739 return myval
740 else:
741 __pkgsplit_cache__[mypkg] = None
742 return None
743
744
745#######################################################################
746
747__catpkgsplit_cache__ = {}
748
749def catpkgsplit(mydata,silent=1):
750 """returns [cat, pkgname, version, rev ]
751
752 >>> catpkgsplit('sys-libs/glibc-1.2-r7')
753 ['sys-libs', 'glibc', '1.2', 'r7']
754 >>> catpkgsplit('glibc-1.2-r7')
755 [None, 'glibc', '1.2', 'r7']
756 """
757
758 try:
759 return __catpkgsplit_cache__[mydata]
760 except KeyError:
761 pass
762
763 cat = os.path.basename(os.path.dirname(mydata))
764 mydata = os.path.join(cat, os.path.basename(mydata))
765 if mydata[-3:] == '.bb':
766 mydata = mydata[:-3]
767
768 mysplit = mydata.split("/")
769 p_split = None
770 splitlen = len(mysplit)
771 if splitlen == 1:
772 retval = [None]
773 p_split = pkgsplit(mydata,silent)
774 else:
775 retval = [mysplit[splitlen - 2]]
776 p_split = pkgsplit(mysplit[splitlen - 1],silent)
777 if not p_split:
778 __catpkgsplit_cache__[mydata] = None
779 return None
780 retval.extend(p_split)
781 __catpkgsplit_cache__[mydata] = retval
782 return retval
783
784
785#######################################################################
786
787__vercmp_cache__ = {}
788
789def vercmp(val1,val2):
790 """This takes two version strings and returns an integer to tell you whether
791 the versions are the same, val1>val2 or val2>val1.
792
793 >>> vercmp('1', '2')
794 -1.0
795 >>> vercmp('2', '1')
796 1.0
797 >>> vercmp('1', '1.0')
798 0
799 >>> vercmp('1', '1.1')
800 -1.0
801 >>> vercmp('1.1', '1_p2')
802 1.0
803 """
804
805 # quick short-circuit
806 if val1 == val2:
807 return 0
808 valkey = val1+" "+val2
809
810 # cache lookup
811 try:
812 return __vercmp_cache__[valkey]
813 try:
814 return - __vercmp_cache__[val2+" "+val1]
815 except KeyError:
816 pass
817 except KeyError:
818 pass
819
820 # consider 1_p2 vc 1.1
821 # after expansion will become (1_p2,0) vc (1,1)
822 # then 1_p2 is compared with 1 before 0 is compared with 1
823 # to solve the bug we need to convert it to (1,0_p2)
824 # by splitting _prepart part and adding it back _after_expansion
825
826 val1_prepart = val2_prepart = ''
827 if val1.count('_'):
828 val1, val1_prepart = val1.split('_', 1)
829 if val2.count('_'):
830 val2, val2_prepart = val2.split('_', 1)
831
832 # replace '-' by '.'
833 # FIXME: Is it needed? can val1/2 contain '-'?
834
835 val1 = string.split(val1,'-')
836 if len(val1) == 2:
837 val1[0] = val1[0] +"."+ val1[1]
838 val2 = string.split(val2,'-')
839 if len(val2) == 2:
840 val2[0] = val2[0] +"."+ val2[1]
841
842 val1 = string.split(val1[0],'.')
843 val2 = string.split(val2[0],'.')
844
845 # add back decimal point so that .03 does not become "3" !
846 for x in range(1,len(val1)):
847 if val1[x][0] == '0' :
848 val1[x] = '.' + val1[x]
849 for x in range(1,len(val2)):
850 if val2[x][0] == '0' :
851 val2[x] = '.' + val2[x]
852
853 # extend varion numbers
854 if len(val2) < len(val1):
855 val2.extend(["0"]*(len(val1)-len(val2)))
856 elif len(val1) < len(val2):
857 val1.extend(["0"]*(len(val2)-len(val1)))
858
859 # add back _prepart tails
860 if val1_prepart:
861 val1[-1] += '_' + val1_prepart
862 if val2_prepart:
863 val2[-1] += '_' + val2_prepart
864 # The above code will extend version numbers out so they
865 # have the same number of digits.
866 for x in range(0,len(val1)):
867 cmp1 = relparse(val1[x])
868 cmp2 = relparse(val2[x])
869 for y in range(0,3):
870 myret = cmp1[y] - cmp2[y]
871 if myret != 0:
872 __vercmp_cache__[valkey] = myret
873 return myret
874 __vercmp_cache__[valkey] = 0
875 return 0
876
877
878#######################################################################
879
880def pkgcmp(pkg1,pkg2):
881 """ Compares two packages, which should have been split via
882 pkgsplit(). if the return value val is less than zero, then pkg2 is
883 newer than pkg1, zero if equal and positive if older.
884
885 >>> pkgcmp(['glibc', '2.2.5', 'r7'], ['glibc', '2.2.5', 'r7'])
886 0
887 >>> pkgcmp(['glibc', '2.2.5', 'r4'], ['glibc', '2.2.5', 'r7'])
888 -1
889 >>> pkgcmp(['glibc', '2.2.5', 'r7'], ['glibc', '2.2.5', 'r2'])
890 1
891 """
892
893 mycmp = vercmp(pkg1[1],pkg2[1])
894 if mycmp > 0:
895 return 1
896 if mycmp < 0:
897 return -1
898 r1=string.atoi(pkg1[2][1:])
899 r2=string.atoi(pkg2[2][1:])
900 if r1 > r2:
901 return 1
902 if r2 > r1:
903 return -1
904 return 0
905
906
907#######################################################################
908
909def dep_parenreduce(mysplit, mypos=0):
910 """Accepts a list of strings, and converts '(' and ')' surrounded items to sub-lists:
911
912 >>> dep_parenreduce([''])
913 ['']
914 >>> dep_parenreduce(['1', '2', '3'])
915 ['1', '2', '3']
916 >>> dep_parenreduce(['1', '(', '2', '3', ')', '4'])
917 ['1', ['2', '3'], '4']
918 """
919
920 while mypos < len(mysplit):
921 if mysplit[mypos] == "(":
922 firstpos = mypos
923 mypos = mypos + 1
924 while mypos < len(mysplit):
925 if mysplit[mypos] == ")":
926 mysplit[firstpos:mypos+1] = [mysplit[firstpos+1:mypos]]
927 mypos = firstpos
928 break
929 elif mysplit[mypos] == "(":
930 # recurse
931 mysplit = dep_parenreduce(mysplit,mypos)
932 mypos = mypos + 1
933 mypos = mypos + 1
934 return mysplit
935
936
937def dep_opconvert(mysplit, myuse):
938 "Does dependency operator conversion"
939
940 mypos = 0
941 newsplit = []
942 while mypos < len(mysplit):
943 if type(mysplit[mypos]) == types.ListType:
944 newsplit.append(dep_opconvert(mysplit[mypos],myuse))
945 mypos += 1
946 elif mysplit[mypos] == ")":
947 # mismatched paren, error
948 return None
949 elif mysplit[mypos]=="||":
950 if ((mypos+1)>=len(mysplit)) or (type(mysplit[mypos+1])!=types.ListType):
951 # || must be followed by paren'd list
952 return None
953 try:
954 mynew = dep_opconvert(mysplit[mypos+1],myuse)
955 except Exception, e:
956 error("unable to satisfy OR dependancy: " + string.join(mysplit," || "))
957 raise e
958 mynew[0:0] = ["||"]
959 newsplit.append(mynew)
960 mypos += 2
961 elif mysplit[mypos][-1] == "?":
962 # use clause, i.e "gnome? ( foo bar )"
963 # this is a quick and dirty hack so that repoman can enable all USE vars:
964 if (len(myuse) == 1) and (myuse[0] == "*"):
965 # enable it even if it's ! (for repoman) but kill it if it's
966 # an arch variable that isn't for this arch. XXX Sparc64?
967 if (mysplit[mypos][:-1] not in settings.usemask) or \
968 (mysplit[mypos][:-1]==settings["ARCH"]):
969 enabled=1
970 else:
971 enabled=0
972 else:
973 if mysplit[mypos][0] == "!":
974 myusevar = mysplit[mypos][1:-1]
975 enabled = not myusevar in myuse
976 #if myusevar in myuse:
977 # enabled = 0
978 #else:
979 # enabled = 1
980 else:
981 myusevar=mysplit[mypos][:-1]
982 enabled = myusevar in myuse
983 #if myusevar in myuse:
984 # enabled=1
985 #else:
986 # enabled=0
987 if (mypos +2 < len(mysplit)) and (mysplit[mypos+2] == ":"):
988 # colon mode
989 if enabled:
990 # choose the first option
991 if type(mysplit[mypos+1]) == types.ListType:
992 newsplit.append(dep_opconvert(mysplit[mypos+1],myuse))
993 else:
994 newsplit.append(mysplit[mypos+1])
995 else:
996 # choose the alternate option
997 if type(mysplit[mypos+1]) == types.ListType:
998 newsplit.append(dep_opconvert(mysplit[mypos+3],myuse))
999 else:
1000 newsplit.append(mysplit[mypos+3])
1001 mypos += 4
1002 else:
1003 # normal use mode
1004 if enabled:
1005 if type(mysplit[mypos+1]) == types.ListType:
1006 newsplit.append(dep_opconvert(mysplit[mypos+1],myuse))
1007 else:
1008 newsplit.append(mysplit[mypos+1])
1009 # otherwise, continue
1010 mypos += 2
1011 else:
1012 # normal item
1013 newsplit.append(mysplit[mypos])
1014 mypos += 1
1015 return newsplit
1016
1017# For compatibility 108# For compatibility
1018from bb.fetch import MalformedUrl, encodeurl, decodeurl 109from bb.fetch import MalformedUrl, encodeurl, decodeurl
1019from bb.data import VarExpandError 110from bb.data import VarExpandError
111from bb.utils import mkdirhier, movefile, copyfile, which
112from bb.utils import tokenize, evaluate, flatten
113from bb.utils import vercmp, pkgcmp, relparse, ververify
114from bb.utils import pkgsplit, catpkgsplit, isjustname, isspecific
115from bb.utils import dep_parenreduce, dep_opconvert
1020 116
1021if __name__ == "__main__": 117if __name__ == "__main__":
1022 import doctest, bb 118 import doctest, bb