def get_timeline_events(self, req, start, stop, filters): if 'changeset' in filters: format = req.args.get('format') wiki_format = self.wiki_format_messages show_files = self.timeline_show_files db = self.env.get_db_cnx() repos = self.env.get_repository(req.authname) for chgset in repos.get_changesets(start, stop): message = chgset.message or '--' if wiki_format: shortlog = wiki_to_oneliner(message, self.env, db, shorten=True) else: shortlog = shorten_line(message) if format == 'rss': title = Markup('Changeset [%s]: %s', chgset.rev, shortlog) href = req.abs_href.changeset(chgset.rev) if wiki_format: message = wiki_to_html(message, self.env, req, db, absurls=True) else: message = html.PRE(message) else: title = Markup('Changeset <em>[%s]</em> by %s', chgset.rev, chgset.author) href = req.href.changeset(chgset.rev) if wiki_format: if self.timeline_long_messages: message = wiki_to_html(message, self.env, req, db, absurls=True) else: message = wiki_to_oneliner(message, self.env, db, shorten=True) else: message = shortlog if show_files and req.perm.has_permission('BROWSER_VIEW'): files = [] for chg in chgset.get_changes(): if show_files > 0 and len(files) >= show_files: files.append(html.LI(Markup('…'))) break files.append(html.LI(html.DIV(class_=chg[2]), chg[0] or '/')) message = html.UL(files, class_="changes") + message yield 'changeset', href, title, chgset.date, chgset.author,\ message
def expand_macro(self, formatter, name, content): if content: arg = content.strip().split() doc = getattr(TracAdmin, "_help_" + arg[0], None) if doc is None: cmd_mgr = AdminCommandManager(self.env) doc = cmd_mgr.get_command_help(arg) if not doc: raise TracError('Unknown trac-admin command "%s"' % content) else: doc = TracAdmin.all_docs(self.env) buf = StringIO.StringIO() TracAdmin.print_doc(doc, buf, long=True) return html.PRE(buf.getvalue().decode('utf-8'), class_='wiki')
def get_changes(env, repos, revs, full=None, req=None, format=None): db = env.get_db_cnx() changes = {} for rev in revs: try: changeset = repos.get_changeset(rev) except NoSuchChangeset: changes[rev] = {} continue wiki_format = env.config['changeset'].getbool('wiki_format_messages') message = changeset.message or '--' absurls = (format == 'rss') if wiki_format: shortlog = wiki_to_oneliner(message, env, db, shorten=True, absurls=absurls) else: shortlog = Markup.escape(shorten_line(message)) if full: if wiki_format: message = wiki_to_html(message, env, req, db, absurls=absurls, escape_newlines=True) else: message = html.PRE(message) else: message = shortlog if format == 'rss': if isinstance(shortlog, Markup): shortlog = shortlog.plaintext(keeplinebreaks=False) message = unicode(message) changes[rev] = { 'date_seconds': changeset.date, 'date': format_datetime(changeset.date), 'age': pretty_timedelta(changeset.date), 'author': changeset.author or 'anonymous', 'message': message, 'shortlog': shortlog, } return changes
def _render_file(self, req, repos, node, rev=None): req.perm.assert_permission('FILE_VIEW') mimeview = Mimeview(self.env) # MIME type detection content = node.get_content() chunk = content.read(CHUNK_SIZE) mime_type = node.content_type if not mime_type or mime_type == 'application/octet-stream': mime_type = mimeview.get_mimetype(node.name, chunk) or \ mime_type or 'text/plain' # Eventually send the file directly format = req.args.get('format') if format in ['raw', 'txt']: req.send_response(200) req.send_header('Content-Type', format == 'txt' and 'text/plain' or mime_type) req.send_header('Content-Length', node.content_length) req.send_header('Last-Modified', http_date(node.last_modified)) req.end_headers() while 1: if not chunk: raise RequestDone req.write(chunk) chunk = content.read(CHUNK_SIZE) else: # The changeset corresponding to the last change on `node` # is more interesting than the `rev` changeset. changeset = repos.get_changeset(node.rev) message = changeset.message or '--' if self.config['changeset'].getbool('wiki_format_messages'): message = wiki_to_html(message, self.env, req, escape_newlines=True) else: message = html.PRE(message) req.hdf['file'] = { 'rev': node.rev, 'changeset_href': req.href.changeset(node.rev), 'date': format_datetime(changeset.date), 'age': pretty_timedelta(changeset.date), 'size': pretty_size(node.content_length), 'author': changeset.author or 'anonymous', 'message': message } # add ''Plain Text'' alternate link if needed if not is_binary(chunk) and mime_type != 'text/plain': plain_href = req.href.browser(node.path, rev=rev, format='txt') add_link(req, 'alternate', plain_href, 'Plain Text', 'text/plain') # add ''Original Format'' alternate link (always) raw_href = req.href.browser(node.path, rev=rev, format='raw') add_link(req, 'alternate', raw_href, u'Format original', mime_type) self.log.debug( "Rendering preview of node %s@%s with mime-type %s" % (node.name, str(rev), mime_type)) del content # the remainder of that content is not needed req.hdf['file'] = mimeview.preview_to_hdf( req, node.get_content(), node.get_content_length(), mime_type, node.created_path, raw_href, annotations=['lineno']) add_stylesheet(req, 'common/css/code.css')
def _render_file(self, req, repos, node, rev=None): req.perm.assert_permission('FILE_VIEW') mimeview = Mimeview(self.env) # MIME type detection content = node.get_content() chunk = content.read(CHUNK_SIZE) mime_type = node.content_type if not mime_type or mime_type == 'application/octet-stream': mime_type = mimeview.get_mimetype(node.name, chunk) or \ mime_type or 'text/plain' # Eventually send the file directly format = req.args.get('format') if format in ['raw', 'txt']: req.send_response(200) req.send_header('Content-Type', format == 'txt' and 'text/plain' or mime_type) req.send_header('Content-Length', node.content_length) req.send_header('Last-Modified', http_date(node.last_modified)) if not self.render_unsafe_content: # Force browser to download files instead of rendering # them, since they might contain malicious code enabling # XSS attacks req.send_header('Content-Disposition', 'attachment') req.end_headers() while 1: if not chunk: raise RequestDone req.write(chunk) chunk = content.read(CHUNK_SIZE) else: # The changeset corresponding to the last change on `node` # is more interesting than the `rev` changeset. changeset = repos.get_changeset(node.rev) message = changeset.message or '--' if self.config['changeset'].getbool('wiki_format_messages'): message = wiki_to_html(message, self.env, req, escape_newlines=True) else: message = html.PRE(message) ZhUnit = { 'second': u'秒', 'seconds': u'秒', 'minute': u'分钟', 'minutes': u'分钟', 'hour': u'小时', 'hours': u'小时', 'day': u'天', 'days': u'天', 'year': u'年', 'years': u'年', 'month': u'月', 'months': u'月' } tempTime = pretty_timedelta(changeset.date) numAndUnit = tempTime.split(' ') numAndUnit[1] = ZhUnit.get(numAndUnit[1], numAndUnit[1]) ZhAge = ' '.join(numAndUnit) req.hdf['file'] = { 'rev': node.rev, 'changeset_href': req.href.changeset(node.rev), 'date': format_datetime(changeset.date), 'age': ZhAge, 'size': pretty_size(node.content_length), 'author': changeset.author or 'anonymous', 'message': message } # add ''Plain Text'' alternate link if needed if not is_binary(chunk) and mime_type != 'text/plain': plain_href = req.href.browser(node.path, rev=rev, format='txt') add_link(req, 'alternate', plain_href, 'Plain Text', 'text/plain') # add ''Original Format'' alternate link (always) raw_href = req.href.browser(node.path, rev=rev, format='raw') add_link(req, 'alternate', raw_href, 'Original Format', mime_type) self.log.debug( "Rendering preview of node %s@%s with mime-type %s" % (node.name, str(rev), mime_type)) del content # the remainder of that content is not needed req.hdf['file'] = mimeview.preview_to_hdf( req, node.get_content(), node.get_content_length(), mime_type, node.created_path, raw_href, annotations=['lineno']) add_stylesheet(req, 'common/css/code.css')
def process_request(self, req): """The appropriate mode of operation is inferred from the request parameters: * If `new_path` and `old_path` are equal (or `old_path` is omitted) and `new` and `old` are equal (or `old` is omitted), then we're about to view a revision Changeset: `chgset` is True. Furthermore, if the path is not the root, the changeset is ''restricted'' to that path (only the changes affecting that path, its children or its ancestor directories will be shown). * In any other case, the set of changes corresponds to arbitrary differences between path@rev pairs. If `new_path` and `old_path` are equal, the ''restricted'' flag will also be set, meaning in this case that the differences between two revisions are restricted to those occurring on that path. In any case, either path@rev pairs must exist. """ req.perm.assert_permission('CHANGESET_VIEW') # -- retrieve arguments new_path = req.args.get('new_path') new = req.args.get('new') old_path = req.args.get('old_path') old = req.args.get('old') if old and '@' in old: old_path, old = unescape(old).split('@') if new and '@' in new: new_path, new = unescape(new).split('@') # -- normalize and check for special case repos = self.env.get_repository(req.authname) new_path = repos.normalize_path(new_path) new = repos.normalize_rev(new) repos.authz.assert_permission_for_changeset(new) old_path = repos.normalize_path(old_path or new_path) old = repos.normalize_rev(old or new) if old_path == new_path and old == new: # revert to Changeset old_path = old = None diff_options = get_diff_options(req) # -- setup the `chgset` and `restricted` flags, see docstring above. chgset = not old and not old_path if chgset: restricted = new_path not in ('', '/') # (subset or not) else: restricted = old_path == new_path # (same path or not) # -- redirect if changing the diff options if req.args.has_key('update'): if chgset: if restricted: req.redirect(req.href.changeset(new, new_path)) else: req.redirect(req.href.changeset(new)) else: req.redirect(req.href.changeset(new, new_path, old=old, old_path=old_path)) # -- preparing the diff arguments if chgset: prev = repos.get_node(new_path, new).get_previous() if prev: prev_path, prev_rev = prev[:2] else: prev_path, prev_rev = new_path, repos.previous_rev(new) diff_args = DiffArgs(old_path=prev_path, old_rev=prev_rev, new_path=new_path, new_rev=new) else: if not new: new = repos.youngest_rev elif not old: old = repos.youngest_rev if not old_path: old_path = new_path diff_args = DiffArgs(old_path=old_path, old_rev=old, new_path=new_path, new_rev=new) if chgset: chgset = repos.get_changeset(new) message = chgset.message or '--' if self.wiki_format_messages: message = wiki_to_html(message, self.env, req, escape_newlines=True) else: message = html.PRE(message) req.check_modified(chgset.date, [ diff_options[0], ''.join(diff_options[1]), repos.name, repos.rev_older_than(new, repos.youngest_rev), message, pretty_timedelta(chgset.date, None, 3600)]) else: message = None # FIXME: what date should we choose for a diff? req.hdf['changeset'] = diff_args format = req.args.get('format') if format in ['diff', 'zip']: req.perm.assert_permission('FILE_VIEW') # choosing an appropriate filename rpath = new_path.replace('/','_') if chgset: if restricted: filename = 'changeset_%s_r%s' % (rpath, new) else: filename = 'changeset_r%s' % new else: if restricted: filename = 'diff-%s-from-r%s-to-r%s' \ % (rpath, old, new) elif old_path == '/': # special case for download (#238) filename = '%s-r%s' % (rpath, old) else: filename = 'diff-from-%s-r%s-to-%s-r%s' \ % (old_path.replace('/','_'), old, rpath, new) if format == 'diff': self._render_diff(req, filename, repos, diff_args, diff_options) return elif format == 'zip': self._render_zip(req, filename, repos, diff_args) return # -- HTML format self._render_html(req, repos, chgset, restricted, message, diff_args, diff_options) if chgset: diff_params = 'new=%s' % new else: diff_params = unicode_urlencode({'new_path': new_path, 'new': new, 'old_path': old_path, 'old': old}) add_link(req, 'alternate', '?format=diff&'+diff_params, 'Unified Diff', 'text/plain', 'diff') add_link(req, 'alternate', '?format=zip&'+diff_params, 'Zip Archive', 'application/zip', 'zip') add_stylesheet(req, 'common/css/changeset.css') add_stylesheet(req, 'common/css/diff.css') add_stylesheet(req, 'common/css/code.css') return 'changeset.cs', None
text.append('\n') text = str(''.join(text)) req.send_response(200) req.send_header('Content-Type', 'text/csv') req.send_header('Content-Length', str(len(text))) req.end_headers() req.write(text) return if not raw: format = { 'path': lambda x: html.A(x, href=req.href.browser(x)), 'rev': lambda x: html.A(x, href=req.href.changeset(x)), 'ticket': lambda x: html.A(x, href=req.href.ticket(x)), 'query': lambda x: html.PRE(x, style="padding: 0; margin: 0;"), 'time': lambda x: fmt_timestamp(x), } if trac.__version__ >= '0.12': format['time'] = lambda x: fmt_timestamp(x / 1000000.) format['base_path'] = format['path'] format['base_rev'] = format['rev'] format['changetime'] = format['time'] context = get_context(req) mimeview = Mimeview(self.env) def format_wiki_text(text):