1.1 --- a/ApproveChangesSupport.py Thu Oct 13 22:48:25 2011 +0200
1.2 +++ b/ApproveChangesSupport.py Thu Oct 13 23:31:45 2011 +0200
1.3 @@ -18,14 +18,12 @@
1.4 from MoinMoin import user
1.5 from MoinMoin.Page import Page
1.6 from MoinMoin.wikiutil import escape
1.7 -
1.8 -try:
1.9 - set
1.10 -except NameError:
1.11 - from sets import Set as set
1.12 +import re
1.13
1.14 __version__ = "0.1"
1.15
1.16 +space_pattern = re.compile("(\s+)")
1.17 +
1.18 def get_queued_changes_page(request):
1.19 return getattr(request.cfg, "queued_changes_page", "ApprovalQueue")
1.20
1.21 @@ -112,13 +110,14 @@
1.22 def remove_directives(body, names):
1.23
1.24 """
1.25 - Remove from the page 'body' the first of each directive using the given
1.26 - 'names'.
1.27 + Return a new page body, copying the page 'body' provided but removing the
1.28 + first of each directive having one of the given 'names', along with a
1.29 + dictionary mapping directive names to values.
1.30 """
1.31
1.32 new_body = []
1.33 header = 1
1.34 - found = set()
1.35 + found = {}
1.36
1.37 for line in body.split("\n"):
1.38 if header:
1.39 @@ -127,20 +126,23 @@
1.40
1.41 if not line.startswith("#"):
1.42 header = 0
1.43 +
1.44 + # Process the comment or directive.
1.45 +
1.46 else:
1.47 - parts = line[1:].split()
1.48 + parts = space_pattern.split(line[1:])
1.49
1.50 # Identify any directive.
1.51
1.52 directive = parts[0]
1.53
1.54 - if directive in names and directive not in found:
1.55 - found.add(directive)
1.56 + if directive in names and not found.has_key(directive):
1.57 + found[directive] = "".join(parts[1:])
1.58 continue
1.59
1.60 new_body.append(line)
1.61
1.62 - return "\n".join(new_body)
1.63 + return "\n".join(new_body), found
1.64
1.65 # Utility classes and associated functions.
1.66 # NOTE: These are a subset of EventAggregatorSupport.
2.1 --- a/actions/ApproveChanges.py Thu Oct 13 22:48:25 2011 +0200
2.2 +++ b/actions/ApproveChanges.py Thu Oct 13 23:31:45 2011 +0200
2.3 @@ -15,7 +15,8 @@
2.4
2.5 from MoinMoin.action import ActionBase
2.6 from MoinMoin.Page import Page
2.7 -from MoinMoin.PageEditor import PageEditor
2.8 +from MoinMoin.PageEditor import PageEditor, conflict_markers
2.9 +from MoinMoin.util import diff3
2.10 from ApproveChangesSupport import *
2.11
2.12 # Action class and supporting functions.
2.13 @@ -82,10 +83,8 @@
2.14 if not is_queued_changes_page(request, self.pagename):
2.15 return 0, _("This page is not queued for approval.")
2.16
2.17 - target_page_name = get_target_page_name(self.pagename)
2.18 - target_page = PageEditor(request, target_page_name)
2.19 -
2.20 - # First, the displayed revision must be retrieved.
2.21 + # First, the displayed revision of the queued changes page must be
2.22 + # retrieved.
2.23
2.24 form = get_form(request)
2.25
2.26 @@ -100,16 +99,51 @@
2.27 page = Page(request, self.page.page_name, rev=rev)
2.28 body = page.get_raw_body()
2.29
2.30 - # Save the target page, removing any introduced directives.
2.31 + # Remove any introduced directives.
2.32 +
2.33 + body, directives = remove_directives(body, ["acl", "parent-revision"])
2.34 +
2.35 + # Get the target page's parent revision for the queued changes.
2.36 +
2.37 + target_page_name = get_target_page_name(self.pagename)
2.38 + target_page = PageEditor(request, target_page_name)
2.39 +
2.40 + current_rev = target_page.current_rev()
2.41 + parent_rev = int(directives.get("parent-revision", current_rev))
2.42 +
2.43 + # Where the parent revision differs from the current revision of the
2.44 + # page, attempt to merge the changes.
2.45 +
2.46 + query = {}
2.47 +
2.48 + if parent_rev != current_rev:
2.49
2.50 - body = remove_directives(body, ["acl", "parent-revision"])
2.51 + # The body of the parent revision of the target page, along with the
2.52 + # body of the current revision must be acquired.
2.53 +
2.54 + parent_body = Page(request, target_page_name, rev=parent_rev).get_raw_body()
2.55 + current_body = target_page.get_raw_body()
2.56 +
2.57 + # The parent, current and queued texts must then be merged.
2.58 +
2.59 + body = diff3.text_merge(parent_body, current_body, body, True, *conflict_markers)
2.60 +
2.61 + # Look for conflict markers and redirect to edit mode on the
2.62 + # resulting page if they are present.
2.63 +
2.64 + for marker in conflict_markers:
2.65 + if body.find(marker) != -1:
2.66 + query = {'action' : 'edit'}
2.67 + break
2.68 +
2.69 + # Save the target page.
2.70
2.71 try:
2.72 target_page.saveText(body, 0, comment=_("Changes to page approved from queue revision %d.") % rev)
2.73 except PageEditor.Unchanged:
2.74 pass
2.75
2.76 - # Delete the current page.
2.77 + # Delete the queued changes page.
2.78 # NOTE: The page could be deleted completely or certain revisions
2.79 # NOTE: purged.
2.80 # NOTE: (to-do/proper-queued-page-deletion.txt)
2.81 @@ -117,9 +151,9 @@
2.82 current_page = PageEditor(request, self.pagename)
2.83 current_page.deletePage(_("Changes to page approved."))
2.84
2.85 - # Redirect to the target page.
2.86 + # Redirect to the target page, potentially in editing mode.
2.87
2.88 - request.http_redirect(target_page.url(request))
2.89 + request.http_redirect(target_page.url(request, query))
2.90 return 1, None
2.91
2.92 def render_success(self, msg, msgtype):