Complete serialization with pretty printing. Works both in FF and Webkit. This fixes...
[redakcja.git] / lib / vstorage.py
index 1060bc2..b23234a 100644 (file)
@@ -15,7 +15,7 @@ import mercurial.revlog
 import mercurial.util
 
 
 import mercurial.util
 
 
-def urlquote(url, safe='/'):
+def urlquote(url, safe = '/'):
     """Quotes URL 
     
     >>> urlquote(u'Za\u017c\xf3\u0142\u0107 g\u0119\u015bl\u0105 ja\u017a\u0144')
     """Quotes URL 
     
     >>> urlquote(u'Za\u017c\xf3\u0142\u0107 g\u0119\u015bl\u0105 ja\u017a\u0144')
@@ -78,7 +78,7 @@ def guess_mime(file_name):
     'archive/gzip'
     """
 
     'archive/gzip'
     """
 
-    mime, encoding = mimetypes.guess_type(file_name, strict=False)
+    mime, encoding = mimetypes.guess_type(file_name, strict = False)
     if encoding:
         mime = 'archive/%s' % encoding
     if mime is None:
     if encoding:
         mime = 'archive/%s' % encoding
     if mime is None:
@@ -96,7 +96,7 @@ class VersionedStorage(object):
     change history, using Mercurial repository as the storage method.
     """
 
     change history, using Mercurial repository as the storage method.
     """
 
-    def __init__(self, path, charset=None):
+    def __init__(self, path, charset = None):
         """
         Takes the path to the directory where the pages are to be kept.
         If the directory doen't exist, it will be created. If it's inside
         """
         Takes the path to the directory where the pages are to be kept.
         If the directory doen't exist, it will be created. If it's inside
@@ -110,8 +110,8 @@ class VersionedStorage(object):
             os.makedirs(self.path)
         self.repo_path = find_repo_path(self.path)
         try:
             os.makedirs(self.path)
         self.repo_path = find_repo_path(self.path)
         try:
-            self.ui = mercurial.ui.ui(report_untrusted=False,
-                                      interactive=False, quiet=True)
+            self.ui = mercurial.ui.ui(report_untrusted = False,
+                                      interactive = False, quiet = True)
         except TypeError:
             # Mercurial 1.3 changed the way we setup the ui object.
             self.ui = mercurial.ui.ui()
         except TypeError:
             # Mercurial 1.3 changed the way we setup the ui object.
             self.ui = mercurial.ui.ui()
@@ -125,7 +125,7 @@ class VersionedStorage(object):
             create = False
         self.repo_prefix = self.path[len(self.repo_path):].strip('/')
         self.repo = mercurial.hg.repository(self.ui, self.repo_path,
             create = False
         self.repo_prefix = self.path[len(self.repo_path):].strip('/')
         self.repo = mercurial.hg.repository(self.ui, self.repo_path,
-                                            create=create)
+                                            create = create)
 
     def reopen(self):
         """Close and reopen the repo, to make sure we are up to date."""
 
     def reopen(self):
         """Close and reopen the repo, to make sure we are up to date."""
@@ -133,10 +133,10 @@ class VersionedStorage(object):
         self.repo = mercurial.hg.repository(self.ui, self.repo_path)
 
     def _file_path(self, title):
         self.repo = mercurial.hg.repository(self.ui, self.repo_path)
 
     def _file_path(self, title):
-        return os.path.join(self.path, urlquote(title, safe=''))
+        return os.path.join(self.path, urlquote(title, safe = ''))
 
     def _title_to_file(self, title):
 
     def _title_to_file(self, title):
-        return os.path.join(self.repo_prefix, urlquote(title, safe=''))
+        return os.path.join(self.repo_prefix, urlquote(title, safe = ''))
 
     def _file_to_title(self, filename):
         assert filename.startswith(self.repo_prefix)
 
     def _file_to_title(self, filename):
         assert filename.startswith(self.repo_prefix)
@@ -144,7 +144,8 @@ class VersionedStorage(object):
         return urlunquote(name)
 
     def __contains__(self, title):
         return urlunquote(name)
 
     def __contains__(self, title):
-        return os.path.exists(self._file_path(title))
+        print "Checking ", title
+        return urlquote(title) in self.repo.dirstate
 
     def __iter__(self):
         return self.all_pages()
 
     def __iter__(self):
         return self.all_pages()
@@ -157,16 +158,19 @@ class VersionedStorage(object):
 
         self.repo.dirstate.setparents(parent_node)
         node = self._commit([repo_file], text, user)
 
         self.repo.dirstate.setparents(parent_node)
         node = self._commit([repo_file], text, user)
