]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blobdiff - src/allmydata/frontends/magic_folder.py
Merge branch '2438.magic-folder-stable.9' of https://github.com/tahoe-lafs/tahoe...
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / frontends / magic_folder.py
index 62e6988d1ef96aab8e4390750a80a8b6a2f8fa83..bd226156d23b81c576b988c32d1babe63c3d3512 100644 (file)
@@ -56,7 +56,7 @@ def is_new_file(pathinfo, db_entry):
 class MagicFolder(service.MultiService):
     name = 'magic-folder'
 
-    def __init__(self, client, upload_dircap, collective_dircap, local_path_u, dbfile,
+    def __init__(self, client, upload_dircap, collective_dircap, local_path_u, dbfile, umask,
                  pending_delay=1.0, clock=None):
         precondition_abspath(local_path_u)
 
@@ -77,7 +77,7 @@ class MagicFolder(service.MultiService):
 
         self.uploader = Uploader(client, local_path_u, db, upload_dirnode, pending_delay, clock, immediate)
         self.downloader = Downloader(client, local_path_u, db, collective_dirnode,
-                                     upload_dirnode.get_readonly_uri(), clock, self.uploader.is_pending)
+                                     upload_dirnode.get_readonly_uri(), clock, self.uploader.is_pending, umask)
 
     def startService(self):
         # TODO: why is this being called more than once?
@@ -484,10 +484,18 @@ class WriteFileMixin(object):
 
         # ensure parent directory exists
         head, tail = os.path.split(abspath_u)
-        mode = 0777 # XXX
-        fileutil.make_dirs(head, mode)
 
-        fileutil.write(replacement_path_u, file_contents)
+        old_mask = os.umask(self._umask)
+        try:
+            fileutil.make_dirs(head, (~ self._umask) & 0777)
+            fileutil.write(replacement_path_u, file_contents)
+        finally:
+            os.umask(old_mask)
+
+        # FUDGE_SECONDS is used to determine if another process
+        # has written to the same file concurrently. This is described
+        # in the Earth Dragon section of our design document:
+        # docs/proposed/magic-folder/remote-to-local-sync.rst
         os.utime(replacement_path_u, (now, now - self.FUDGE_SECONDS))
         if is_conflict:
             print "0x00 ------------ <><> is conflict; calling _rename_conflicted_file... %r %r" % (abspath_u, replacement_path_u)
@@ -525,7 +533,7 @@ class Downloader(QueueMixin, WriteFileMixin):
     REMOTE_SCAN_INTERVAL = 3  # facilitates tests
 
     def __init__(self, client, local_path_u, db, collective_dirnode,
-                 upload_readonly_dircap, clock, is_upload_pending):
+                 upload_readonly_dircap, clock, is_upload_pending, umask):
         QueueMixin.__init__(self, client, local_path_u, db, 'downloader', clock)
 
         if not IDirectoryNode.providedBy(collective_dirnode):
@@ -538,8 +546,7 @@ class Downloader(QueueMixin, WriteFileMixin):
         self._collective_dirnode = collective_dirnode
         self._upload_readonly_dircap = upload_readonly_dircap
         self._is_upload_pending = is_upload_pending
-
-        self._turn_delay = self.REMOTE_SCAN_INTERVAL
+        self._umask = umask
 
     def start_scanning(self):
         self._log("start_scanning")
@@ -609,6 +616,10 @@ class Downloader(QueueMixin, WriteFileMixin):
             node = None
             for success, result in deferredList:
                 if success:
+                    if 'version' not in result[1]:
+                        self._log("invalid remote metadata detected")
+                        continue
+
                     if result[1]['version'] > max_version:
                         node, metadata = result
                         max_version = result[1]['version']
@@ -626,10 +637,15 @@ class Downloader(QueueMixin, WriteFileMixin):
 
                 file_node, metadata = listing_map[encoded_relpath_u]
                 local_version = self._get_local_latest(relpath_u)
-                remote_version = metadata.get('version', None)
+
+                if 'version' not in metadata:
+                    self._log("invalid remote metadata detected for %r" % (relpath_u,))
+                    continue
+
+                remote_version = metadata['version']
                 self._log("%r has local version %r, remote version %r" % (relpath_u, local_version, remote_version))
 
-                if local_version is None or remote_version is None or local_version < remote_version:
+                if local_version is None or local_version < remote_version:
                     self._log("%r added to download queue" % (relpath_u,))
                     if scan_batch.has_key(relpath_u):
                         scan_batch[relpath_u] += [(file_node, metadata)]
@@ -676,7 +692,7 @@ class Downloader(QueueMixin, WriteFileMixin):
         return d
 
     def _when_queue_is_empty(self):
-        d = task.deferLater(self._clock, self._turn_delay, self._scan_remote_collective)
+        d = task.deferLater(self._clock, self.REMOTE_SCAN_INTERVAL, self._scan_remote_collective)
         d.addBoth(self._logcb, "after _scan_remote_collective 1")
         d.addCallback(lambda ign: self._turn_deque())
         return d