def xmlrpc_getDiff(self, pagename, from_rev, to_rev, n_name=None): """ Gets the binary difference between two page revisions. @param pagename: unicode string qualifying the page name @param fromRev: integer specifying the source revision. May be None to refer to a virtual empty revision which leads to a diff containing the whole page. @param toRev: integer specifying the target revision. May be None to refer to the current revision. If the current revision is the same as fromRev, there will be a special error condition "ALREADY_CURRENT" @param n_name: do a tag check verifying that n_name was the normalised name of the last tag If both fromRev and toRev are None, this function acts similar to getPage, i.e. it will diff("",currentRev). @return: Returns a dict: * status (not a field, implicit, returned as Fault if not SUCCESS): * "SUCCESS" - if the diff could be retrieved successfully * "NOT_EXIST" - item does not exist * "FROMREV_INVALID" - the source revision is invalid * "TOREV_INVALID" - the target revision is invalid * "INTERNAL_ERROR" - there was an internal error * "INVALID_TAG" - the last tag does not match the supplied normalised name * "ALREADY_CURRENT" - this not merely an error condition. It rather means that there is no new revision to diff against which is a good thing while synchronisation. * current: the revision number of the current revision (not the one which was diff'ed against) * diff: Binary object that transports a zlib-compressed binary diff (see bdiff.py, taken from Mercurial) * conflict: if there is a conflict on the page currently """ from MoinMoin.util.bdiff import textdiff, compress from MoinMoin.wikisync import TagStore pagename = self._instr(pagename) if n_name is not None: n_name = self._instr(n_name) # User may read page? if not self.request.user.may.read(pagename): return self.notAllowedFault() def allowed_rev_type(data): if data is None: return True return isinstance(data, int) and data > 0 if not allowed_rev_type(from_rev): return xmlrpclib.Fault("FROMREV_INVALID", "Incorrect type for from_rev.") if not allowed_rev_type(to_rev): return xmlrpclib.Fault("TOREV_INVALID", "Incorrect type for to_rev.") currentpage = Page(self.request, pagename) if not currentpage.exists(): return xmlrpclib.Fault("NOT_EXIST", "Page does not exist.") revisions = currentpage.getRevList() if from_rev is not None and from_rev not in revisions: return xmlrpclib.Fault("FROMREV_INVALID", "Unknown from_rev.") if to_rev is not None and to_rev not in revisions: return xmlrpclib.Fault("TOREV_INVALID", "Unknown to_rev.") # use lambda to defer execution in the next lines if from_rev is None: oldcontents = lambda: "" else: oldpage = Page(self.request, pagename, rev=from_rev) oldcontents = lambda: oldpage.get_raw_body_str() if to_rev is None: newpage = currentpage newcontents = lambda: currentpage.get_raw_body_str() else: newpage = Page(self.request, pagename, rev=to_rev) newcontents = lambda: newpage.get_raw_body_str() if oldcontents() and oldpage.get_real_rev() == newpage.get_real_rev(): return xmlrpclib.Fault("ALREADY_CURRENT", "There are no changes.") if n_name is not None: tags = TagStore(newpage) last_tag = tags.get_last_tag() if last_tag is not None and last_tag.normalised_name != n_name: return xmlrpclib.Fault( "INVALID_TAG", "The used tag is incorrect because the normalised name does not match." ) newcontents = newcontents() conflict = wikiutil.containsConflictMarker(newcontents) diffblob = xmlrpclib.Binary( compress(textdiff(oldcontents(), newcontents))) return { "conflict": conflict, "diff": diffblob, "diffversion": 1, "current": currentpage.get_real_rev() }
def xmlrpc_getDiff(self, pagename, from_rev, to_rev, n_name=None): """ Gets the binary difference between two page revisions. @param pagename: unicode string qualifying the page name @param fromRev: integer specifying the source revision. May be None to refer to a virtual empty revision which leads to a diff containing the whole page. @param toRev: integer specifying the target revision. May be None to refer to the current revision. If the current revision is the same as fromRev, there will be a special error condition "ALREADY_CURRENT" @param n_name: do a tag check verifying that n_name was the normalised name of the last tag If both fromRev and toRev are None, this function acts similar to getPage, i.e. it will diff("",currentRev). @return: Returns a dict: * status (not a field, implicit, returned as Fault if not SUCCESS): * "SUCCESS" - if the diff could be retrieved successfully * "NOT_EXIST" - item does not exist * "FROMREV_INVALID" - the source revision is invalid * "TOREV_INVALID" - the target revision is invalid * "INTERNAL_ERROR" - there was an internal error * "INVALID_TAG" - the last tag does not match the supplied normalised name * "ALREADY_CURRENT" - this not merely an error condition. It rather means that there is no new revision to diff against which is a good thing while synchronisation. * current: the revision number of the current revision (not the one which was diff'ed against) * diff: Binary object that transports a zlib-compressed binary diff (see bdiff.py, taken from Mercurial) * conflict: if there is a conflict on the page currently """ from MoinMoin.util.bdiff import textdiff, compress from MoinMoin.wikisync import TagStore pagename = self._instr(pagename) if n_name is not None: n_name = self._instr(n_name) # User may read page? if not self.request.user.may.read(pagename): return self.notAllowedFault() def allowed_rev_type(data): if data is None: return True return isinstance(data, int) and data > 0 if not allowed_rev_type(from_rev): return xmlrpclib.Fault("FROMREV_INVALID", "Incorrect type for from_rev.") if not allowed_rev_type(to_rev): return xmlrpclib.Fault("TOREV_INVALID", "Incorrect type for to_rev.") currentpage = Page(self.request, pagename) if not currentpage.exists(): return xmlrpclib.Fault("NOT_EXIST", "Page does not exist.") revisions = currentpage.getRevList() if from_rev is not None and from_rev not in revisions: return xmlrpclib.Fault("FROMREV_INVALID", "Unknown from_rev.") if to_rev is not None and to_rev not in revisions: return xmlrpclib.Fault("TOREV_INVALID", "Unknown to_rev.") # use lambda to defer execution in the next lines if from_rev is None: oldcontents = lambda: "" else: oldpage = Page(self.request, pagename, rev=from_rev) oldcontents = lambda: oldpage.get_raw_body_str() if to_rev is None: newpage = currentpage newcontents = lambda: currentpage.get_raw_body_str() else: newpage = Page(self.request, pagename, rev=to_rev) newcontents = lambda: newpage.get_raw_body_str() if oldcontents() and oldpage.get_real_rev() == newpage.get_real_rev(): return xmlrpclib.Fault("ALREADY_CURRENT", "There are no changes.") if n_name is not None: tags = TagStore(newpage) last_tag = tags.get_last_tag() if last_tag is not None and last_tag.normalised_name != n_name: return xmlrpclib.Fault("INVALID_TAG", "The used tag is incorrect because the normalised name does not match.") newcontents = newcontents() conflict = wikiutil.containsConflictMarker(newcontents) diffblob = xmlrpclib.Binary(compress(textdiff(oldcontents(), newcontents))) return {"conflict": conflict, "diff": diffblob, "diffversion": 1, "current": currentpage.get_real_rev()}