diff options
Diffstat (limited to 'bitbake/lib/bb/utils.py')
-rw-r--r-- | bitbake/lib/bb/utils.py | 185 |
1 files changed, 93 insertions, 92 deletions
diff --git a/bitbake/lib/bb/utils.py b/bitbake/lib/bb/utils.py index 5015ee440a..93c158c604 100644 --- a/bitbake/lib/bb/utils.py +++ b/bitbake/lib/bb/utils.py | |||
@@ -19,11 +19,12 @@ BitBake Utility Functions | |||
19 | # with this program; if not, write to the Free Software Foundation, Inc., | 19 | # with this program; if not, write to the Free Software Foundation, Inc., |
20 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 20 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
21 | 21 | ||
22 | separators = ".-" | ||
23 | |||
24 | import re, fcntl, os, types, bb, string, stat, shutil, time | 22 | import re, fcntl, os, types, bb, string, stat, shutil, time |
25 | from commands import getstatusoutput | 23 | from commands import getstatusoutput |
26 | 24 | ||
25 | # Version comparison | ||
26 | separators = ".-" | ||
27 | |||
27 | # Context used in better_exec, eval | 28 | # Context used in better_exec, eval |
28 | _context = { | 29 | _context = { |
29 | "os": os, | 30 | "os": os, |
@@ -92,19 +93,19 @@ def vercmp(ta, tb): | |||
92 | r = vercmp_part(ra, rb) | 93 | r = vercmp_part(ra, rb) |
93 | return r | 94 | return r |
94 | 95 | ||
95 | _package_weights_ = {"pre":-2,"p":0,"alpha":-4,"beta":-3,"rc":-1} # dicts are unordered | 96 | _package_weights_ = {"pre":-2, "p":0, "alpha":-4, "beta":-3, "rc":-1} # dicts are unordered |
96 | _package_ends_ = ["pre", "p", "alpha", "beta", "rc", "cvs", "bk", "HEAD" ] # so we need ordered list | 97 | _package_ends_ = ["pre", "p", "alpha", "beta", "rc", "cvs", "bk", "HEAD" ] # so we need ordered list |
97 | 98 | ||
98 | def relparse(myver): | 99 | def relparse(myver): |
99 | """Parses the last elements of a version number into a triplet, that can | 100 | """Parses the last elements of a version number into a triplet, that can |
100 | later be compared. | 101 | later be compared. |
101 | """ | 102 | """ |
102 | 103 | ||
103 | number = 0 | 104 | number = 0 |
104 | p1 = 0 | 105 | p1 = 0 |
105 | p2 = 0 | 106 | p2 = 0 |
106 | mynewver = myver.split('_') | 107 | mynewver = myver.split('_') |
107 | if len(mynewver)==2: | 108 | if len(mynewver) == 2: |
108 | # an _package_weights_ | 109 | # an _package_weights_ |
109 | number = float(mynewver[0]) | 110 | number = float(mynewver[0]) |
110 | match = 0 | 111 | match = 0 |
@@ -132,15 +133,15 @@ def relparse(myver): | |||
132 | divider = len(myver)-1 | 133 | divider = len(myver)-1 |
133 | if myver[divider:] not in "1234567890": | 134 | if myver[divider:] not in "1234567890": |
134 | #letter at end | 135 | #letter at end |
135 | p1 = ord(myver[divider:]) | 136 | p1 = ord(myver[divider:]) |
136 | number = float(myver[0:divider]) | 137 | number = float(myver[0:divider]) |
137 | else: | 138 | else: |
138 | number = float(myver) | 139 | number = float(myver) |
139 | return [number,p1,p2] | 140 | return [number, p1, p2] |
140 | 141 | ||
141 | __vercmp_cache__ = {} | 142 | __vercmp_cache__ = {} |
142 | 143 | ||
143 | def vercmp_string(val1,val2): | 144 | def vercmp_string(val1, val2): |
144 | """This takes two version strings and returns an integer to tell you whether | 145 | """This takes two version strings and returns an integer to tell you whether |
145 | the versions are the same, val1>val2 or val2>val1. | 146 | the versions are the same, val1>val2 or val2>val1. |
146 | """ | 147 | """ |
@@ -148,13 +149,13 @@ def vercmp_string(val1,val2): | |||
148 | # quick short-circuit | 149 | # quick short-circuit |
149 | if val1 == val2: | 150 | if val1 == val2: |
150 | return 0 | 151 | return 0 |
151 | valkey = val1+" "+val2 | 152 | valkey = val1 + " " + val2 |
152 | 153 | ||
153 | # cache lookup | 154 | # cache lookup |
154 | try: | 155 | try: |
155 | return __vercmp_cache__[valkey] | 156 | return __vercmp_cache__[valkey] |
156 | try: | 157 | try: |
157 | return - __vercmp_cache__[val2+" "+val1] | 158 | return - __vercmp_cache__[val2 + " " + val1] |
158 | except KeyError: | 159 | except KeyError: |
159 | pass | 160 | pass |
160 | except KeyError: | 161 | except KeyError: |
@@ -175,21 +176,21 @@ def vercmp_string(val1,val2): | |||
175 | # replace '-' by '.' | 176 | # replace '-' by '.' |
176 | # FIXME: Is it needed? can val1/2 contain '-'? | 177 | # FIXME: Is it needed? can val1/2 contain '-'? |
177 | 178 | ||
178 | val1 = string.split(val1,'-') | 179 | val1 = val1.split("-") |
179 | if len(val1) == 2: | 180 | if len(val1) == 2: |
180 | val1[0] = val1[0] +"."+ val1[1] | 181 | val1[0] = val1[0] + "." + val1[1] |
181 | val2 = string.split(val2,'-') | 182 | val2 = val2.split("-") |
182 | if len(val2) == 2: | 183 | if len(val2) == 2: |
183 | val2[0] = val2[0] +"."+ val2[1] | 184 | val2[0] = val2[0] + "." + val2[1] |
184 | 185 | ||
185 | val1 = string.split(val1[0],'.') | 186 | val1 = val1[0].split('.') |
186 | val2 = string.split(val2[0],'.') | 187 | val2 = val2[0].split('.') |
187 | 188 | ||
188 | # add back decimal point so that .03 does not become "3" ! | 189 | # add back decimal point so that .03 does not become "3" ! |
189 | for x in range(1,len(val1)): | 190 | for x in range(1, len(val1)): |
190 | if val1[x][0] == '0' : | 191 | if val1[x][0] == '0' : |
191 | val1[x] = '.' + val1[x] | 192 | val1[x] = '.' + val1[x] |
192 | for x in range(1,len(val2)): | 193 | for x in range(1, len(val2)): |
193 | if val2[x][0] == '0' : | 194 | if val2[x][0] == '0' : |
194 | val2[x] = '.' + val2[x] | 195 | val2[x] = '.' + val2[x] |
195 | 196 | ||
@@ -206,10 +207,10 @@ def vercmp_string(val1,val2): | |||
206 | val2[-1] += '_' + val2_prepart | 207 | val2[-1] += '_' + val2_prepart |
207 | # The above code will extend version numbers out so they | 208 | # The above code will extend version numbers out so they |
208 | # have the same number of digits. | 209 | # have the same number of digits. |
209 | for x in range(0,len(val1)): | 210 | for x in range(0, len(val1)): |
210 | cmp1 = relparse(val1[x]) | 211 | cmp1 = relparse(val1[x]) |
211 | cmp2 = relparse(val2[x]) | 212 | cmp2 = relparse(val2[x]) |
212 | for y in range(0,3): | 213 | for y in range(0, 3): |
213 | myret = cmp1[y] - cmp2[y] | 214 | myret = cmp1[y] - cmp2[y] |
214 | if myret != 0: | 215 | if myret != 0: |
215 | __vercmp_cache__[valkey] = myret | 216 | __vercmp_cache__[valkey] = myret |
@@ -290,9 +291,9 @@ def _print_trace(body, line): | |||
290 | 291 | ||
291 | # print the environment of the method | 292 | # print the environment of the method |
292 | bb.msg.error(bb.msg.domain.Util, "Printing the environment of the function") | 293 | bb.msg.error(bb.msg.domain.Util, "Printing the environment of the function") |
293 | min_line = max(1,line-4) | 294 | min_line = max(1, line-4) |
294 | max_line = min(line+4,len(body)-1) | 295 | max_line = min(line + 4, len(body)-1) |
295 | for i in range(min_line,max_line+1): | 296 | for i in range(min_line, max_line + 1): |
296 | bb.msg.error(bb.msg.domain.Util, "\t%.4d:%s" % (i, body[i-1]) ) | 297 | bb.msg.error(bb.msg.domain.Util, "\t%.4d:%s" % (i, body[i-1]) ) |
297 | 298 | ||
298 | 299 | ||
@@ -304,7 +305,7 @@ def better_compile(text, file, realfile, mode = "exec"): | |||
304 | try: | 305 | try: |
305 | return compile(text, file, mode) | 306 | return compile(text, file, mode) |
306 | except Exception, e: | 307 | except Exception, e: |
307 | import bb,sys | 308 | import bb, sys |
308 | 309 | ||
309 | # split the text into lines again | 310 | # split the text into lines again |
310 | body = text.split('\n') | 311 | body = text.split('\n') |
@@ -323,18 +324,18 @@ def better_exec(code, context, text, realfile): | |||
323 | print the lines that are responsible for the | 324 | print the lines that are responsible for the |
324 | error. | 325 | error. |
325 | """ | 326 | """ |
326 | import bb,sys | 327 | import bb, sys |
327 | try: | 328 | try: |
328 | exec code in _context, context | 329 | exec code in _context, context |
329 | except: | 330 | except: |
330 | (t,value,tb) = sys.exc_info() | 331 | (t, value, tb) = sys.exc_info() |
331 | 332 | ||
332 | if t in [bb.parse.SkipPackage, bb.build.FuncFailed]: | 333 | if t in [bb.parse.SkipPackage, bb.build.FuncFailed]: |
333 | raise | 334 | raise |
334 | 335 | ||
335 | # print the Header of the Error Message | 336 | # print the Header of the Error Message |
336 | bb.msg.error(bb.msg.domain.Util, "Error in executing python function in: %s" % realfile) | 337 | bb.msg.error(bb.msg.domain.Util, "Error in executing python function in: %s" % realfile) |
337 | bb.msg.error(bb.msg.domain.Util, "Exception:%s Message:%s" % (t,value) ) | 338 | bb.msg.error(bb.msg.domain.Util, "Exception:%s Message:%s" % (t, value)) |
338 | 339 | ||
339 | # let us find the line number now | 340 | # let us find the line number now |
340 | while tb.tb_next: | 341 | while tb.tb_next: |
@@ -344,7 +345,7 @@ def better_exec(code, context, text, realfile): | |||
344 | line = traceback.tb_lineno(tb) | 345 | line = traceback.tb_lineno(tb) |
345 | 346 | ||
346 | _print_trace( text.split('\n'), line ) | 347 | _print_trace( text.split('\n'), line ) |
347 | 348 | ||
348 | raise | 349 | raise |
349 | 350 | ||
350 | def simple_exec(code, context): | 351 | def simple_exec(code, context): |
@@ -367,22 +368,22 @@ def lockfile(name): | |||
367 | while True: | 368 | while True: |
368 | # If we leave the lockfiles lying around there is no problem | 369 | # If we leave the lockfiles lying around there is no problem |
369 | # but we should clean up after ourselves. This gives potential | 370 | # but we should clean up after ourselves. This gives potential |
370 | # for races though. To work around this, when we acquire the lock | 371 | # for races though. To work around this, when we acquire the lock |
371 | # we check the file we locked was still the lock file on disk. | 372 | # we check the file we locked was still the lock file on disk. |
372 | # by comparing inode numbers. If they don't match or the lockfile | 373 | # by comparing inode numbers. If they don't match or the lockfile |
373 | # no longer exists, we start again. | 374 | # no longer exists, we start again. |
374 | 375 | ||
375 | # This implementation is unfair since the last person to request the | 376 | # This implementation is unfair since the last person to request the |
376 | # lock is the most likely to win it. | 377 | # lock is the most likely to win it. |
377 | 378 | ||
378 | try: | 379 | try: |
379 | lf = open(name, "a+") | 380 | lf = open(name, "a + ") |
380 | fcntl.flock(lf.fileno(), fcntl.LOCK_EX) | 381 | fcntl.flock(lf.fileno(), fcntl.LOCK_EX) |
381 | statinfo = os.fstat(lf.fileno()) | 382 | statinfo = os.fstat(lf.fileno()) |
382 | if os.path.exists(lf.name): | 383 | if os.path.exists(lf.name): |
383 | statinfo2 = os.stat(lf.name) | 384 | statinfo2 = os.stat(lf.name) |
384 | if statinfo.st_ino == statinfo2.st_ino: | 385 | if statinfo.st_ino == statinfo2.st_ino: |
385 | return lf | 386 | return lf |
386 | # File no longer exists or changed, retry | 387 | # File no longer exists or changed, retry |
387 | lf.close | 388 | lf.close |
388 | except Exception, e: | 389 | except Exception, e: |
@@ -390,7 +391,7 @@ def lockfile(name): | |||
390 | 391 | ||
391 | def unlockfile(lf): | 392 | def unlockfile(lf): |
392 | """ | 393 | """ |
393 | Unlock a file locked using lockfile() | 394 | Unlock a file locked using lockfile() |
394 | """ | 395 | """ |
395 | os.unlink(lf.name) | 396 | os.unlink(lf.name) |
396 | fcntl.flock(lf.fileno(), fcntl.LOCK_UN) | 397 | fcntl.flock(lf.fileno(), fcntl.LOCK_UN) |
@@ -406,7 +407,7 @@ def md5_file(filename): | |||
406 | except ImportError: | 407 | except ImportError: |
407 | import md5 | 408 | import md5 |
408 | m = md5.new() | 409 | m = md5.new() |
409 | 410 | ||
410 | for line in open(filename): | 411 | for line in open(filename): |
411 | m.update(line) | 412 | m.update(line) |
412 | return m.hexdigest() | 413 | return m.hexdigest() |
@@ -472,7 +473,7 @@ def filter_environment(good_vars): | |||
472 | for key in os.environ.keys(): | 473 | for key in os.environ.keys(): |
473 | if key in good_vars: | 474 | if key in good_vars: |
474 | continue | 475 | continue |
475 | 476 | ||
476 | removed_vars.append(key) | 477 | removed_vars.append(key) |
477 | os.unsetenv(key) | 478 | os.unsetenv(key) |
478 | del os.environ[key] | 479 | del os.environ[key] |
@@ -517,7 +518,7 @@ def build_environment(d): | |||
517 | def prunedir(topdir): | 518 | def prunedir(topdir): |
518 | # Delete everything reachable from the directory named in 'topdir'. | 519 | # Delete everything reachable from the directory named in 'topdir'. |
519 | # CAUTION: This is dangerous! | 520 | # CAUTION: This is dangerous! |
520 | for root, dirs, files in os.walk(topdir, topdown=False): | 521 | for root, dirs, files in os.walk(topdir, topdown = False): |
521 | for name in files: | 522 | for name in files: |
522 | os.remove(os.path.join(root, name)) | 523 | os.remove(os.path.join(root, name)) |
523 | for name in dirs: | 524 | for name in dirs: |
@@ -532,7 +533,7 @@ def prunedir(topdir): | |||
532 | # but thats possibly insane and suffixes is probably going to be small | 533 | # but thats possibly insane and suffixes is probably going to be small |
533 | # | 534 | # |
534 | def prune_suffix(var, suffixes, d): | 535 | def prune_suffix(var, suffixes, d): |
535 | # See if var ends with any of the suffixes listed and | 536 | # See if var ends with any of the suffixes listed and |
536 | # remove it if found | 537 | # remove it if found |
537 | for suffix in suffixes: | 538 | for suffix in suffixes: |
538 | if var.endswith(suffix): | 539 | if var.endswith(suffix): |
@@ -553,42 +554,42 @@ def mkdirhier(dir): | |||
553 | 554 | ||
554 | import stat | 555 | import stat |
555 | 556 | ||
556 | def movefile(src,dest,newmtime=None,sstat=None): | 557 | def movefile(src, dest, newmtime = None, sstat = None): |
557 | """Moves a file from src to dest, preserving all permissions and | 558 | """Moves a file from src to dest, preserving all permissions and |
558 | attributes; mtime will be preserved even when moving across | 559 | attributes; mtime will be preserved even when moving across |
559 | filesystems. Returns true on success and false on failure. Move is | 560 | filesystems. Returns true on success and false on failure. Move is |
560 | atomic. | 561 | atomic. |
561 | """ | 562 | """ |
562 | 563 | ||
563 | #print "movefile("+src+","+dest+","+str(newmtime)+","+str(sstat)+")" | 564 | #print "movefile(" + src + "," + dest + "," + str(newmtime) + "," + str(sstat) + ")" |
564 | try: | 565 | try: |
565 | if not sstat: | 566 | if not sstat: |
566 | sstat=os.lstat(src) | 567 | sstat = os.lstat(src) |
567 | except Exception, e: | 568 | except Exception, e: |
568 | print "movefile: Stating source file failed...", e | 569 | print "movefile: Stating source file failed...", e |
569 | return None | 570 | return None |
570 | 571 | ||
571 | destexists=1 | 572 | destexists = 1 |
572 | try: | 573 | try: |
573 | dstat=os.lstat(dest) | 574 | dstat = os.lstat(dest) |
574 | except: | 575 | except: |
575 | dstat=os.lstat(os.path.dirname(dest)) | 576 | dstat = os.lstat(os.path.dirname(dest)) |
576 | destexists=0 | 577 | destexists = 0 |
577 | 578 | ||
578 | if destexists: | 579 | if destexists: |
579 | if stat.S_ISLNK(dstat[stat.ST_MODE]): | 580 | if stat.S_ISLNK(dstat[stat.ST_MODE]): |
580 | try: | 581 | try: |
581 | os.unlink(dest) | 582 | os.unlink(dest) |
582 | destexists=0 | 583 | destexists = 0 |
583 | except Exception, e: | 584 | except Exception, e: |
584 | pass | 585 | pass |
585 | 586 | ||
586 | if stat.S_ISLNK(sstat[stat.ST_MODE]): | 587 | if stat.S_ISLNK(sstat[stat.ST_MODE]): |
587 | try: | 588 | try: |
588 | target=os.readlink(src) | 589 | target = os.readlink(src) |
589 | if destexists and not stat.S_ISDIR(dstat[stat.ST_MODE]): | 590 | if destexists and not stat.S_ISDIR(dstat[stat.ST_MODE]): |
590 | os.unlink(dest) | 591 | os.unlink(dest) |
591 | os.symlink(target,dest) | 592 | os.symlink(target, dest) |
592 | #os.lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID]) | 593 | #os.lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID]) |
593 | os.unlink(src) | 594 | os.unlink(src) |
594 | return os.lstat(dest) | 595 | return os.lstat(dest) |
@@ -596,38 +597,38 @@ def movefile(src,dest,newmtime=None,sstat=None): | |||
596 | print "movefile: failed to properly create symlink:", dest, "->", target, e | 597 | print "movefile: failed to properly create symlink:", dest, "->", target, e |
597 | return None | 598 | return None |
598 | 599 | ||
599 | renamefailed=1 | 600 | renamefailed = 1 |
600 | if sstat[stat.ST_DEV]==dstat[stat.ST_DEV]: | 601 | if sstat[stat.ST_DEV] == dstat[stat.ST_DEV]: |
601 | try: | 602 | try: |
602 | ret=os.rename(src,dest) | 603 | ret = os.rename(src, dest) |
603 | renamefailed=0 | 604 | renamefailed = 0 |
604 | except Exception, e: | 605 | except Exception, e: |
605 | import errno | 606 | import errno |
606 | if e[0]!=errno.EXDEV: | 607 | if e[0] != errno.EXDEV: |
607 | # Some random error. | 608 | # Some random error. |
608 | print "movefile: Failed to move", src, "to", dest, e | 609 | print "movefile: Failed to move", src, "to", dest, e |
609 | return None | 610 | return None |
610 | # Invalid cross-device-link 'bind' mounted or actually Cross-Device | 611 | # Invalid cross-device-link 'bind' mounted or actually Cross-Device |
611 | 612 | ||
612 | if renamefailed: | 613 | if renamefailed: |
613 | didcopy=0 | 614 | didcopy = 0 |
614 | if stat.S_ISREG(sstat[stat.ST_MODE]): | 615 | if stat.S_ISREG(sstat[stat.ST_MODE]): |
615 | try: # For safety copy then move it over. | 616 | try: # For safety copy then move it over. |
616 | shutil.copyfile(src,dest+"#new") | 617 | shutil.copyfile(src, dest + "#new") |
617 | os.rename(dest+"#new",dest) | 618 | os.rename(dest + "#new", dest) |
618 | didcopy=1 | 619 | didcopy = 1 |
619 | except Exception, e: | 620 | except Exception, e: |
620 | print 'movefile: copy', src, '->', dest, 'failed.', e | 621 | print 'movefile: copy', src, '->', dest, 'failed.', e |
621 | return None | 622 | return None |
622 | else: | 623 | else: |
623 | #we don't yet handle special, so we need to fall back to /bin/mv | 624 | #we don't yet handle special, so we need to fall back to /bin/mv |
624 | a=getstatusoutput("/bin/mv -f "+"'"+src+"' '"+dest+"'") | 625 | a = getstatusoutput("/bin/mv -f " + "'" + src + "' '" + dest + "'") |
625 | if a[0]!=0: | 626 | if a[0] != 0: |
626 | print "movefile: Failed to move special file:" + src + "' to '" + dest + "'", a | 627 | print "movefile: Failed to move special file:" + src + "' to '" + dest + "'", a |
627 | return None # failure | 628 | return None # failure |
628 | try: | 629 | try: |
629 | if didcopy: | 630 | if didcopy: |
630 | os.lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID]) | 631 | os.lchown(dest, sstat[stat.ST_UID], sstat[stat.ST_GID]) |
631 | os.chmod(dest, stat.S_IMODE(sstat[stat.ST_MODE])) # Sticky is reset on chown | 632 | os.chmod(dest, stat.S_IMODE(sstat[stat.ST_MODE])) # Sticky is reset on chown |
632 | os.unlink(src) | 633 | os.unlink(src) |
633 | except Exception, e: | 634 | except Exception, e: |
@@ -635,47 +636,47 @@ def movefile(src,dest,newmtime=None,sstat=None): | |||
635 | return None | 636 | return None |
636 | 637 | ||
637 | if newmtime: | 638 | if newmtime: |
638 | os.utime(dest,(newmtime,newmtime)) | 639 | os.utime(dest, (newmtime, newmtime)) |
639 | else: | 640 | else: |
640 | os.utime(dest, (sstat[stat.ST_ATIME], sstat[stat.ST_MTIME])) | 641 | os.utime(dest, (sstat[stat.ST_ATIME], sstat[stat.ST_MTIME])) |
641 | newmtime=sstat[stat.ST_MTIME] | 642 | newmtime = sstat[stat.ST_MTIME] |
642 | return newmtime | 643 | return newmtime |
643 | 644 | ||
644 | def copyfile(src,dest,newmtime=None,sstat=None): | 645 | def copyfile(src, dest, newmtime = None, sstat = None): |
645 | """ | 646 | """ |
646 | Copies a file from src to dest, preserving all permissions and | 647 | Copies a file from src to dest, preserving all permissions and |
647 | attributes; mtime will be preserved even when moving across | 648 | attributes; mtime will be preserved even when moving across |
648 | filesystems. Returns true on success and false on failure. | 649 | filesystems. Returns true on success and false on failure. |
649 | """ | 650 | """ |
650 | #print "copyfile("+src+","+dest+","+str(newmtime)+","+str(sstat)+")" | 651 | #print "copyfile(" + src + "," + dest + "," + str(newmtime) + "," + str(sstat) + ")" |
651 | try: | 652 | try: |
652 | if not sstat: | 653 | if not sstat: |
653 | sstat=os.lstat(src) | 654 | sstat = os.lstat(src) |
654 | except Exception, e: | 655 | except Exception, e: |
655 | print "copyfile: Stating source file failed...", e | 656 | print "copyfile: Stating source file failed...", e |
656 | return False | 657 | return False |
657 | 658 | ||
658 | destexists=1 | 659 | destexists = 1 |
659 | try: | 660 | try: |
660 | dstat=os.lstat(dest) | 661 | dstat = os.lstat(dest) |
661 | except: | 662 | except: |
662 | dstat=os.lstat(os.path.dirname(dest)) | 663 | dstat = os.lstat(os.path.dirname(dest)) |
663 | destexists=0 | 664 | destexists = 0 |
664 | 665 | ||
665 | if destexists: | 666 | if destexists: |
666 | if stat.S_ISLNK(dstat[stat.ST_MODE]): | 667 | if stat.S_ISLNK(dstat[stat.ST_MODE]): |
667 | try: | 668 | try: |
668 | os.unlink(dest) | 669 | os.unlink(dest) |
669 | destexists=0 | 670 | destexists = 0 |
670 | except Exception, e: | 671 | except Exception, e: |
671 | pass | 672 | pass |
672 | 673 | ||
673 | if stat.S_ISLNK(sstat[stat.ST_MODE]): | 674 | if stat.S_ISLNK(sstat[stat.ST_MODE]): |
674 | try: | 675 | try: |
675 | target=os.readlink(src) | 676 | target = os.readlink(src) |
676 | if destexists and not stat.S_ISDIR(dstat[stat.ST_MODE]): | 677 | if destexists and not stat.S_ISDIR(dstat[stat.ST_MODE]): |
677 | os.unlink(dest) | 678 | os.unlink(dest) |
678 | os.symlink(target,dest) | 679 | os.symlink(target, dest) |
679 | #os.lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID]) | 680 | #os.lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID]) |
680 | return os.lstat(dest) | 681 | return os.lstat(dest) |
681 | except Exception, e: | 682 | except Exception, e: |
@@ -683,30 +684,30 @@ def copyfile(src,dest,newmtime=None,sstat=None): | |||
683 | return False | 684 | return False |
684 | 685 | ||
685 | if stat.S_ISREG(sstat[stat.ST_MODE]): | 686 | if stat.S_ISREG(sstat[stat.ST_MODE]): |
686 | try: # For safety copy then move it over. | 687 | try: # For safety copy then move it over. |
687 | shutil.copyfile(src,dest+"#new") | 688 | shutil.copyfile(src, dest + "#new") |
688 | os.rename(dest+"#new",dest) | 689 | os.rename(dest + "#new", dest) |
689 | except Exception, e: | 690 | except Exception, e: |
690 | print 'copyfile: copy', src, '->', dest, 'failed.', e | 691 | print 'copyfile: copy', src, '->', dest, 'failed.', e |
691 | return False | 692 | return False |
692 | else: | 693 | else: |
693 | #we don't yet handle special, so we need to fall back to /bin/mv | 694 | #we don't yet handle special, so we need to fall back to /bin/mv |
694 | a=getstatusoutput("/bin/cp -f "+"'"+src+"' '"+dest+"'") | 695 | a = getstatusoutput("/bin/cp -f " + "'" + src + "' '" + dest + "'") |
695 | if a[0]!=0: | 696 | if a[0] != 0: |
696 | print "copyfile: Failed to copy special file:" + src + "' to '" + dest + "'", a | 697 | print "copyfile: Failed to copy special file:" + src + "' to '" + dest + "'", a |
697 | return False # failure | 698 | return False # failure |
698 | try: | 699 | try: |
699 | os.lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID]) | 700 | os.lchown(dest, sstat[stat.ST_UID], sstat[stat.ST_GID]) |
700 | os.chmod(dest, stat.S_IMODE(sstat[stat.ST_MODE])) # Sticky is reset on chown | 701 | os.chmod(dest, stat.S_IMODE(sstat[stat.ST_MODE])) # Sticky is reset on chown |
701 | except Exception, e: | 702 | except Exception, e: |
702 | print "copyfile: Failed to chown/chmod/unlink", dest, e | 703 | print "copyfile: Failed to chown/chmod/unlink", dest, e |
703 | return False | 704 | return False |
704 | 705 | ||
705 | if newmtime: | 706 | if newmtime: |
706 | os.utime(dest,(newmtime,newmtime)) | 707 | os.utime(dest, (newmtime, newmtime)) |
707 | else: | 708 | else: |
708 | os.utime(dest, (sstat[stat.ST_ATIME], sstat[stat.ST_MTIME])) | 709 | os.utime(dest, (sstat[stat.ST_ATIME], sstat[stat.ST_MTIME])) |
709 | newmtime=sstat[stat.ST_MTIME] | 710 | newmtime = sstat[stat.ST_MTIME] |
710 | return newmtime | 711 | return newmtime |
711 | 712 | ||
712 | def which(path, item, direction = 0): | 713 | def which(path, item, direction = 0): |