diff options
-rw-r--r-- | __init__.py | 5 | ||||
-rw-r--r-- | backends/couch.py | 53 | ||||
-rw-r--r-- | backends/objectstore.py | 9 |
3 files changed, 62 insertions, 5 deletions
diff --git a/__init__.py b/__init__.py index c83627f0..2ed1a369 100644 --- a/__init__.py +++ b/__init__.py @@ -8,7 +8,6 @@ import random import hmac from leap.soledad.backends import sqlcipher from leap.soledad.util import GPGWrapper -import util class Soledad(object): @@ -28,7 +27,7 @@ class Soledad(object): os.makedirs(self.PREFIX) if not gpghome: gpghome = self.GNUPG_HOME - self._gpg = util.GPGWrapper(gpghome=gpghome) + self._gpg = GPGWrapper(gpghome=gpghome) # load/generate OpenPGP keypair if not self._has_openpgp_keypair(): self._gen_openpgp_keypair() @@ -64,7 +63,7 @@ class Soledad(object): try: with open(self.SECRET_PATH) as f: self._secret = str(self._gpg.decrypt(f.read())) - except IOError as e: + except IOError: raise IOError('Failed to open secret file %s.' % self.SECRET_PATH) def _gen_secret(self): diff --git a/backends/couch.py b/backends/couch.py index c8dadfa8..56b12574 100644 --- a/backends/couch.py +++ b/backends/couch.py @@ -1,10 +1,16 @@ +# general imports import uuid from base64 import b64encode, b64decode +import re +# u1db from u1db import errors from u1db.sync import LocalSyncTarget from u1db.backends.inmemory import InMemoryIndex +from u1db.remote.server_state import ServerState +# couchdb from couchdb.client import Server, Document as CouchDocument from couchdb.http import ResourceNotFound +# leap from leap.soledad.backends.objectstore import ObjectStore from leap.soledad.backends.leap_backend import LeapDocument @@ -14,9 +20,29 @@ except ImportError: import json # noqa +class InvalidURLError(Exception): + pass + + class CouchDatabase(ObjectStore): """A U1DB implementation that uses Couch as its persistence layer.""" + @classmethod + def open_database(cls, url, create): + # get database from url + m = re.match('(.*)/([^/]+)$', url) + if not m: + raise InvalidURLError + url = m.group(1) + dbname = m.group(2) + server = Server(url=url) + try: + server[dbname] + except ResourceNotFound: + if not create: + raise + return cls(url, dbname) + def __init__(self, url, database, replica_uid=None, full_commit=True, session=None): """Create a new Couch data container.""" @@ -215,3 +241,30 @@ class CouchSyncTarget(LocalSyncTarget): self._db._set_replica_gen_and_trans_id( source_replica_uid, source_replica_generation, source_replica_transaction_id) + + +class CouchServerState(ServerState): + + def open_database(self, path): + """ + Open a database at the given location. + """ + return CouchDatabase.open_database(path, create=False) + + def check_database(self, path): + """ + Check if the database at the given location exists. + """ + db = self.open_database(path) + db.close() + + def ensure_database(self, path): + """Ensure database at the given location.""" + db = CouchDatabase.open_database(path, + create=True) + return db, db._replica_uid + + def delete_database(self, path): + """Delete database at the given location.""" + db = CouchDatabase.open_database(path) + db.delete_database() diff --git a/backends/objectstore.py b/backends/objectstore.py index 588fc7a1..199107af 100644 --- a/backends/objectstore.py +++ b/backends/objectstore.py @@ -7,8 +7,13 @@ class ObjectStore(InMemoryDatabase): A backend for storing u1db data in an object store. """ - def __init__(self, replica_uid=None): - super(ObjectStore, self).__init__(replica_uid) + @classmethod + def open_database(cls, url, create, document_factory=None): + raise NotImplementedError(cls.open_database) + + def __init__(self, replica_uid=None, document_factory=None): + super(ObjectStore, self).__init__(replica_uid, + document_factory=document_factory) # sync data in memory with data in object store if not self._get_doc(self.U1DB_DATA_DOC_ID): self._init_u1db_data() |