def log_receiver (self, changed_paths, rev, author, date, log, pool): if not changed_paths: return # Store the copyfrom-information so we can follow the file/dir # through tags/banches/copy/renames. for newpath in changed_paths.keys(): change = changed_paths[newpath] if change.copyfrom_path: self.branch_info.setdefault(rev, []).append((change.copyfrom_path, newpath)) shortlog = util.shorten_line(util.wiki_escape_newline(log)) t = svn.core.svn_time_from_cstring(date, pool) / 1000000 gmt = time.gmtime(t) item = { 'rev' : rev, 'author' : author and util.escape(author) or 'None', 'date' : util.svn_date_to_string (date, pool), 'gmt' : time.strftime('%a, %d %b %Y %H:%M:%S GMT', gmt), 'log.raw' : util.escape(log), 'log' : wiki_to_oneliner(util.shorten_line(util.wiki_escape_newline(log)), self.req.hdf, self.env,self.db), 'shortlog' : util.escape(shortlog), 'file_href': self.env.href.browser(self.path, rev), 'changeset_href': self.env.href.changeset(rev) } self.log_info.insert (0, item)
def _changesethref_formatter(self, match, fullmatch): number = int(match[1:-1]) cursor = self.db.cursor () cursor.execute('SELECT message FROM revision WHERE rev=%d', number) row = cursor.fetchone () if not row: return '[<a class="missing" href="%s">%d</a>]' % (self._href.changeset(number), number) else: return '[<a title="%s" href="%s">%d</a>]' % ( util.escape(util.shorten_line(row[0])),self._href.changeset(number), number)
def _expand_module_link(self, text): sep = text.find(':') if sep == -1: return None, None module = text[:sep] args = text[sep+1:] if module in ['bug', 'ticket']: cursor = self.db.cursor () cursor.execute('SELECT summary,status FROM ticket WHERE id=%s', args) row = cursor.fetchone () if row: summary = util.escape(util.shorten_line(row[0])) if row[1] == 'new': return self._href.ticket(args), '%s:%s*' % (module, args), 0, 'NEW: ' + summary elif row[1] == 'closed': return self._href.ticket(args), '<del>%s:%s</del>' % (module, args), 0, 'CLOSED: ' + summary else: return self._href.ticket(args), '%s:%s' % (module, args), 0, summary else: return self._href.ticket(args), '%s:%s' % (module, args), 1, '' elif module == 'wiki': if not self.env._wiki_pages.has_key(args): return self._href.wiki(args), '%s:%s' % (module, args), 1, None else: return self._href.wiki(args), '%s:%s' % (module, args), 0, None elif module == 'report': return self._href.report(args), '%s:%s' % (module, args), 0, None elif module == 'changeset': cursor = self.db.cursor () cursor.execute('SELECT message FROM revision WHERE rev=%s', args) row = cursor.fetchone () if row: return self._href.changeset(args), '%s:%s' % (module,args), 0, util.escape(util.shorten_line(row[0])) else: return self._href.changeset(args), '%s:%s' % (module,args), 1, '' elif module == 'milestone': return self._href.milestone(args), '%s:%s' % (module, args), 0, None elif module == 'search': return self._href.search(args), '%s:%s' % (module, args), 0, None elif module in ['source', 'repos', 'browser']: rev = None match = re.search('([^#]+)#(.+)', args) if match: args = match.group(1) rev = match.group(2) if rev: return self._href.browser(args, rev), \ '%s:%s#%s' % (module, args, rev), 0, None else: return self._href.browser(args), '%s:%s' % (module, args), 0, None else: return None, None, 0, None
def _tickethref_formatter(self, match, fullmatch): number = int(match[1:]) cursor = self.db.cursor () cursor.execute('SELECT summary,status FROM ticket WHERE id=%s', number) row = cursor.fetchone () if not row: return '<a class="missing" href="%s">#%d</a>' % (self._href.ticket(number), number) else: summary = util.escape(util.shorten_line(row[0])) if row[1] == 'new': return '<a href="%s" title="NEW : %s">#%d*</a>' % (self._href.ticket(number), summary, number) elif row[1] == 'closed': return '<a href="%s" title="CLOSED : %s"><del>#%d</del></a>' % (self._href.ticket(number), summary, number) else: return '<a href="%s" title="%s">#%d</a>' % (self._href.ticket(number), summary, number)
def get_info(self, path, revision, rev_specified): """ Extracts information for a given path and revision """ # We need to really make sure it's an ordinary string. The FieldStorage # class provided by modpython might give us some strange string-like object # that svn doesn't like. path = str(path) try: root = svn.fs.revision_root(self.fs_ptr, revision, self.pool) except svn.core.SubversionException: raise util.TracError('Invalid revision number: %d' % revision) node_type = svn.fs.check_path(root, path, self.pool) if not node_type in [svn.core.svn_node_dir, svn.core.svn_node_file]: raise util.TracError('"%s": no such file or directory in revision %d' \ % (path, revision), 'No such file or directory') # Redirect to the file module if the requested path happens # to point to a regular file if svn.fs.is_file(root, path, self.pool): if rev_specified: self.req.redirect(self.env.href.file(path, revision)) else: self.req.redirect(self.env.href.log(path)) entries = svn.fs.dir_entries(root, path, self.pool) info = [] for item in entries.keys(): fullpath = posixpath.join(path, item) is_dir = svn.fs.is_dir(root, fullpath, self.pool) if is_dir: name = item + '/' fullpath = fullpath + '/' else: name = item created_rev = svn.fs.node_created_rev(root, fullpath, self.pool) date = svn.fs.revision_prop(self.fs_ptr, created_rev, svn.core.SVN_PROP_REVISION_DATE, self.pool) if date: date_seconds = svn.core.svn_time_from_cstring(date, self.pool) / 1000000 date = time.strftime('%x %X', time.localtime(date_seconds)) else: date_seconds = 0 date = '' author = svn.fs.revision_prop(self.fs_ptr, created_rev, svn.core.SVN_PROP_REVISION_AUTHOR, self.pool) change = svn.fs.revision_prop(self.fs_ptr, created_rev, svn.core.SVN_PROP_REVISION_LOG, self.pool) item = { 'name' : name, 'fullpath' : fullpath, 'created_rev' : created_rev, 'date' : date, 'date_seconds' : date_seconds, 'age' : util.pretty_age(date_seconds), 'is_dir' : is_dir, 'author' : author, 'change' : wiki_to_oneliner(util.shorten_line(util.wiki_escape_newline(change)), self.req.hdf, self.env,self.db), 'permission' : self.authzperm.has_permission(fullpath) } if rev_specified: item['log_href'] = self.env.href.log(fullpath, revision) if is_dir: item['browser_href'] = self.env.href.browser(fullpath, revision) else: item['browser_href'] = self.env.href.file(fullpath, revision) else: item['log_href'] = self.env.href.log(fullpath) if is_dir: item['browser_href'] = self.env.href.browser(fullpath) else: item['browser_href'] = self.env.href.file(fullpath) info.append(item) return info
def get_info (self, start, stop, maxrows, tickets, changeset, wiki, milestone): cursor = self.db.cursor () tickets = tickets and self.perm.has_permission(perm.TICKET_VIEW) changeset = changeset and self.perm.has_permission(perm.CHANGESET_VIEW) wiki = wiki and self.perm.has_permission(perm.WIKI_VIEW) milestone = milestone and self.perm.has_permission(perm.MILESTONE_VIEW) if tickets == changeset == wiki == milestone == 0: return [] CHANGESET = 1 NEW_TICKET = 2 CLOSED_TICKET = 3 REOPENED_TICKET = 4 WIKI = 5 MILESTONE = 6 q = [] if changeset: q.append("SELECT time, rev AS idata, '' AS tdata, 1 AS type, " " message, author " "FROM revision WHERE time>=%s AND time<=%s" % (start, stop)) if tickets: q.append("SELECT time, id AS idata, '' AS tdata, 2 AS type, " "summary AS message, reporter AS author " "FROM ticket WHERE time>=%s AND time<=%s" % (start, stop)) q.append("SELECT time, ticket AS idata, '' AS tdata, 4 AS type, " "'' AS message, author " "FROM ticket_change WHERE field='status' " "AND newvalue='reopened' AND time>=%s AND time<=%s" % (start, stop)) q.append("SELECT t1.time AS time, t1.ticket AS idata," " t2.newvalue AS tdata, 3 AS type," " t3.newvalue AS message, t1.author AS author" " FROM ticket_change t1" " INNER JOIN ticket_change t2 ON t1.ticket = t2.ticket" " AND t1.time = t2.time" " LEFT OUTER JOIN ticket_change t3 ON t1.time = t3.time" " AND t1.ticket = t3.ticket AND t3.field = 'comment'" " WHERE t1.field = 'status' AND t1.newvalue = 'closed'" " AND t2.field = 'resolution'" " AND t1.time >= %s AND t1.time <= %s" % (start,stop)) if wiki: q.append("SELECT time, -1 AS idata, name AS tdata, 5 AS type, " "comment AS message, author " "FROM wiki WHERE time>=%s AND time<=%s" % (start, stop)) if milestone: q.append("SELECT time, -1 AS idata, '' AS tdata, 6 AS type, " "name AS message, '' AS author " "FROM milestone WHERE time>=%s AND time<=%s" % (start, stop)) q_str = string.join(q, ' UNION ALL ') q_str += ' ORDER BY time DESC' if maxrows: q_str += ' LIMIT %d' % maxrows cursor.execute(q_str) # Make the data more HDF-friendly info = [] while 1: row = cursor.fetchone() if not row: break t = time.localtime(int(row['time'])) gmt = time.gmtime(int(row['time'])) item = {'time': time.strftime('%H:%M', t), 'date': time.strftime('%x', t), 'datetime': time.strftime('%a, %d %b %Y %H:%M:%S GMT', gmt), 'idata': int(row['idata']), 'tdata': row['tdata'], 'type': int(row['type']), 'message': row['message'] or '', 'author': util.escape(row['author'] or 'anonymous') } if item['type'] == CHANGESET: item['href'] = self.env.href.changeset(item['idata']) msg = item['message'] item['shortmsg'] = util.escape(util.shorten_line(msg)) item['msg_nowiki'] = util.escape(msg) item['msg_escwiki'] = util.escape(wiki_to_html(msg, self.req.hdf, self.env, self.db, absurls=1)) item['message'] = wiki_to_oneliner(msg, self.req.hdf, self.env, self.db,absurls=1) try: max_node = int(self.env.get_config('timeline', 'changeset_show_files', 0)) except ValueError, e: self.env.log.warning("Invalid 'changeset_show_files' value, " "please edit trac.ini : %s" % e) max_node = 0 if max_node != 0: cursor_node = self.db.cursor () cursor_node.execute("SELECT name, change " "FROM node_change WHERE rev=%d" % item['idata']) node_list = '' node_data = '' node_count = 0; while 1: row_node = cursor_node.fetchone() if not row_node: break if node_count != 0: node_list += ', ' if (max_node != -1) and (node_count >= max_node): node_list += '...' break if row_node['change'] == 'A': node_data = '<span class="diff-add">' + row_node['name'] + "</span>" elif row_node['change'] == 'M': node_data = '<span class="diff-mod">' + row_node['name'] + "</span>" elif row_node['change'] == 'D': node_data = '<span class="diff-rem">' + row_node['name'] + "</span>" node_list += node_data node_count += 1 item['node_list'] = node_list + ': ' elif item['type'] == WIKI: item['href'] = self.env.href.wiki(row['tdata']) item['message'] = wiki_to_oneliner(util.shorten_line(item['message']), self.req.hdf, self.env, self.db, absurls=1)
node_data = '<span class="diff-rem">' + row_node['name'] + "</span>" node_list += node_data node_count += 1 item['node_list'] = node_list + ': ' elif item['type'] == WIKI: item['href'] = self.env.href.wiki(row['tdata']) item['message'] = wiki_to_oneliner(util.shorten_line(item['message']), self.req.hdf, self.env, self.db, absurls=1) elif item['type'] == MILESTONE: item['href'] = self.env.href.milestone(item['message']) item['message'] = util.escape(item['message']) else: # TICKET item['href'] = self.env.href.ticket(item['idata']) msg = item['message'] item['shortmsg'] = util.escape(util.shorten_line(msg)) item['message'] = wiki_to_oneliner( util.shorten_line(item['message']), self.req.hdf, self.env, self.db, absurls=1) item['msg_escwiki'] = util.escape(wiki_to_html(msg, self.req.hdf, self.env, self.db, absurls=1)) # Kludges for RSS item['author.rss'] = item['author'] if item['author.rss'].find('@') == -1: item['author.rss'] = '' item['message.rss'] = util.escape(item['message'] or '') info.append(item)
elif item['type'] == WIKI: item['href'] = util.escape(self.env.href.wiki(row['tdata'])) item['message'] = wiki_to_oneliner(util.shorten_line( item['message']), self.req.hdf, self.env, self.db, absurls=1) elif item['type'] == MILESTONE: item['href'] = util.escape( self.env.href.milestone(item['message'])) item['message'] = util.escape(item['message']) else: # TICKET item['href'] = util.escape(self.env.href.ticket(item['idata'])) msg = item['message'] item['shortmsg'] = util.escape(util.shorten_line(msg)) item['message'] = wiki_to_oneliner(util.shorten_line( item['message']), self.req.hdf, self.env, self.db, absurls=1) item['msg_escwiki'] = util.escape( wiki_to_html(msg, self.req.hdf, self.env, self.db, absurls=1)) # Kludges for RSS item['author.rss'] = item['author'] if item['author.rss'].find('@') == -1:
def perform_query (self, query, changeset, tickets, wiki, page=0): if not query: return ([], 0) keywords = query.split(' ') if changeset: changeset = self.perm.has_permission(perm.CHANGESET_VIEW) if tickets: tickets = self.perm.has_permission(perm.TICKET_VIEW) if wiki: wiki = self.perm.has_permission(perm.WIKI_VIEW) if changeset == tickets == wiki == 0: return ([], 0) if len(keywords) == 1: kwd = keywords[0] redir = None # Prepending a '!' disables quickjump feature if kwd[0] == '!': keywords[0] = kwd[1:] query = query[1:] self.req.hdf.setValue('search.q', query) # Ticket quickjump elif kwd[0] == '#' and kwd[1:].isdigit(): redir = self.env.href.ticket(kwd[1:]) # Changeset quickjump elif kwd[0] == '[' and kwd[-1] == ']' and kwd[1:-1].isdigit(): redir = self.env.href.changeset(kwd[1:-1]) # Report quickjump elif kwd[0] == '{' and kwd[-1] == '}' and kwd[1:-1].isdigit(): redir = self.env.href.report(kwd[1:-1]) elif kwd[0].isupper() and kwd[1].islower(): r = "((^|(?<=[^A-Za-z]))[!]?[A-Z][a-z/]+(?:[A-Z][a-z/]+)+)" if re.match (r, kwd): redir = self.env.href.wiki(kwd) if redir: self.req.hdf.setValue('search.q', '') self.req.redirect(redir) elif len(query) < 3: raise TracError('Search query too short. ' 'Query must be at least 3 characters long.', 'Search Error') cursor = self.db.cursor () q = [] if changeset: q.append('SELECT 1 as type, message AS title, message, author, ' ' \'\' AS keywords, rev AS data, time,0 AS ver' ' FROM revision WHERE %s OR %s' % (self.query_to_sql(query, 'message'), self.query_to_sql(query, 'author'))) if tickets: q.append('SELECT DISTINCT 2 as type, a.summary AS title, ' ' a.description AS message, a.reporter AS author, ' ' a.keywords as keywords, a.id AS data, a.time as time, 0 AS ver' ' FROM ticket a LEFT JOIN ticket_change b ON a.id = b.ticket' ' WHERE (b.field=\'comment\' AND %s ) OR' ' %s OR %s OR %s OR %s OR %s' % (self.query_to_sql(query, 'b.newvalue'), self.query_to_sql(query, 'summary'), self.query_to_sql(query, 'keywords'), self.query_to_sql(query, 'description'), self.query_to_sql(query, 'reporter'), self.query_to_sql(query, 'cc'))) if wiki: q.append('SELECT 3 as type, text AS title, text AS message,' ' author, \'\' AS keywords, w1.name AS data, time,' ' w1.version as ver' ' FROM wiki w1, ' ' (SELECT name,max(version) AS ver ' ' FROM wiki GROUP BY name) w2' ' WHERE w1.version = w2.ver AND w1.name = w2.name AND' ' (%s OR %s OR %s) ' % (self.query_to_sql(query, 'w1.name'), self.query_to_sql(query, 'w1.author'), self.query_to_sql(query, 'w1.text'))) if not q: return [] q_str = string.join(q, ' UNION ALL ') q_str += ' ORDER BY 7 DESC LIMIT %d OFFSET %d' % \ (self.RESULTS_PER_PAGE + 1, self.RESULTS_PER_PAGE * page) self.log.debug("SQL Query: %s" % q_str) cursor.execute(q_str) # Make the data more HDF-friendly info = [] more = 0 while 1: row = cursor.fetchone() if not row: break if len(info) == self.RESULTS_PER_PAGE: more = 1 break msg = row['message'] t = time.localtime(int(row['time'])) item = {'type': int(row['type']), 'keywords': row['keywords'] or '', 'data': row['data'], 'title': escape(row['title'] or ''), 'datetime' : time.strftime('%c', t), 'author': escape(row['author'])} if item['type'] == 1: item['changeset_href'] = self.env.href.changeset(int(row['data'])) elif item['type'] == 2: item['ticket_href'] = self.env.href.ticket(int(row['data'])) elif item['type'] == 3: item['wiki_href'] = self.env.href.wiki(row['data']) item['shortmsg'] = escape(shorten_line(msg)) item['message'] = escape(self.shorten_result(msg, keywords)) info.append(item) return info, more