diff --git a/py/execnet/rsync.py b/py/execnet/rsync.py index 8e8b00e20..f9638a6df 100644 --- a/py/execnet/rsync.py +++ b/py/execnet/rsync.py @@ -85,26 +85,33 @@ class RSync(object): elif command == "send": modified_rel_path, checksum = data modifiedpath = os.path.join(self.sourcedir, *modified_rel_path) - f = open(modifiedpath, 'rb') - data = f.read() + try: + f = open(modifiedpath, 'rb') + data = f.read() + except IOError: + data = None # provide info to progress callback function modified_rel_path = "/".join(modified_rel_path) - self.paths[modified_rel_path] = len(data) + if data is not None: + self.paths[modified_rel_path] = len(data) + else: + self.paths[modified_rel_path] = 0 if channel not in self.to_send: self.to_send[channel] = [] self.to_send[channel].append(modified_rel_path) - f.close() - if checksum is not None and checksum == md5.md5(data).digest(): - data = None # not really modified - else: - # ! there is a reason for the interning: - # sharing multiple copies of the file's data - data = intern(data) - print '%s <= %s' % ( - channel.gateway._getremoteaddress(), - modified_rel_path) + if data is not None: + f.close() + if checksum is not None and checksum == md5.md5(data).digest(): + data = None # not really modified + else: + # ! there is a reason for the interning: + # sharing multiple copies of the file's data + data = intern(data) + print '%s <= %s' % ( + channel.gateway._getremoteaddress(), + modified_rel_path) channel.send(data) del data else: @@ -118,7 +125,11 @@ class RSync(object): self.links.append(("link", basename, linkpoint)) def _send_directory_structure(self, path): - st = os.lstat(path) + try: + st = os.lstat(path) + except OSError: + self._broadcast((0, 0)) + return if stat.S_ISREG(st.st_mode): # regular file: send a timestamp/size pair self._broadcast((st.st_mtime, st.st_size)) diff --git a/py/execnet/rsync_remote.py b/py/execnet/rsync_remote.py index bb770ebc7..9b5a15571 100644 --- a/py/execnet/rsync_remote.py +++ b/py/execnet/rsync_remote.py @@ -65,7 +65,10 @@ def f(): f = open(path, 'wb') f.write(data) f.close() - os.utime(path, (time, time)) + try: + os.utime(path, (time, time)) + except OSError: + pass del data channel.send(("links", None)) diff --git a/py/execnet/testing/test_rsync.py b/py/execnet/testing/test_rsync.py index 7b01c3ae3..cba7e76fc 100644 --- a/py/execnet/testing/test_rsync.py +++ b/py/execnet/testing/test_rsync.py @@ -78,3 +78,24 @@ def test_callback(): assert total == {("list", 110):True, ("ack", 100):True, ("ack", 10):True} +def test_file_disappearing(): + base = py.test.ensuretemp("file_disappearing") + dest = base.join("dest") + source = base.join("source") + source.ensure("ex").write("a" * 100) + source.ensure("ex2").write("a" * 100) + + class DRsync(RSync): + def filter(self, x): + if x.endswith("ex2"): + self.x = 1 + source.join("ex2").remove() + return True + + rsync = DRsync() + rsync.add_target(gw, dest) + rsync.send(source) + assert rsync.x == 1 + assert len(dest.listdir()) == 1 + assert len(source.listdir()) == 1 +