changeset 1385:8bf6e48c6236

Added rollback and exception logging to SyncPages.
author Alexander Schremmer <alex AT alexanderweb DOT de>
date Sun, 20 Aug 2006 18:37:26 +0200
parents 4a71075e6d39
children 0559fa036536
files MoinMoin/action/SyncPages.py MoinMoin/wikisync.py MoinMoin/xmlrpc/__init__.py docs/CHANGES.aschremmer
diffstat 4 files changed, 47 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/action/SyncPages.py	Sun Aug 20 17:29:00 2006 +0200
+++ b/MoinMoin/action/SyncPages.py	Sun Aug 20 18:37:26 2006 +0200
@@ -24,7 +24,7 @@
 from MoinMoin.PageEditor import PageEditor, conflict_markers
 from MoinMoin.Page import Page
 from MoinMoin.wikidicts import Dict, Group
-from MoinMoin.wikisync import TagStore, UnsupportedWikiException, SyncPage
+from MoinMoin.wikisync import TagStore, UnsupportedWikiException, SyncPage, NotAllowedException
 from MoinMoin.wikisync import MoinLocalWiki, MoinRemoteWiki, UP, DOWN, BOTH, MIMETYPE_MOIN
 from MoinMoin.util.bdiff import decompress, patch, compress, textdiff
 from MoinMoin.util import diff3
@@ -136,15 +136,20 @@
 
             if not remote.valid:
                 raise ActionStatus(_("The ''remoteWiki'' is unknown."))
-
-            self.sync(params, local, remote)
         except ActionStatus, e:
             msg = u'<p class="error">%s</p>\n' % (e.args[0], )
-        else:
-            msg = u"%s" % (_("Syncronisation finished. Look below for the status messages."), )
 
-        self.page.saveText(self.page.get_raw_body() + "\n\n" + self.generate_log_table(), 0)
-        # XXX release readlock on self.page
+        try:
+            try:
+                self.sync(params, local, remote)
+            except Exception, e:
+                self.log_status(self.ERROR, _("A severe error occured:"), raw_suffix=repr(e))
+                raise
+            else:
+                msg = u"%s" % (_("Syncronisation finished. Look below for the status messages."), )
+        finally:
+            self.page.saveText(self.page.get_raw_body() + "\n\n" + self.generate_log_table(), 0)
+            # XXX release readlock on self.page
 
         self.page.send_page(self.request, msg=msg)
 
@@ -335,21 +340,37 @@
 
             # XXX upgrade to write lock
             try:
+                local_change_done = True
                 current_page.saveText(merged_text, sp.local_rev, comment=comment) # YYY direct access
             except PageEditor.Unchanged:
-                pass
+                local_change_done = False
             except PageEditor.EditConflict:
+                local_change_done = False
                 assert False, "You stumbled on a problem with the current storage system - I cannot lock pages"
 
             new_local_rev = current_page.get_real_rev() # YYY direct access
 
-            if direction == BOTH:
-                try:
-                    very_current_remote_rev = remote.merge_diff(sp.remote_name, compress(diff), new_local_rev, current_remote_rev, current_remote_rev, local_full_iwid, sp.name)
-                except Exception, e:
-                    raise # XXX rollback locally and do not tag locally
-            else:
-                very_current_remote_rev = current_remote_rev
+            def rollback_local_change(): # YYY direct local access
+                rev = new_local_rev - 1
+                revstr = '%08d' % rev
+                oldpg = Page(self.request, sp.local_name, rev=rev)
+                pg = PageEditor(self.request, sp.local_name)
+                savemsg = pg.saveText(oldpg.get_raw_body(), 0, comment=u"Wikisync rollback", extra=revstr, action="SAVE/REVERT")
+
+            try:
+                if direction == BOTH:
+                    try:
+                        very_current_remote_rev = remote.merge_diff(sp.remote_name, compress(diff), new_local_rev, current_remote_rev, current_remote_rev, local_full_iwid, sp.name)
+                    except NotAllowedException:
+                        self.log_status(ActionClass.ERROR, _("Page could not be merged because you are not allowed to modify the page in the remote wiki."))
+                        return
+                else:
+                    very_current_remote_rev = current_remote_rev
+
+                local_change_done = False # changes are committed remotely, all is fine
+            finally:
+                if local_change_done:
+                    rollback_local_change()
 
             tags.add(remote_wiki=remote_full_iwid, remote_rev=very_current_remote_rev, current_rev=new_local_rev, direction=direction, normalised_name=sp.name)
 
--- a/MoinMoin/wikisync.py	Sun Aug 20 17:29:00 2006 +0200
+++ b/MoinMoin/wikisync.py	Sun Aug 20 18:37:26 2006 +0200
@@ -43,6 +43,9 @@
 class UnsupportedWikiException(Exception): pass
 
 
+class NotAllowedException(Exception): pass
+
+
 class SyncPage(object):
     """ This class represents a page in one or two wiki(s). """
     def __init__(self, name, local_rev=None, remote_rev=None, local_name=None, remote_name=None,
@@ -211,7 +214,12 @@
 
     def merge_diff(self, pagename, diff, local_rev, delta_remote_rev, last_remote_rev, interwiki_name, n_name):
         """ Merges the diff into the page on the remote side. """
-        result = self.connection.mergeDiff(pagename, xmlrpclib.Binary(diff), local_rev, delta_remote_rev, last_remote_rev, interwiki_name, n_name)
+        try:
+            result = self.connection.mergeDiff(pagename, xmlrpclib.Binary(diff), local_rev, delta_remote_rev, last_remote_rev, interwiki_name, n_name)
+        except xmlrpclib.Fault, e:
+            if e.faultCode == "NOT_ALLOWED":
+                raise NotAllowedException
+            raise
         return result
 
     def delete_page(self, pagename, last_remote_rev, interwiki_name):
--- a/MoinMoin/xmlrpc/__init__.py	Sun Aug 20 17:29:00 2006 +0200
+++ b/MoinMoin/xmlrpc/__init__.py	Sun Aug 20 18:37:26 2006 +0200
@@ -723,7 +723,7 @@
 
         # User may read page?
         if not self.request.user.may.read(pagename) or not self.request.user.may.write(pagename):
-            return self.notAllowedFault()
+            return xmlrpclib.Fault("NOT_ALLOWED", "You are not allowed to write to this page.")
 
         # XXX add locking here!
 
--- a/docs/CHANGES.aschremmer	Sun Aug 20 17:29:00 2006 +0200
+++ b/docs/CHANGES.aschremmer	Sun Aug 20 18:37:26 2006 +0200
@@ -8,7 +8,6 @@
       (currently done in Pickle files)
 
   ToDo:
-    * Implement rollback
     * Reduce round-trip times by caching queries and using MultiCall objects (coroutines?)
     * Check what needs to be documented on MoinMaster.
     * Test with prefixes
@@ -114,6 +113,7 @@
          Added infrastructure support for detecting deleted pages (not used in the merging logic yet).
          Reworked i18n and logging support. Added GetText2 macro. Getting syncing of pages
          working that are just available on one side. Working synchronisation of deleted pages.
+         Implemented rollback in case of remote problems and exception logging.
 
 2006-07-18: the requested daily entry is missing here, see http://moinmoin.wikiwikiweb.de/GoogleSoc2006/BetterProgress
 2006-07-19: the requested daily entry is missing here, see http://moinmoin.wikiwikiweb.de/GoogleSoc2006/BetterProgress