def get_search_results(self, req, query, filters): if not 'discussion' in filters: return # Create database context db = self.env.get_db_cnx() cursor = db.cursor() # Search in topics. columns = ('id', 'forum', 'time', 'subject', 'body', 'author') sql = "SELECT id, forum, time, subject, body, author FROM topic" \ " WHERE subject || body LIKE '%%%s%%'" % (query) self.log.debug(sql) cursor.execute(sql) for row in cursor: row = dict(zip(columns, row)) yield (self.env.href.discussion(row['forum'], row['id']) + '#-1', "topic: %d: %s" % (row['id'], util.shorten_line(row['subject'])), row['time'], row['author'], shorten_result(row['body'], query.split())) # Search in messages columns = ('id', 'forum', 'topic', 'time', 'author', 'body', 'subject') sql = "SELECT id, forum, topic, time, author, body, (SELECT" \ " subject FROM topic t WHERE t.id = message.topic) FROM message" \ " WHERE body LIKE '%%%s%%'" % (query) self.log.debug(sql) cursor.execute(sql) for row in cursor: row = dict(zip(columns, row)) yield (self.env.href.discussion(row['forum'], row['topic'], row['id']) + '#%s' % (row['id']), "message: %d: %s" % (row['id'], util.shorten_line(row['subject'])), row['time'], row['author'], shorten_result(row['body'], query.split()))
def get_search_results(self, req, terms, filters): """ Search through requirements. The search term may be <x y z> or x-y-z; both are interpreted as component, fp, and object. """ if not 'requirement' in filters: return if re.match(r'^([a-zA-Z_\d]+)-([a-zA-Z_\d]+)-([a-zA-Z_\d]+)$', terms[0]): terms = string.split(terms[0], '-') db = self.env.get_db_cnx() sql, args = search_to_sql(db, ['b.newvalue'], terms) sql2, args2 = search_to_sql(db, ['a.component', 'a.fp', 'a.object', 'a.description', 'a.creator'], terms) cursor = db.cursor() cursor.execute("SELECT DISTINCT a.component, a.fp, a.object, " "a.description, a.creator, a.time " "FROM requirement a " "LEFT JOIN requirement_change b " "ON a.component = b.component AND a.fp = b.fp AND a.object = b.object " "WHERE (b.field='comment' AND %s ) OR %s" % (sql, sql2), args + args2) for component, fp, object, desc, creator, date in cursor: requirement = '<%s %s %s> ' % (component, fp, object) yield (req.href.requirement('%s-%s-%s' % (component, fp, object)), requirement + shorten_line(desc), date, creator, shorten_result(desc, terms))
def get_search_results(self, req, query, filters): if not "discussion" in filters: return # Create database context db = self.env.get_db_cnx() cursor = db.cursor() # Search in topics. columns = ("id", "forum", "time", "subject", "body", "author") sql = "SELECT id, forum, time, subject, body, author FROM topic" " WHERE subject || body LIKE '%%%s%%'" % ( query ) self.log.debug(sql) cursor.execute(sql) for row in cursor: row = dict(zip(columns, row)) yield ( self.env.href.discussion(row["forum"], row["id"]) + "#-1", "topic: %d: %s" % (row["id"], util.shorten_line(row["subject"])), row["time"], row["author"], shorten_result(row["body"], query.split()), ) # Search in messages columns = ("id", "forum", "topic", "time", "author", "body", "subject") sql = ( "SELECT id, forum, topic, time, author, body, (SELECT" " subject FROM topic t WHERE t.id = message.topic) FROM message" " WHERE body LIKE '%%%s%%'" % (query) ) self.log.debug(sql) cursor.execute(sql) for row in cursor: row = dict(zip(columns, row)) yield ( self.env.href.discussion(row["forum"], row["topic"], row["id"]) + "#%s" % (row["id"]), "message: %d: %s" % (row["id"], util.shorten_line(row["subject"])), row["time"], row["author"], shorten_result(row["body"], query.split()), )
def get_search_results(self, req, keywords, filters): if not 'discussion' in filters: return # Create database context db = self.env.get_db_cnx() cursor = db.cursor() # Search in topics. query = ' '.join(keywords) columns = ('id', 'forum', 'time', 'subject', 'body', 'author') sql = "SELECT id, forum, time, subject, body, author FROM topic" \ " WHERE subject || body LIKE '%%%s%%'" % (query) self.log.debug(sql) cursor.execute(sql) for row in cursor: row = dict(zip(columns, row)) yield (req.href.discussion(row['forum'], row['id']) + '#-1', "topic: %d: %s" % (row['id'], util.shorten_line(row['subject'])), row['time'], row['author'], shorten_result(row['body'], [query])) # Search in messages columns = ('id', 'forum', 'topic', 'time', 'author', 'body', 'subject') sql = "SELECT m.id, m.forum, m.topic, m.time, m.author, m.body," \ " t.subject FROM message m LEFT JOIN (SELECT subject, id FROM" \ " topic) t ON t.id = m.topic WHERE body LIKE '%%%s%%'" \ % (query) self.log.debug(sql) cursor.execute(sql) for row in cursor: row = dict(zip(columns, row)) yield (req.href.discussion(row['forum'], row['topic'], row['id']) + '#%s' % (row['id']), "message: %d: %s" % (row['id'], util.shorten_line(row['subject'])), row['time'], row['author'], shorten_result(row['body'], [query]))
def get_search_results(self, req, terms, filters): if not 'changeset' in filters: return repos = self.env.get_repository(req.authname) db = self.env.get_db_cnx() sql, args = search_to_sql(db, ['message', 'author'], terms) cursor = db.cursor() cursor.execute("SELECT rev,time,author,message " "FROM revision WHERE " + sql, args) for rev, date, author, log in cursor: if not repos.authz.has_permission_for_changeset(rev): continue yield (req.href.changeset(rev), '[%s]: %s' % (rev, shorten_line(log)), date, author, shorten_result(log, terms))
def get_search_results(self, req, query, filters): if not 'changeset' in filters: return authzperm = SubversionAuthorizer(self.env, req.authname) db = self.env.get_db_cnx() sql, args = query_to_sql(db, query, 'message||author') cursor = db.cursor() cursor.execute("SELECT rev,time,author,message " "FROM revision WHERE " + sql, args) for rev, date, author, log in cursor: if not authzperm.has_permission_for_changeset(rev): continue yield (self.env.href.changeset(rev), '[%s]: %s' % (rev, util.shorten_line(log)), date, author, shorten_result(log, query.split()))
def get_search_results(self, req, terms, filters): if not 'wiki' in filters: return db = self.env.get_db_cnx() sql_query, args = search_to_sql(db, ['w1.name', 'w1.author', 'w1.text'], terms) cursor = db.cursor() cursor.execute("SELECT w1.name,w1.time,w1.author,w1.text " "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 " + sql_query, args) for name, date, author, text in cursor: yield (req.href.wiki(name), '%s: %s' % (name, shorten_line(text)), date, author, shorten_result(text, terms))
def get_search_results(self, req, query, filters): if not 'ticket' in filters: return db = self.env.get_db_cnx() sql = "SELECT DISTINCT a.summary,a.description,a.reporter, " \ "a.keywords,a.id,a.time FROM ticket a " \ "LEFT JOIN ticket_change b ON a.id = b.ticket " \ "WHERE (b.field='comment' AND %s ) OR %s" % \ (query_to_sql(db, query, 'b.newvalue'), query_to_sql(db, query, 'summary||keywords||description||reporter||cc')) cursor = db.cursor() cursor.execute(sql) for summary, desc, author, keywords, tid, date in cursor: yield (self.env.href.ticket(tid), '#%d: %s' % (tid, util.escape(util.shorten_line(summary))), date, author, util.escape(shorten_result(desc, query.split())))
def get_search_results(self, req, query, filters): if not 'ticket' in filters: return db = self.env.get_db_cnx() sql, args = query_to_sql(db, query, 'b.newvalue') sql2, args2 = query_to_sql(db, query, 'summary||keywords||description||reporter||cc') cursor = db.cursor() cursor.execute("SELECT DISTINCT a.summary,a.description,a.reporter, " "a.keywords,a.id,a.time FROM ticket a " "LEFT JOIN ticket_change b ON a.id = b.ticket " "WHERE (b.field='comment' AND %s ) OR %s" % (sql, sql2), args + args2) for summary,desc,author,keywords,tid,date in cursor: yield (self.env.href.ticket(tid), '#%d: %s' % (tid, util.shorten_line(summary)), date, author, shorten_result(desc, query.split()))
def get_search_results(self, req, query, filters): if not 'wiki' in filters: return db = self.env.get_db_cnx() sql = "SELECT w1.name,w1.time,w1.author,w1.text " \ "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" % \ (query_to_sql(db, query, 'w1.name||w1.author||w1.text'),) cursor = db.cursor() cursor.execute(sql) for name, date, author, text in cursor: yield (self.env.href.wiki(name), '%s: %s' % (name, escape(shorten_line(text))), date, author, escape(shorten_result(text, query.split())))
def get_search_results(self, req, terms, filters): if not 'wiki' in filters: return db = self.env.get_db_cnx() sql_query, args = search_to_sql(db, ['w1.name', 'w1.author', 'w1.text'], terms) cursor = db.cursor() cursor.execute( "SELECT w1.name,w1.time,w1.author,w1.text " "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 " + sql_query, args) for name, date, author, text in cursor: yield (req.href.wiki(name), '%s: %s' % (name, shorten_line(text)), date, author, shorten_result(text, terms))
def get_search_results(self, req, terms, filters): if not 'ticket' in filters: return db = self.env.get_db_cnx() sql, args = search_to_sql(db, ['b.newvalue'], terms) sql2, args2 = search_to_sql(db, ['summary', 'keywords', 'description', 'reporter', 'cc'], terms) cursor = db.cursor() cursor.execute("SELECT DISTINCT a.summary,a.description,a.reporter, " "a.keywords,a.id,a.time,a.status FROM ticket a " "LEFT JOIN ticket_change b ON a.id = b.ticket " "WHERE (b.field='comment' AND %s ) OR %s" % (sql, sql2), args + args2) for summary, desc, author, keywords, tid, date, status in cursor: ticket = '#%d: ' % tid if status == 'closed': ticket = Markup('<span style="text-decoration: line-through">' '#%s</span>: ', tid) yield (req.href.ticket(tid), ticket + shorten_line(summary), date, author, shorten_result(desc, terms))
def get_search_results(self, req, query, filters): if 'repo' not in filters or not req.perm.has_permission('REPO_SEARCH'): return if not self.indexer: raise TracError('RepoSearch plugin not configured correctly. ' 'You need to set "repo-search.indexer".') db = self.env.get_db_cnx() to_unicode = Mimeview(self.env).to_unicode self._update_index() for hit in self.framework.search(' '.join(query)): node = self.repo.get_node(hit.uri) change = self.repo.get_changeset(node.rev) if node.kind == Node.DIRECTORY: yield (self.env.href.browser(node.path), node.path, change.date, change.author, 'Directory') else: found = 0 content = to_unicode(node.get_content().read(), node.get_content_type()) for n, line in enumerate(content.splitlines()): line = line.lower() for q in query: idx = line.find(q) if idx != -1: found = n + 1 break if found: break yield (self.env.href.browser(node.path) + (found and '#L%i' % found or ''), node.path, change.date, change.author, shorten_result(content, query))
def get_search_results(self, req, query, filters): if not "wiki" in filters: return db = self.env.get_db_cnx() sql_query, args = query_to_sql(db, query, "w1.name||w1.author||w1.text") cursor = db.cursor() cursor.execute( "SELECT w1.name,w1.time,w1.author,w1.text " "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 " + sql_query, args, ) for name, date, author, text in cursor: yield ( self.env.href.wiki(name), "%s: %s" % (name, shorten_line(text)), date, author, shorten_result(text, query.split()), )
class TracRepoSearchPlugin(Component): """ Search the source repository. """ implements(ISearchSource, IPermissionRequestor) def _get_filters(self): includes = [ glob for glob in self.env.config.get( 'repo-search', 'include', '').split(os.path.pathsep) if glob ] excludes = [ glob for glob in self.env.config.get( 'repo-search', 'exclude', '').split(os.path.pathsep) if glob ] return (includes, excludes) def walk_repo(self, repo): """ Walk all nodes in the repo that match the filters. """ includes, excludes = self._get_filters() def searchable(path): # Exclude paths for exclude in excludes: if fnmatch(path, exclude): return 0 # Include paths for include in includes: if fnmatch(path, include): return 1 return not includes def do_walk(path): node = repo.get_node(path) basename = posixpath.basename(path) if searchable(node.path): yield node if node.kind == Node.DIRECTORY: for subnode in node.get_entries(): for result in do_walk(subnode.path): yield result for node in do_walk('/'): yield node # IPermissionRequestor methods def get_permission_actions(self): yield 'REPO_SEARCH' # ISearchSource methods def get_search_filters(self, req): if req.perm.has_permission('REPO_SEARCH'): yield ('repo', 'Source Repository', 0) def get_search_results(self, req, query, filters): if 'repo' not in filters: return repo = self.env.get_repository(req.authname) if not isinstance(query, list): query = query.split() query = [q.lower() for q in query] db = self.env.get_db_cnx() include, excludes = self._get_filters() to_unicode = Mimeview(self.env).to_unicode # Use indexer if possible, otherwise fall back on brute force search. try: from tracreposearch.indexer import Indexer self.indexer = Indexer(self.env) self.indexer.reindex() walker = lambda repo, query: [ repo.get_node(filename) for filename in self.indexer.find_words(query) ] except TracError, e: self.env.log.warning(e) self.env.log.warning('Falling back on full repository walk') def full_walker(repo, query): for node in self.walk_repo(repo): # Search content matched = 1 content = node.get_content() if not content: continue content = to_unicode(content.read().lower(), node.get_content_type()) for term in query: if term not in content: matched = 0 break if matched: yield node walker = full_walker if not req.perm.has_permission('REPO_SEARCH'): return def match_name(name): for term in query: if term not in name: return 0 return 1 for node in walker(repo, query): change = repo.get_changeset(node.rev) if node.kind == Node.DIRECTORY: yield (self.env.href.browser(node.path), node.path, change.date, change.author, 'Directory') else: found = 0 content = to_unicode(node.get_content().read(), node.get_content_type()) for n, line in enumerate(content.splitlines()): line = line.lower() for q in query: idx = line.find(q) if idx != -1: found = n + 1 break if found: break yield (self.env.href.browser(node.path) + (found and '#L%i' % found or ''), node.path, change.date, change.author, shorten_result(content, query))