-        
+
         partial = lambda filename: repo_file == filename
         partial = lambda filename: repo_file == filename
-        
+
         # If p1 is equal to p2, there is no work to do. Even the dirstate is correct.
         p1, p2 = self.repo[None].parents()[0], self.repo[tip_node]
         if p1 == p2:
             return text
         # If p1 is equal to p2, there is no work to do. Even the dirstate is correct.
         p1, p2 = self.repo[None].parents()[0], self.repo[tip_node]
         if p1 == p2:
             return text
-        
-        # TODO: Check if merge was successful
-        mercurial.merge.update(self.repo, tip_node, True, False, partial)
+
+        try:
+            mercurial.merge.update(self.repo, tip_node, True, False, partial)
+            msg = 'merge of edit conflict'
+        except mercurial.util.Abort:
+            msg = 'failed merge of edit conflict'
 
         self.repo.dirstate.setparents(tip_node, node)
         # Mercurial 1.1 and later need updating the merge state
 
         self.repo.dirstate.setparents(tip_node, node)
         # Mercurial 1.1 and later need updating the merge state
@@ -174,10 +178,10 @@ class VersionedStorage(object):
             mercurial.merge.mergestate(self.repo).mark(repo_file, "r")
         except (AttributeError, KeyError):
             pass
             mercurial.merge.mergestate(self.repo).mark(repo_file, "r")
         except (AttributeError, KeyError):
             pass
-        return u'merge of edit conflict'
+        return msg
 
     @locked_repo
 
     @locked_repo
-    def save_file(self, title, file_name, author=u'', comment=u'', parent=None):
+    def save_file(self, title, file_name, author = u'', comment = u'', parent = None):
         """Save an existing file as specified page."""
 
         user = author.encode('utf-8') or u'anon'.encode('utf-8')
         """Save an existing file as specified page."""
 
         user = author.encode('utf-8') or u'anon'.encode('utf-8')
@@ -201,20 +205,20 @@ class VersionedStorage(object):
 
     def _commit(self, files, text, user):
         try:
 
     def _commit(self, files, text, user):
         try:
-            return self.repo.commit(files=files, text=text, user=user,
-                                    force=True, empty_ok=True)
+            return self.repo.commit(files = files, text = text, user = user,
+                                    force = True, empty_ok = True)
         except TypeError:
             # Mercurial 1.3 doesn't accept empty_ok or files parameter
             match = mercurial.match.exact(self.repo_path, '', list(files))
         except TypeError:
             # Mercurial 1.3 doesn't accept empty_ok or files parameter
             match = mercurial.match.exact(self.repo_path, '', list(files))
-            return self.repo.commit(match=match, text=text, user=user,
-                                    force=True)
+            return self.repo.commit(match = match, text = text, user = user,
+                                    force = True)
 
 
 
 
-    def save_data(self, title, data, author=u'', comment=u'', parent=None):
+    def save_data(self, title, data, author = u'', comment = u'', parent = None):
         """Save data as specified page."""
 
         try:
         """Save data as specified page."""
 
         try:
-            temp_path = tempfile.mkdtemp(dir=self.path)
+            temp_path = tempfile.mkdtemp(dir = self.path)
             file_path = os.path.join(temp_path, 'saved')
             f = open(file_path, "wb")
             f.write(data)
             file_path = os.path.join(temp_path, 'saved')
             f = open(file_path, "wb")
             f.write(data)
@@ -230,7 +234,7 @@ class VersionedStorage(object):
             except OSError:
                 pass
 
             except OSError:
                 pass
 
-    def save_text(self, title, text, author=u'', comment=u'', parent=None):
+    def save_text(self, title, text, author = u'', comment = u'', parent = None):
         """Save text as specified page, encoded to charset."""
 
         data = text.encode(self.charset)
         """Save text as specified page, encoded to charset."""
 
         data = text.encode(self.charset)
@@ -248,7 +252,7 @@ class VersionedStorage(object):
             yield unicode(data, self.charset, 'replace')
 
     @locked_repo
             yield unicode(data, self.charset, 'replace')
 
     @locked_repo
-    def delete_page(self, title, author=u'', comment=u''):
+    def delete_page(self, title, author = u'', comment = u''):
         user = author.encode('utf-8') or 'anon'
         text = comment.encode('utf-8') or 'deleted'
         repo_file = self._title_to_file(title)
         user = author.encode('utf-8') or 'anon'
         text = comment.encode('utf-8') or 'deleted'
         repo_file = self._title_to_file(title)
