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() | 
