search.py
144 lines
| 5.5 KiB
| text/x-python
|
PythonLexer
r861 | # -*- coding: utf-8 -*- | |||
""" | ||||
rhodecode.controllers.search | ||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
r2646 | Search controller for RhodeCode | |||
r1203 | ||||
r861 | :created_on: Aug 7, 2010 | |||
:author: marcink | ||||
r1824 | :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com> | |||
r861 | :license: GPLv3, see COPYING for more details. | |||
""" | ||||
r1206 | # This program is free software: you can redistribute it and/or modify | |||
# it under the terms of the GNU General Public License as published by | ||||
# the Free Software Foundation, either version 3 of the License, or | ||||
# (at your option) any later version. | ||||
r1203 | # | |||
r547 | # This program is distributed in the hope that it will be useful, | |||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
# GNU General Public License for more details. | ||||
r1203 | # | |||
r547 | # You should have received a copy of the GNU General Public License | |||
r1206 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
r861 | import logging | |||
import traceback | ||||
r2913 | import urllib | |||
r861 | from pylons.i18n.translation import _ | |||
r1995 | from pylons import request, config, tmpl_context as c | |||
r861 | ||||
r3776 | from whoosh.index import open_dir, EmptyIndexError | |||
from whoosh.qparser import QueryParser, QueryParserError | ||||
from whoosh.query import Phrase, Wildcard, Term, Prefix | ||||
from webhelpers.util import update_params | ||||
r547 | from rhodecode.lib.auth import LoginRequired | |||
Mads Kiilerich
|
r3289 | from rhodecode.lib.base import BaseRepoController, render | ||
r2646 | from rhodecode.lib.indexers import CHGSETS_SCHEMA, SCHEMA, CHGSET_IDX_NAME, \ | |||
IDX_NAME, WhooshResultWrapper | ||||
r2319 | from rhodecode.model.repo import RepoModel | |||
r2845 | from rhodecode.lib.utils2 import safe_str, safe_int | |||
r3776 | from rhodecode.lib.helpers import Page | |||
r2913 | ||||
r547 | log = logging.getLogger(__name__) | |||
r1212 | ||||
Mads Kiilerich
|
r3289 | class SearchController(BaseRepoController): | ||
r547 | ||||
def __before__(self): | ||||
r688 | super(SearchController, self).__before__() | |||
r547 | ||||
r3749 | @LoginRequired() | |||
Mads Kiilerich
|
r3289 | def index(self, repo_name=None): | ||
c.repo_name = repo_name | ||||
r547 | c.formated_results = [] | |||
c.runtime = '' | ||||
c.cur_query = request.GET.get('q', None) | ||||
Indra Talip
|
r2640 | c.cur_type = request.GET.get('type', 'content') | ||
r1212 | c.cur_search = search_type = {'content': 'content', | |||
Indra Talip
|
r2640 | 'commit': 'message', | ||
r1212 | 'path': 'path', | |||
r2646 | 'repository': 'repository' | |||
}.get(c.cur_type, 'content') | ||||
r556 | ||||
Indra Talip
|
r2640 | index_name = { | ||
'content': IDX_NAME, | ||||
'commit': CHGSET_IDX_NAME, | ||||
r2646 | 'path': IDX_NAME | |||
}.get(c.cur_type, IDX_NAME) | ||||
Indra Talip
|
r2640 | |||
schema_defn = { | ||||
'content': SCHEMA, | ||||
'commit': CHGSETS_SCHEMA, | ||||
r2646 | 'path': SCHEMA | |||
}.get(c.cur_type, SCHEMA) | ||||
Indra Talip
|
r2640 | |||
log.debug('IDX: %s' % index_name) | ||||
log.debug('SCHEMA: %s' % schema_defn) | ||||
r547 | if c.cur_query: | |||
cur_query = c.cur_query.lower() | ||||
Indra Talip
|
r2640 | log.debug(cur_query) | ||
r688 | ||||
r547 | if c.cur_query: | |||
r3748 | p = safe_int(request.GET.get('page', 1), 1) | |||
r547 | highlight_items = set() | |||
try: | ||||
r1212 | idx = open_dir(config['app_conf']['index_dir'], | |||
Indra Talip
|
r2640 | indexname=index_name) | ||
r547 | searcher = idx.searcher() | |||
Indra Talip
|
r2640 | qp = QueryParser(search_type, schema=schema_defn) | ||
r547 | if c.repo_name: | |||
cur_query = u'repository:%s %s' % (c.repo_name, cur_query) | ||||
try: | ||||
query = qp.parse(unicode(cur_query)) | ||||
r1995 | # extract words for highlight | |||
r547 | if isinstance(query, Phrase): | |||
highlight_items.update(query.words) | ||||
r1303 | elif isinstance(query, Prefix): | |||
highlight_items.add(query.text) | ||||
r547 | else: | |||
for i in query.all_terms(): | ||||
Indra Talip
|
r2640 | if i[0] in ['content', 'message']: | ||
r547 | highlight_items.add(i[1]) | |||
matcher = query.matcher(searcher) | ||||
r688 | ||||
Indra Talip
|
r2640 | log.debug('query: %s' % query) | ||
log.debug('hl terms: %s' % highlight_items) | ||||
r547 | results = searcher.search(query) | |||
res_ln = len(results) | ||||
r1995 | c.runtime = '%s results (%.3f seconds)' % ( | |||
res_ln, results.runtime | ||||
) | ||||
r688 | ||||
r547 | def url_generator(**kw): | |||
r2913 | q = urllib.quote(safe_str(c.cur_query)) | |||
r556 | return update_params("?q=%s&type=%s" \ | |||
r2913 | % (q, safe_str(c.cur_type)), **kw) | |||
r2319 | repo_location = RepoModel().repos_path | |||
r547 | c.formated_results = Page( | |||
r2319 | WhooshResultWrapper(search_type, searcher, matcher, | |||
highlight_items, repo_location), | ||||
r1995 | page=p, | |||
item_count=res_ln, | ||||
items_per_page=10, | ||||
url=url_generator | ||||
) | ||||
r688 | ||||
r547 | except QueryParserError: | |||
c.runtime = _('Invalid search query. Try quoting it.') | ||||
searcher.close() | ||||
except (EmptyIndexError, IOError): | ||||
log.error(traceback.format_exc()) | ||||
log.error('Empty Index data') | ||||
r861 | c.runtime = _('There is no index to search in. ' | |||
'Please run whoosh indexer') | ||||
r1303 | except (Exception): | |||
log.error(traceback.format_exc()) | ||||
c.runtime = _('An error occurred during this search operation') | ||||
r688 | ||||
r547 | # Return a rendered template | |||
return render('/search/search.html') | ||||