@@ -261,9 +265,14 @@ class VersionedStorage(object):
         self._commit([repo_file], text, user)
 
     def open_page(self, title):
         self._commit([repo_file], text, user)
 
     def open_page(self, title):
+        if title not in self:
+            raise DocumentNotFound()
+
         try:
             return open(self._file_path(title), "rb")
         except IOError:
         try:
             return open(self._file_path(title), "rb")
         except IOError:
+            import traceback
+            print traceback.print_exc()
             raise DocumentNotFound()
 
     def page_file_meta(self, title):
             raise DocumentNotFound()
 
     def page_file_meta(self, title):
@@ -278,11 +287,12 @@ class VersionedStorage(object):
 
     def page_meta(self, title):
         """Get page's revision, date, last editor and his edit comment."""
 
     def page_meta(self, title):
         """Get page's revision, date, last editor and his edit comment."""
+        if not title in self:
+            raise DocumentNotFound()
 
         filectx_tip = self._find_filectx(title)
         if filectx_tip is None:
             raise DocumentNotFound()
 
         filectx_tip = self._find_filectx(title)
         if filectx_tip is None:
             raise DocumentNotFound()
-            #return -1, None, u'', u''
         rev = filectx_tip.filerev()
         filectx = filectx_tip.filectx(rev)
         date = datetime.datetime.fromtimestamp(filectx.date()[0])
         rev = filectx_tip.filerev()
         filectx = filectx_tip.filectx(rev)
         date = datetime.datetime.fromtimestamp(filectx.date()[0])
@@ -333,7 +343,7 @@ class VersionedStorage(object):
             return
         maxrev = filectx_tip.filerev()
         minrev = 0
             return
         maxrev = filectx_tip.filerev()
         minrev = 0
-        for rev in range(maxrev, minrev-1, -1):
+        for rev in range(maxrev, minrev - 1, -1):
             filectx = filectx_tip.filectx(rev)
             date = datetime.datetime.fromtimestamp(filectx.date()[0])
             author = unicode(filectx.user(), "utf-8",
             filectx = filectx_tip.filectx(rev)
             date = datetime.datetime.fromtimestamp(filectx.date()[0])
             author = unicode(filectx.user(), "utf-8",
@@ -364,7 +374,7 @@ class VersionedStorage(object):
         changectx = self._changectx()
         maxrev = changectx.rev()
         minrev = 0
         changectx = self._changectx()
         maxrev = changectx.rev()
         minrev = 0
-        for wiki_rev in range(maxrev, minrev-1, -1):
+        for wiki_rev in range(maxrev, minrev - 1, -1):
             change = self.repo.changectx(wiki_rev)
             date = datetime.datetime.fromtimestamp(change.date()[0])
             author = unicode(change.user(), "utf-8",
             change = self.repo.changectx(wiki_rev)
             date = datetime.datetime.fromtimestamp(change.date()[0])
             author = unicode(change.user(), "utf-8",
@@ -381,11 +391,11 @@ class VersionedStorage(object):
 
     def all_pages(self):
         """Iterate over the titles of all pages in the wiki."""
 
     def all_pages(self):
         """Iterate over the titles of all pages in the wiki."""
-
-        for filename in os.listdir(self.path):
-            if (os.path.isfile(os.path.join(self.path, filename))
-                and not filename.startswith('.')):
-                yield urlunquote(filename)
+        return [ urlunquote(filename) for filename in self.repo.dirstate]
+        #status = self.repo.status(self.repo[None], None, None, True, True, True)
+        #clean_files = status[6]
+        #for filename in clean_files:
+        #    yield
 
     def changed_since(self, rev):
         """Return all pages that changed since specified repository revision."""
 
     def changed_since(self, rev):
         """Return all pages that changed since specified repository revision."""
@@ -399,6 +409,6 @@ class VersionedStorage(object):
         current = self.repo.lookup('tip')
         status = self.repo.status(current, last)
         modified, added, removed, deleted, unknown, ignored, clean = status
         current = self.repo.lookup('tip')
         status = self.repo.status(current, last)
         modified, added, removed, deleted, unknown, ignored, clean = status
-        for filename in modified+added+removed+deleted:
+        for filename in modified + added + removed + deleted:
             if filename.startswith(self.repo_prefix):
                 yield self._file_to_title(filename)
             if filename.startswith(self.repo_prefix):
                 yield self._file_to_title(filename)