diff options
| -rw-r--r-- | src/leap/soledad/client/_db/blobs/sql.py | 7 | ||||
| -rw-r--r-- | src/leap/soledad/client/_db/blobs/sync.py | 7 | ||||
| -rw-r--r-- | tests/server/test_blobs_server.py | 19 | 
3 files changed, 33 insertions, 0 deletions
| diff --git a/src/leap/soledad/client/_db/blobs/sql.py b/src/leap/soledad/client/_db/blobs/sql.py index c5b0b64b..5337ab87 100644 --- a/src/leap/soledad/client/_db/blobs/sql.py +++ b/src/leap/soledad/client/_db/blobs/sql.py @@ -190,6 +190,13 @@ class SQLiteBlobBackend(object):          query = 'DELETE FROM blobs WHERE blob_id = ? AND namespace = ?'          return self.dbpool.runQuery(query, (blob_id, namespace,)) +    def batch_delete(self, blob_id_list, namespace=''): +        query = 'DELETE FROM blobs WHERE blob_id IN ' +        size = len(blob_id_list) +        query += ('(%s)' % ', '.join(['?' for _ in range(size)])) +        values = tuple(blob_id_list) +        return self.dbpool.runQuery(query, values) +  def _init_tables(conn):      # unified init for running under the same lock diff --git a/src/leap/soledad/client/_db/blobs/sync.py b/src/leap/soledad/client/_db/blobs/sync.py index bfdc5fbe..bdfbb983 100644 --- a/src/leap/soledad/client/_db/blobs/sync.py +++ b/src/leap/soledad/client/_db/blobs/sync.py @@ -73,6 +73,12 @@ class BlobsSynchronizer(object):              namespace=namespace)      @defer.inlineCallbacks +    def _apply_deletions_from_server(self, namespace=''): +        remote_deletions = self.remote_list(namespace=namespace, deleted=True) +        remote_deletions = yield remote_deletions +        yield self.local.batch_delete(remote_deletions) + +    @defer.inlineCallbacks      def send_missing(self, namespace=''):          """          Compare local and remote blobs and send what's missing in server. @@ -131,6 +137,7 @@ class BlobsSynchronizer(object):      @defer.inlineCallbacks      def sync(self, namespace=''):          try: +            yield self._apply_deletions_from_server(namespace)              yield self.refresh_sync_status_from_server(namespace)              yield self.fetch_missing(namespace)              yield self.send_missing(namespace) diff --git a/tests/server/test_blobs_server.py b/tests/server/test_blobs_server.py index ba4a03d7..4e7b4a3b 100644 --- a/tests/server/test_blobs_server.py +++ b/tests/server/test_blobs_server.py @@ -37,6 +37,7 @@ from leap.soledad.client._db.blobs import SyncStatus  from leap.soledad.client._db.blobs import RetriableTransferError  from leap.soledad.client._db.blobs import MaximumRetriesError  from leap.soledad.client._db import blobs as client_blobs +from leap.soledad.client._document import BlobDoc  def sleep(x): @@ -324,6 +325,24 @@ class BlobServerTestCase(unittest.TestCase):      @defer.inlineCallbacks      @pytest.mark.usefixtures("method_tmpdir") +    def test_refresh_deletions_from_server(self): +        manager = BlobManager(self.tempdir, self.uri, self.secret, +                              self.secret, uuid4().hex) +        self.addCleanup(manager.close) +        blob_id, content = 'delete_me', 'content' +        blob_id2 = 'dont_delete_me' +        doc1 = BlobDoc(BytesIO(content), blob_id) +        doc2 = BlobDoc(BytesIO(content), blob_id2) +        yield manager.put(doc1, len(content)) +        yield manager.put(doc2, len(content)) +        yield manager._delete_from_remote(blob_id)  # remote only deletion +        self.assertTrue((yield manager.local.exists(blob_id))) +        yield manager.sync() +        self.assertFalse((yield manager.local.exists(blob_id))) +        self.assertTrue((yield manager.local.exists(blob_id2))) + +    @defer.inlineCallbacks +    @pytest.mark.usefixtures("method_tmpdir")      def test_download_corrupted_tag_marks_blob_as_failed(self):          user_id = uuid4().hex          manager = BlobManager(self.tempdir, self.uri, self.secret, | 
