23 |
import errno |
import errno |
24 |
import Globals, metadata, rorpiter, TempFile, Hardlink, robust, increment, \ |
import Globals, metadata, rorpiter, TempFile, Hardlink, robust, increment, \ |
25 |
rpath, static, log, selection, Time, Rdiff, statistics, iterfile, \ |
rpath, static, log, selection, Time, Rdiff, statistics, iterfile, \ |
26 |
hash |
hash, longname |
27 |
|
|
28 |
def Mirror(src_rpath, dest_rpath): |
def Mirror(src_rpath, dest_rpath): |
29 |
"""Turn dest_rpath into a copy of src_rpath""" |
"""Turn dest_rpath into a copy of src_rpath""" |
189 |
elif dest_rorp: |
elif dest_rorp: |
190 |
dest_sig = dest_rorp.getRORPath() |
dest_sig = dest_rorp.getRORPath() |
191 |
if dest_rorp.isreg(): |
if dest_rorp.isreg(): |
192 |
sig_fp = cls.get_one_sig_fp(dest_base_rpath.new_index(index)) |
dest_rp = longname.get_mirror_rp(dest_base_rpath, dest_rorp) |
193 |
|
sig_fp = cls.get_one_sig_fp(dest_rp) |
194 |
if sig_fp is None: return None |
if sig_fp is None: return None |
195 |
dest_sig.setfile(sig_fp) |
dest_sig.setfile(sig_fp) |
196 |
else: dest_sig = rpath.RORPath(index) |
else: dest_sig = rpath.RORPath(index) |
197 |
return dest_sig |
return dest_sig |
198 |
|
|
199 |
def get_one_sig_fp(cls, dest_rp): |
def get_one_sig_fp(cls, dest_rp): |
200 |
"""Return a signature fp of given index, corresponding to reg file""" |
"""Return a signature fp of given index, corresponding to reg file""" |
468 |
self.statfileobj = (statistics.get_active_statfileobj() or |
self.statfileobj = (statistics.get_active_statfileobj() or |
469 |
statistics.StatFileObj()) |
statistics.StatFileObj()) |
470 |
self.dir_replacement, self.dir_update = None, None |
self.dir_replacement, self.dir_update = None, None |
|
self.cached_rp = None |
|
471 |
self.CCPP = CCPP |
self.CCPP = CCPP |
472 |
self.error_handler = robust.get_error_handler("UpdateError") |
self.error_handler = robust.get_error_handler("UpdateError") |
473 |
|
|
|
def get_rp_from_root(self, index): |
|
|
"""Return RPath by adding index to self.basis_root_rp""" |
|
|
if not self.cached_rp or self.cached_rp.index != index: |
|
|
self.cached_rp = self.basis_root_rp.new_index(index) |
|
|
return self.cached_rp |
|
|
|
|
|
def check_long_name(self, func, *args): |
|
|
"""Execute function, checking for ENAMETOOLONG error""" |
|
|
try: result = func(*args) |
|
|
except OSError, exc: |
|
|
if (errno.errorcode.has_key(exc[0]) and |
|
|
errno.errorcode[exc[0]] == 'ENAMETOOLONG'): |
|
|
self.error_handler(exc, args[0]) |
|
|
return None |
|
|
else: raise |
|
|
return result |
|
|
|
|
474 |
def can_fast_process(self, index, diff_rorp): |
def can_fast_process(self, index, diff_rorp): |
475 |
"""True if diff_rorp and mirror are not directories""" |
"""True if diff_rorp and mirror are not directories""" |
476 |
rp = self.check_long_name(self.get_rp_from_root, index) |
mirror_rorp = self.CCPP.get_mirror_rorp(index) |
477 |
# filename too long error qualifies (hack) |
return not (diff_rorp.isdir() or (mirror_rorp and mirror_rorp.isdir())) |
|
return not rp or (not diff_rorp.isdir() and not rp.isdir()) |
|
478 |
|
|
479 |
def fast_process(self, index, diff_rorp): |
def fast_process(self, index, diff_rorp): |
480 |
"""Patch base_rp with diff_rorp (case where neither is directory)""" |
"""Patch base_rp with diff_rorp (case where neither is directory)""" |
481 |
rp = self.check_long_name(self.get_rp_from_root, index) |
mirror_rp, discard = longname.get_mirror_inc_rps( |
482 |
if not rp: return |
self.CCPP.get_rorps(index), self.basis_root_rp) |
483 |
tf = TempFile.new(rp) |
assert not mirror_rp.isdir(), mirror_rp |
484 |
if self.patch_to_temp(rp, diff_rorp, tf): |
tf = TempFile.new(mirror_rp) |
485 |
|
if self.patch_to_temp(mirror_rp, diff_rorp, tf): |
486 |
if tf.lstat(): |
if tf.lstat(): |
487 |
rpath.rename(tf, rp) |
rpath.rename(tf, mirror_rp) |
488 |
self.CCPP.flag_success(index) |
self.CCPP.flag_success(index) |
489 |
elif rp.lstat(): |
elif mirror_rp and mirror_rp.lstat(): |
490 |
rp.delete() |
mirror_rp.delete() |
491 |
self.CCPP.flag_deleted(index) |
self.CCPP.flag_deleted(index) |
492 |
else: |
else: |
493 |
tf.setdata() |
tf.setdata() |
566 |
|
|
567 |
def start_process(self, index, diff_rorp): |
def start_process(self, index, diff_rorp): |
568 |
"""Start processing directory - record information for later""" |
"""Start processing directory - record information for later""" |
569 |
base_rp = self.base_rp = self.get_rp_from_root(index) |
self.base_rp, discard = longname.get_mirror_inc_rps( |
570 |
assert diff_rorp.isdir() or base_rp.isdir() or not base_rp.index |
self.CCPP.get_rorps(index), self.basis_root_rp) |
571 |
if diff_rorp.isdir(): self.prepare_dir(diff_rorp, base_rp) |
if diff_rorp.isdir(): self.prepare_dir(diff_rorp, self.base_rp) |
572 |
elif self.set_dir_replacement(diff_rorp, base_rp): |
elif self.set_dir_replacement(diff_rorp, self.base_rp): |
573 |
self.CCPP.flag_success(index) |
if diff_rorp.lstat(): self.CCPP.flag_success(index) |
574 |
|
else: self.CCPP.flag_deleted(index) |
575 |
|
|
576 |
def set_dir_replacement(self, diff_rorp, base_rp): |
def set_dir_replacement(self, diff_rorp, base_rp): |
577 |
"""Set self.dir_replacement, which holds data until done with dir |
"""Set self.dir_replacement, which holds data until done with dir |
591 |
else: return 1 |
else: return 1 |
592 |
|
|
593 |
def prepare_dir(self, diff_rorp, base_rp): |
def prepare_dir(self, diff_rorp, base_rp): |
594 |
"""Prepare base_rp to turn into a directory""" |
"""Prepare base_rp to be a directory""" |
595 |
self.dir_update = diff_rorp.getRORPath() # make copy in case changes |
self.dir_update = diff_rorp.getRORPath() # make copy in case changes |
596 |
if not base_rp.isdir(): |
if not base_rp.isdir(): |
597 |
if base_rp.lstat(): base_rp.delete() |
if base_rp.lstat(): self.base_rp.delete() |
598 |
|
base_rp.setdata() |
599 |
base_rp.mkdir() |
base_rp.mkdir() |
600 |
self.CCPP.flag_success(diff_rorp.index) |
self.CCPP.flag_success(diff_rorp.index) |
601 |
else: # maybe no change, so query CCPP before tagging success |
else: # maybe no change, so query CCPP before tagging success |
607 |
if self.dir_update: |
if self.dir_update: |
608 |
assert self.base_rp.isdir() |
assert self.base_rp.isdir() |
609 |
rpath.copy_attribs(self.dir_update, self.base_rp) |
rpath.copy_attribs(self.dir_update, self.base_rp) |
610 |
else: |
elif self.dir_replacement: |
|
assert self.dir_replacement |
|
611 |
self.base_rp.rmdir() |
self.base_rp.rmdir() |
612 |
if self.dir_replacement.lstat(): |
if self.dir_replacement.lstat(): |
613 |
rpath.rename(self.dir_replacement, self.base_rp) |
rpath.rename(self.dir_replacement, self.base_rp) |
621 |
""" |
""" |
622 |
def __init__(self, basis_root_rp, inc_root_rp, rorp_cache): |
def __init__(self, basis_root_rp, inc_root_rp, rorp_cache): |
623 |
self.inc_root_rp = inc_root_rp |
self.inc_root_rp = inc_root_rp |
|
self.cached_incrp = None |
|
624 |
PatchITRB.__init__(self, basis_root_rp, rorp_cache) |
PatchITRB.__init__(self, basis_root_rp, rorp_cache) |
625 |
|
|
|
def get_incrp(self, index): |
|
|
"""Return inc RPath by adding index to self.basis_root_rp""" |
|
|
if not self.cached_incrp or self.cached_incrp.index != index: |
|
|
self.cached_incrp = self.inc_root_rp.new_index(index) |
|
|
return self.cached_incrp |
|
|
|
|
626 |
def fast_process(self, index, diff_rorp): |
def fast_process(self, index, diff_rorp): |
627 |
"""Patch base_rp with diff_rorp and write increment (neither is dir)""" |
"""Patch base_rp with diff_rorp and write increment (neither is dir)""" |
628 |
rp = self.check_long_name(self.get_rp_from_root, index) |
mirror_rp, inc_prefix = longname.get_mirror_inc_rps( |
629 |
if not rp: return |
self.CCPP.get_rorps(index), self.basis_root_rp, self.inc_root_rp) |
630 |
tf = TempFile.new(rp) |
tf = TempFile.new(mirror_rp) |
631 |
if self.patch_to_temp(rp, diff_rorp, tf): |
if self.patch_to_temp(mirror_rp, diff_rorp, tf): |
632 |
inc = self.check_long_name(increment.Increment, |
inc = increment.Increment(tf, mirror_rp, inc_prefix) |
|
tf, rp, self.get_incrp(index)) |
|
633 |
if inc is not None: |
if inc is not None: |
634 |
self.CCPP.set_inc(index, inc) |
self.CCPP.set_inc(index, inc) |
635 |
if inc.isreg(): |
if inc.isreg(): |
636 |
inc.fsync_with_dir() # Write inc before rp changed |
inc.fsync_with_dir() # Write inc before rp changed |
637 |
if tf.lstat(): |
if tf.lstat(): |
638 |
rpath.rename(tf, rp) |
rpath.rename(tf, mirror_rp) |
639 |
self.CCPP.flag_success(index) |
self.CCPP.flag_success(index) |
640 |
elif rp.lstat(): |
elif mirror_rp.lstat(): |
641 |
rp.delete() |
mirror_rp.delete() |
642 |
self.CCPP.flag_deleted(index) |
self.CCPP.flag_deleted(index) |
643 |
return # normal return, otherwise error occurred |
return # normal return, otherwise error occurred |
644 |
tf.setdata() |
tf.setdata() |
646 |
|
|
647 |
def start_process(self, index, diff_rorp): |
def start_process(self, index, diff_rorp): |
648 |
"""Start processing directory""" |
"""Start processing directory""" |
649 |
base_rp = self.base_rp = self.get_rp_from_root(index) |
self.base_rp, inc_prefix = longname.get_mirror_inc_rps( |
650 |
assert diff_rorp.isdir() or base_rp.isdir() |
self.CCPP.get_rorps(index), self.basis_root_rp, self.inc_root_rp) |
651 |
|
self.base_rp.setdata() |
652 |
|
assert diff_rorp.isdir() or self.base_rp.isdir() |
653 |
if diff_rorp.isdir(): |
if diff_rorp.isdir(): |
654 |
inc = self.check_long_name(increment.Increment, |
inc = increment.Increment(diff_rorp, self.base_rp, inc_prefix) |
|
diff_rorp, base_rp, self.get_incrp(index)) |
|
655 |
if inc and inc.isreg(): |
if inc and inc.isreg(): |
656 |
inc.fsync_with_dir() # must write inc before rp changed |
inc.fsync_with_dir() # must write inc before rp changed |
657 |
self.prepare_dir(diff_rorp, base_rp) |
self.base_rp.setdata() # in case written by increment above |
658 |
elif self.set_dir_replacement(diff_rorp, base_rp): |
self.prepare_dir(diff_rorp, self.base_rp) |
659 |
inc = self.check_long_name(increment.Increment, |
elif self.set_dir_replacement(diff_rorp, self.base_rp): |
660 |
self.dir_replacement, base_rp, self.get_incrp(index)) |
inc = increment.Increment(self.dir_replacement, self.base_rp, |
661 |
|
inc_prefix) |
662 |
if inc: |
if inc: |
663 |
self.CCPP.set_inc(index, inc) |
self.CCPP.set_inc(index, inc) |
664 |
self.CCPP.flag_success(index) |
self.CCPP.flag_success(index) |