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 _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 filter_stream(self, req, method, filename, stream, data): action = req.args.get('action', '') if filename == 'browser.html' and action == 'edit': req.perm.require('REPOSITORY_MODIFY') # NB TracBrowserOps already inserts javascript and css we need # So only add css/javascript needed solely by the editor if data['file'] and data['file']['preview']['rendered']: max_edit_size = self.max_edit_size data['max_edit_size'] = max_edit_size # Discard rendered table, replace with textarea of file contents # This means reading the file from the repository again # N.B. If a file is rendered as something other than a table # e.g. due to PreCodeBrowserPlugin this code won't trigger # Retrieve the same node that BrowserModule.process_request() # used to render the preview. # At this point reponame has been removed from data['path'] # and repos has already been determined repos = data['repos'] path = data['path'] rev = data['rev'] node = repos.get_node(path, rev) # If node is too large then don't allow editing, abort if max_edit_size > 0 and node.content_length > max_edit_size: return stream # Open the node and read it node_file = node.get_content() node_data = node_file.read() # Discover the mime type and character encoding of the node # Try in order # - svn:mime-type property # - detect from file name and content (BOM) # - use configured default for Trac mime_view = Mimeview(self.env) mime_type = node.content_type \ or mime_view.get_mimetype(node.name, node_data) \ or 'text/plain' encoding = mime_view.get_charset(node_data, mime_type) # Populate template data content = mime_view.to_unicode(node_data, mime_type, encoding) data['file_content'] = content data['file_encoding'] = encoding # Replace the already rendered preview with a form and textarea bsops_stream = Chrome(self.env).render_template(req, 'file_edit.html', data, fragment=True) transf = Transformer('//div[@id="preview"]' '/table[@class="code"]') stream |= transf.replace( bsops_stream.select('//div[@id="bsop_edit"]')) return stream
def filter_stream(self, req, method, filename, stream, data): action = req.args.get('action', '') if filename == 'browser.html' and action == 'edit': req.perm.require('REPOSITORY_MODIFY') # NB TracBrowserOps already inserts javascript and css we need # So only add css/javascript needed solely by the editor if data['file'] and data['file']['preview']['rendered']: max_edit_size = self.max_edit_size data['max_edit_size'] = max_edit_size # Discard rendered table, replace with textarea of file contents # This means reading the file from the repository again # N.B. If a file is rendered as something other than a table # e.g. due to PreCodeBrowserPlugin this code won't trigger # Retrieve the same node that BrowserModule.process_request() # used to render the preview. # At this point reponame has been removed from data['path'] # and repos has already been determined repos = data['repos'] path = data['path'] rev = data['rev'] node = repos.get_node(path, rev) # If node is too large then don't allow editing, abort if max_edit_size > 0 and node.content_length > max_edit_size: return stream # Open the node and read it node_file = node.get_content() node_data = node_file.read() # Discover the mime type and character encoding of the node # Try in order # - svn:mime-type property # - detect from file name and content (BOM) # - use configured default for Trac mime_view = Mimeview(self.env) mime_type = node.content_type \ or mime_view.get_mimetype(node.name, node_data) \ or 'text/plain' encoding = mime_view.get_charset(node_data, mime_type) # Populate template data content = mime_view.to_unicode(node_data, mime_type, encoding) data['file_content'] = content data['file_encoding'] = encoding # Replace the already rendered preview with a form and textarea bsops_stream = Chrome(self.env).render_template( req, 'file_edit.html', data, fragment=True) transf = Transformer('//div[@id="preview"]' '/table[@class="code"]') stream |= transf.replace( bsops_stream.select('//div[@id="bsop_edit"]')) return stream
def _content_changes(old_node, new_node): """Returns the list of differences. The list is empty when no differences between comparable files are detected, but the return value is None for non-comparable files. """ mview = Mimeview(self.env) if mview.is_binary(old_node.content_type, old_node.path): return None if mview.is_binary(new_node.content_type, new_node.path): return None old_content = old_node.get_content().read() if mview.is_binary(content=old_content): return None new_content = new_node.get_content().read() if mview.is_binary(content=new_content): return None old_content = mview.to_unicode(old_content, old_node.content_type) new_content = mview.to_unicode(new_content, new_node.content_type) if old_content != new_content: context = options.get('contextlines', 3) if context < 0: context = None tabwidth = self.config['diff'].getint('tab_width') or \ self.config['mimeviewer'].getint('tab_width', 8) ignore_blank_lines = options.get('ignoreblanklines') ignore_case = options.get('ignorecase') ignore_space = options.get('ignorewhitespace') return diff_blocks(old_content.splitlines(), new_content.splitlines(), context, tabwidth, ignore_blank_lines=ignore_blank_lines, ignore_case=ignore_case, ignore_space_changes=ignore_space) else: return []
def _content_changes(old_node, new_node): """Returns the list of differences. The list is empty when no differences between comparable files are detected, but the return value is None for non-comparable files. """ old_content = old_node.get_content().read() if is_binary(old_content): return None new_content = new_node.get_content().read() if is_binary(new_content): return None mview = Mimeview(self.env) old_content = mview.to_unicode(old_content, old_node.content_type) new_content = mview.to_unicode(new_content, new_node.content_type) 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 context < 0: context = None tabwidth = self.config['diff'].getint('tab_width') or \ self.config['mimeviewer'].getint('tab_width', 8) return hdf_diff(old_content.splitlines(), new_content.splitlines(), context, tabwidth, ignore_blank_lines='-B' in options, ignore_case='-i' in options, ignore_space_changes='-b' in options) else: return []
def _content_changes(old_node, new_node): """Returns the list of differences. The list is empty when no differences between comparable files are detected, but the return value is None for non-comparable files. """ old_content = old_node.get_content().read() if is_binary(old_content): return None new_content = new_node.get_content().read() if is_binary(new_content): return None mview = Mimeview(self.env) old_content = mview.to_unicode(old_content, old_node.content_type) new_content = mview.to_unicode(new_content, new_node.content_type) 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 context < 0: context = None tabwidth = self.config['diff'].getint('tab_width') or \ self.config['mimeviewer'].getint('tab_width', 8) return hdf_diff(old_content.splitlines(), new_content.splitlines(), context, tabwidth, ignore_blank_lines='-B' in options, ignore_case='-i' in options, ignore_space_changes='-b' in options) else: return []
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 _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