def _render_diff(self, req, filename, repos, diff, diff_options): """Raw Unified Diff version""" req.send_response(200) req.send_header('Content-Type', 'text/plain;charset=utf-8') req.send_header('Content-Disposition', 'inline;' 'filename=%s.diff' % filename) req.end_headers() mimeview = Mimeview(self.env) for old_node, new_node, kind, change in repos.get_changes(**diff): # TODO: Property changes # Content changes if kind == Node.DIRECTORY: continue new_content = old_content = '' new_node_info = old_node_info = ('','') mimeview = Mimeview(self.env) if old_node: old_content = old_node.get_content().read() if is_binary(old_content): continue old_node_info = (old_node.path, old_node.rev) old_content = mimeview.to_unicode(old_content, old_node.content_type) if new_node: new_content = new_node.get_content().read() if is_binary(new_content): continue new_node_info = (new_node.path, new_node.rev) new_path = new_node.path new_content = mimeview.to_unicode(new_content, new_node.content_type) else: old_node_path = repos.normalize_path(old_node.path) diff_old_path = repos.normalize_path(diff.old_path) new_path = posixpath.join(diff.new_path, old_node_path[len(diff_old_path)+1:]) if old_content != new_content: context = 3 options = diff_options[1] for option in options: if option.startswith('-U'): context = int(option[2:]) break if not old_node_info[0]: old_node_info = new_node_info # support for 'A'dd changes req.write('Index: ' + new_path + CRLF) req.write('=' * 67 + CRLF) req.write('--- %s (revision %s)' % old_node_info + CRLF) req.write('+++ %s (revision %s)' % new_node_info + CRLF) for line in unified_diff(old_content.splitlines(), new_content.splitlines(), context, ignore_blank_lines='-B' in options, ignore_case='-i' in options, ignore_space_changes='-b' in options): req.write(line + CRLF)
def notify(self, action, page, version=None, time=None, comment=None, author=None, ipnr=None, redirect=False, old_name=None): self.page = page self.change_author = author self.time = time self.action = action self.version = version self.redirect = redirect self.old_name = old_name # self.env.log.debug("Notify Action: %s", action) # self.env.log.debug("Page time: %r, %s", time, time) if action == "added": self.newwiki = True self.data['name'] = page.name self.data['old_name'] = old_name self.data['redirect'] = redirect self.data['text'] = page.text self.data['version'] = version self.data['author'] = author self.data['comment'] = comment self.data['ip'] = ipnr self.data['action'] = action self.data['link'] = self.env.abs_href.wiki(page.name) self.data['linkdiff'] = self.env.abs_href.wiki(page.name, action='diff', version=page.version) if page.version > 0 and action == 'modified': diff = diff_header % { 'name': self.page.name, 'version': self.page.version, 'oldversion': self.page.version - 1 } oldpage = WikiPage(self.env, page.name, page.version - 1) self.data["oldversion"] = oldpage.version self.data["oldtext"] = oldpage.text for line in unified_diff(oldpage.text.splitlines(), page.text.splitlines(), context=3): diff += "%s\n" % line self.wikidiff = diff self.data["wikidiff"] = self.wikidiff subject = self.format_subject(action.replace('_', ' ')) NotifyEmail.notify(self, page.name, subject)
def render_property_diff(self, name, old_context, old_props, new_context, new_props, options): old, new = old_props[name], new_props[name] # Render as diff only if multiline (see #3002) if '\n' not in old and '\n' not in new: return None unidiff = '--- \n+++ \n' + \ '\n'.join(unified_diff(old.splitlines(), new.splitlines(), options.get('contextlines', 3))) return tag.li('Property ', tag.strong(name), Mimeview(self.env).render(old_context, 'text/x-diff', unidiff))
def _format_plaintext(self, event): page = event.target data = dict( action=event.category, attachment=event.attachment, page=page, author=event.author, comment=event.comment, category=event.category, page_link=self.env.abs_href('wiki', page.name), project_name=self.env.project_name, project_desc=self.env.project_description, project_link=self.env.project_url or self.env.abs_href(), ) old_page = WikiPage(self.env, page.name, page.version - 1) if page.version: data["changed"] = True data["diff_link"] = self.env.abs_href('wiki', page.name, action="diff", version=page.version) if self.wiki_email_diff: # DEVEL: Formatter needs req object to get preferred language. diff_header = _(""" Index: %(name)s ============================================================================== --- %(name)s (version: %(oldversion)s) +++ %(name)s (version: %(version)s) """) diff = "\n" diff += diff_header % { 'name': page.name, 'version': page.version, 'oldversion': page.version - 1 } for line in unified_diff(old_page.text.splitlines(), page.text.splitlines(), context=3): diff += "%s\n" % line data["diff"] = diff chrome = Chrome(self.env) dirs = [] for provider in chrome.template_providers: dirs += provider.get_templates_dirs() templates = TemplateLoader(dirs, variable_lookup='lenient') template = templates.load('wiki_email_plaintext.txt', cls=NewTextTemplate) if template: stream = template.generate(**data) output = stream.render('text') return output
def _format_plaintext(self, event): page = event.target data = dict( action=event.category, attachment=event.attachment, page=page, author=event.author, comment=event.comment, category=event.category, page_link=self.env.abs_href('wiki', page.name), project_name=self.env.project_name, project_desc=self.env.project_description, project_link=self.env.project_url or self.env.abs_href(), ) old_page = WikiPage(self.env, page.name, page.version - 1) if page.version: data['changed'] = True data['diff_link'] = self.env.abs_href('wiki', page.name, action='diff', version=page.version) if self.wiki_email_diff: # DEVEL: Formatter needs req object to get preferred language. diff_header = _(""" Index: %(name)s ============================================================================== --- %(name)s (version: %(oldversion)s) +++ %(name)s (version: %(version)s) """) diff = "\n" diff += diff_header % { 'name': page.name, 'version': page.version, 'oldversion': page.version - 1 } for line in unified_diff(old_page.text.splitlines(), page.text.splitlines(), context=3): diff += "%s\n" % line data['diff'] = diff chrome = Chrome(self.env) dirs = [] for provider in chrome.template_providers: dirs += provider.get_templates_dirs() templates = TemplateLoader(dirs, variable_lookup='lenient') template = templates.load('wiki_email_plaintext.txt', cls=NewTextTemplate) if template: stream = template.generate(**data) return stream.render('text')
def _format_plaintext(self, event): page = event.target data = dict( action = event.category, attachment = event.attachment, page = page, author = event.author, comment = event.comment, category = event.category, page_link = self.env.abs_href('wiki', page.name), project_name = self.env.project_name, project_desc = self.env.project_description, project_link = self.env.project_url or self.env.abs_href(), ) old_page = WikiPage(self.env, page.name, page.version - 1) if page.version: data["changed"] = True data["diff_link"] = self.env.abs_href('wiki', page.name, action="diff", version=page.version) if self.wiki_email_diff: diff = "\n" diff += diff_header % { 'name': page.name, 'version': page.version, 'oldversion': page.version - 1 } for line in unified_diff(old_page.text.splitlines(), page.text.splitlines(), context=3): diff += "%s\n" % line data["diff"] = diff chrome = Chrome(self.env) dirs = [] for provider in chrome.template_providers: dirs += provider.get_templates_dirs() templates = TemplateLoader(dirs, variable_lookup='lenient') template = templates.load('wiki_email_plaintext.txt', cls=NewTextTemplate) if template: stream = template.generate(**data) output = stream.render('text') return output
def _render_diff(self, req, repos, chgset, diff_options): """Raw Unified Diff version""" req.send_response(200) req.send_header('Content-Type', 'text/plain;charset=utf-8') req.send_header('Content-Disposition', 'filename=Changeset%s.diff' % req.args.get('rev')) req.end_headers() for path, kind, change, base_path, base_rev in chgset.get_changes(): if change == Changeset.ADD: old_node = None else: old_node = repos.get_node(base_path or path, base_rev) if change == Changeset.DELETE: new_node = None else: new_node = repos.get_node(path, chgset.rev) # TODO: Property changes # Content changes if kind == 'dir': continue default_charset = self.config.get('trac', 'default_charset') new_content = old_content = '' new_node_info = old_node_info = ('', '') if old_node: charset = mimeview.get_charset(old_node.content_type) or \ default_charset old_content = util.to_utf8(old_node.get_content().read(), charset) old_node_info = (old_node.path, old_node.rev) if mimeview.is_binary(old_content): continue if new_node: charset = mimeview.get_charset(new_node.content_type) or \ default_charset new_content = util.to_utf8(new_node.get_content().read(), charset) new_node_info = (new_node.path, new_node.rev) if mimeview.is_binary(new_content): continue if old_content != new_content: context = 3 for option in diff_options[1]: if option.startswith('-U'): context = int(option[2:]) break req.write('Index: ' + path + util.CRLF) req.write('=' * 67 + util.CRLF) req.write('--- %s (revision %s)' % old_node_info + util.CRLF) req.write('+++ %s (revision %s)' % new_node_info + util.CRLF) for line in unified_diff(old_content.splitlines(), new_content.splitlines(), context, ignore_blank_lines='-B' in diff_options[1], ignore_case='-i' in diff_options[1], ignore_space_changes='-b' in diff_options[1]): req.write(line + util.CRLF)
def test_unified_diff_no_context(self): diff_lines = list(diff.unified_diff(['a'], ['b'])) self.assertEqual(['@@ -1,1 +1,1 @@', '-a', '+b'], diff_lines)
def _render_diff(self, req, repos, chgset, diff_options): """Raw Unified Diff version""" req.send_response(200) req.send_header('Content-Type', 'text/plain;charset=utf-8') req.send_header('Content-Disposition', 'inline;' 'filename=Changeset%s.diff' % chgset.rev) req.end_headers() for path, kind, change, base_path, base_rev in chgset.get_changes(): if change == Changeset.ADD: old_node = None else: old_node = repos.get_node(base_path or path, base_rev) if change == Changeset.DELETE: new_node = None else: new_node = repos.get_node(path, chgset.rev) # TODO: Property changes # Content changes if kind == 'dir': continue default_charset = self.config.get('trac', 'default_charset') new_content = old_content = '' new_node_info = old_node_info = ('','') if old_node: charset = mimeview.get_charset(old_node.content_type) or \ default_charset old_content = util.to_utf8(old_node.get_content().read(), charset) old_node_info = (old_node.path, old_node.rev) if mimeview.is_binary(old_content): continue if new_node: charset = mimeview.get_charset(new_node.content_type) or \ default_charset new_content = util.to_utf8(new_node.get_content().read(), charset) new_node_info = (new_node.path, new_node.rev) if mimeview.is_binary(new_content): continue if old_content != new_content: context = 3 for option in diff_options[1]: if option.startswith('-U'): context = int(option[2:]) break req.write('Index: ' + path + util.CRLF) req.write('=' * 67 + util.CRLF) req.write('--- %s (revision %s)' % old_node_info + util.CRLF) req.write('+++ %s (revision %s)' % new_node_info + util.CRLF) for line in unified_diff(old_content.splitlines(), new_content.splitlines(), context, ignore_blank_lines='-B' in diff_options[1], ignore_case='-i' in diff_options[1], ignore_space_changes='-b' in diff_options[1]): req.write(line + util.CRLF)
def notify(self, action, page, version=None, time=None, comment=None, author=None, ipnr=None, redirect=False, old_name=None): self.page = page self.change_author = author self.time = time self.action = action self.version = version self.redirect = redirect self.old_name = old_name # self.env.log.debug("Notify Action: %s", action) # self.env.log.debug("Page time: %r, %s", time, time) if action == "added": self.newwiki = True self.data['name'] = page.name self.data['old_name'] = old_name self.data['redirect'] = redirect self.data['text'] = page.text self.data['version'] = version self.data['author'] = author self.data['comment'] = comment self.data['ip'] = ipnr self.data['action'] = action self.data['link'] = self.env.abs_href.wiki(page.name) self.data['linkdiff'] = self.env.abs_href.wiki(page.name, action='diff', version=page.version) if page.version > 0 and action == 'modified': diff = diff_header % { 'name': self.page.name, 'version': self.page.version, 'oldversion': self.page.version - 1 } oldpage = WikiPage(self.env, page.name, page.version - 1) self.data["oldversion"] = oldpage.version self.data["oldtext"] = oldpage.text for line in unified_diff(oldpage.text.splitlines(), page.text.splitlines(), context=3): diff += "%s\n" % line self.wikidiff = diff self.data["wikidiff"] = self.wikidiff self.subject = self.format_subject(action.replace('_', ' ')) config = self.config['notification'] if not config.getbool('smtp_enabled'): return self.replyto_email = config.get('smtp_replyto') self.from_email = self.from_email or self.replyto_email if not self.from_email and not self.replyto_email: message = tag( tag.p(_('Unable to send email due to identity crisis.')), # convert explicitly to `Fragment` to avoid breaking message # when passing `LazyProxy` object to `Fragment` tag.p( to_fragment( tag_( "Neither %(from_)s nor %(reply_to)s are specified in the " "configuration.", from_=tag.strong('[notification] smtp_from'), reply_to=tag.strong( '[notification] smtp_replyto'))))) raise TracError(message, _('SMTP Notification Error')) Notify.notify(self, page.name)
def test_unified_diff_no_context(self): diff_lines = list(diff.unified_diff(["a"], ["b"])) self.assertEqual(["@@ -1,1 +1,1 @@", "-a", "+b"], diff_lines)
def _render_diff(self, req, filename, repos, data): """Raw Unified Diff version""" req.send_response(200) req.send_header('Content-Type', 'text/x-patch;charset=utf-8') req.send_header('Content-Disposition', content_disposition('inline', filename + '.diff')) buf = StringIO() mimeview = Mimeview(self.env) for old_node, new_node, kind, change in repos.get_changes( new_path=data['new_path'], new_rev=data['new_rev'], old_path=data['old_path'], old_rev=data['old_rev']): # TODO: Property changes # Content changes if kind == Node.DIRECTORY: continue new_content = old_content = '' new_node_info = old_node_info = ('','') mimeview = Mimeview(self.env) if old_node: if mimeview.is_binary(old_node.content_type, old_node.path): continue old_content = old_node.get_content().read() if mimeview.is_binary(content=old_content): continue old_node_info = (old_node.path, old_node.rev) old_content = mimeview.to_unicode(old_content, old_node.content_type) if new_node: if mimeview.is_binary(new_node.content_type, new_node.path): continue new_content = new_node.get_content().read() if mimeview.is_binary(content=new_content): continue new_node_info = (new_node.path, new_node.rev) new_path = new_node.path new_content = mimeview.to_unicode(new_content, new_node.content_type) else: old_node_path = repos.normalize_path(old_node.path) diff_old_path = repos.normalize_path(data['old_path']) new_path = posixpath.join(data['new_path'], old_node_path[len(diff_old_path)+1:]) if old_content != new_content: options = data['diff']['options'] context = options.get('contextlines', 3) if context < 0: context = 3 # FIXME: unified_diff bugs with context=None ignore_blank_lines = options.get('ignoreblanklines') ignore_case = options.get('ignorecase') ignore_space = options.get('ignorewhitespace') if not old_node_info[0]: old_node_info = new_node_info # support for 'A'dd changes buf.write('Index: ' + new_path + CRLF) buf.write('=' * 67 + CRLF) buf.write('--- %s\t(revision %s)' % old_node_info + CRLF) buf.write('+++ %s\t(revision %s)' % new_node_info + CRLF) for line in unified_diff(old_content.splitlines(), new_content.splitlines(), context, ignore_blank_lines=ignore_blank_lines, ignore_case=ignore_case, ignore_space_changes=ignore_space): buf.write(line + CRLF) diff_str = buf.getvalue().encode('utf-8') req.send_header('Content-Length', len(diff_str)) req.end_headers() req.write(diff_str) raise RequestDone
def notify(self, action, page, version=None, time=None, comment=None, author=None, ipnr=None, redirect=False, old_name=None): self.page = page self.change_author = author self.time = time self.action = action self.version = version self.redirect = redirect self.old_name = old_name # self.env.log.debug("Notify Action: %s", action) # self.env.log.debug("Page time: %r, %s", time, time) if action == "added": self.newwiki = True self.data['name'] = page.name self.data['old_name'] = old_name self.data['redirect'] = redirect self.data['text'] = page.text self.data['version'] = version self.data['author'] = author self.data['comment'] = comment self.data['ip'] = ipnr self.data['action'] = action self.data['link'] = self.env.abs_href.wiki(page.name) self.data['linkdiff'] = self.env.abs_href.wiki(page.name, action='diff', version=page.version) if page.version > 0 and action == 'modified': diff = diff_header % {'name': self.page.name, 'version': self.page.version, 'oldversion': self.page.version - 1 } oldpage = WikiPage(self.env, page.name, page.version - 1) self.data["oldversion"] = oldpage.version self.data["oldtext"] = oldpage.text for line in unified_diff(oldpage.text.splitlines(), page.text.splitlines(), context=3): diff += "%s\n" % line self.wikidiff = diff self.data["wikidiff"] = self.wikidiff self.subject = self.format_subject(action.replace('_', ' ')) config = self.config['notification'] if not config.getbool('smtp_enabled'): return self.replyto_email = config.get('smtp_replyto') self.from_email = self.from_email or self.replyto_email if not self.from_email and not self.replyto_email: message = tag( tag.p(_('Unable to send email due to identity crisis.')), # convert explicitly to `Fragment` to avoid breaking message # when passing `LazyProxy` object to `Fragment` tag.p(to_fragment(tag_( "Neither %(from_)s nor %(reply_to)s are specified in the " "configuration.", from_=tag.strong('[notification] smtp_from'), reply_to=tag.strong('[notification] smtp_replyto'))))) raise TracError(message, _('SMTP Notification Error')) Notify.notify(self, page.name)
def _get_userlog(self, req, db, user, sort): mimeview = Mimeview(self.env) repos = self.env.get_repository() diff_options = get_diff_options(req) cursor = db.cursor() cursor.execute("SELECT rev, time, message FROM revision " "WHERE author='%s' ORDER BY time %s" % (user, sort)) # Have to sort by time because rev is a text field # and sorts lexicographically rather than numerically changesets = [] for rev, time, message in cursor: if self.wiki_format_messages: message = wiki_to_html(message, self.env, req, escape_newlines=True) else: message = html.PRE(message) prev = repos.get_node('/', rev).get_previous() if prev: prev_rev = prev[1] else: prev_rev = rev diffs = [] changes = repos.get_changes(old_path='/', old_rev=prev_rev, new_path='/', new_rev=rev) for old_node, new_node, kind, change in changes: if kind == Node.DIRECTORY: if change == Changeset.ADD: diffs.append(('%s added' % new_node.path, '')) elif change == Changeset.DELETE: diffs.append(('%s deleted' % old_node.path, '')) continue new_content = old_content = '' new_node_info = old_node_info = ('','') if old_node: old_content = old_node.get_content().read() if is_binary(old_content): continue old_node_info = (old_node.path, old_node.rev) old_content = mimeview.to_unicode(old_content, old_node.content_type) if new_node: new_content = new_node.get_content().read() if is_binary(new_content): continue new_node_info = (new_node.path, new_node.rev) new_path = new_node.path new_content = mimeview.to_unicode(new_content, new_node.content_type) else: old_node_path = repos.normalize_path(old_node.path) diff_old_path = repos.normalize_path('/') new_path = posixpath.join('/', old_node_path[len(diff_old_path)+1:]) if old_content != new_content: context = 3 options = diff_options[1] for option in options: if option.startswith('-U'): context = int(option[2:]) break if not old_node_info[0]: old_node_info = new_node_info # support for 'A'dd changes diff = 'Index: ' + new_path + CRLF diff += '=' * 67 + CRLF diff += '--- %s (revision %s)' % old_node_info + CRLF diff += '+++ %s (revision %s)' % new_node_info + CRLF for line in unified_diff(old_content.splitlines(), new_content.splitlines(), context, ignore_blank_lines='-B' in options, ignore_case='-i' in options, ignore_space_changes='-b' in options): diff += line + CRLF if change == Changeset.ADD: diffs.append(('%s added' % (new_node.path,), diff)) elif change == Changeset.DELETE: diffs.append(('%s deleted' % (old_node.path,), diff)) else: diffs.append(('%s edited' % (new_node.path,), diff)) changesets.append((int(rev), format_datetime(time), message, diffs)) return changesets