Changeset 367

Show
Ignore:
Timestamp:
01/19/06 10:40:54 (3 years ago)
Author:
athomas
Message:

RepoSearchPlugin:

  • Added optional indexer which will speed up searches significantly.
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • reposearchplugin/0.9/tracreposearch/__init__.py

    r363 r367  
    1 # tracreposearch module 
    2 from tracreposearch import * 
     1from search import * 
  • reposearchplugin/0.9/tracreposearch/search.py

    r366 r367  
    1313    implements(ISearchSource, IPermissionRequestor) 
    1414 
    15     # IPermissionRequestor methods 
    16     def get_permission_actions(self): 
    17         yield 'REPO_SEARCH' 
     15    def __init__(self): 
     16        from tracreposearch.indexer import Indexer 
     17        self.indexer = Indexer(self.env) 
    1818 
    19     # ISearchSource methods 
    20     def get_search_filters(self, req): 
    21         if req.perm.has_permission('REPO_SEARCH'): 
    22             yield ('repo', 'Source Repository', 0) 
    23  
    24     def get_search_results(self, req, query, filters): 
    25         if not req.perm.has_permission('REPO_SEARCH'): 
    26             return 
    27  
     19    def _get_filters(self): 
    2820        includes = [glob for glob in self.env.config.get('repo-search', 
    2921                   'include', '').split(os.path.pathsep) if glob] 
    3022        excludes = [glob for glob in self.env.config.get('repo-search', 
    3123                   'exclude', '').split(os.path.pathsep) if glob] 
     24        return (includes, excludes) 
    3225 
    33         repo = self.env.get_repository(req.authname) 
    34  
    35         query = query.split() 
    36         db = self.env.get_db_cnx() 
    37  
    38         self.env.log.debug(str(includes)) 
    39         self.env.log.debug(str(excludes)) 
     26    def walk_repo(self, repo): 
     27        """ Walk all nodes in the repo that match the filters. """ 
     28        includes, excludes = self._get_filters() 
    4029 
    4130        def searchable(path): 
     
    5039                    return 1 
    5140 
    52             return 1 
     41            return not include and not exclude 
     42 
     43        def do_walk(path): 
     44            node = repo.get_node(path) 
     45            basename = posixpath.basename(path) 
     46 
     47            if searchable(node.path): 
     48                yield node 
     49 
     50            if node.kind == Node.DIRECTORY: 
     51                for subnode in node.get_entries(): 
     52                    for result in do_walk(subnode.path): 
     53                        yield result 
     54 
     55        for node in do_walk('/'): 
     56            yield node 
     57 
     58    # IPermissionRequestor methods 
     59    def get_permission_actions(self): 
     60        yield 'REPO_SEARCH' 
     61 
     62    # ISearchSource methods 
     63    def get_search_filters(self, req): 
     64        if req.perm.has_permission('REPO_SEARCH'): 
     65            yield ('repo', 'Source Repository', 0) 
     66 
     67    def get_search_results(self, req, query, filters): 
     68        repo = self.env.get_repository(req.authname) 
     69        query = [term.lower() for term in query.split()] 
     70        db = self.env.get_db_cnx() 
     71        include, excludes = self._get_filters() 
     72 
     73        # Use indexer if possible, otherwise fall back on brute force search. 
     74        try: 
     75            self.indexer.reindex(repo) 
     76            walker = lambda repo, query: [repo.get_node(filename) for filename in self.indexer.find_words(query)] 
     77        except TracError: 
     78            def full_walker(repo, query): 
     79                for node in self.walk_repo(repo): 
     80                    # Search content 
     81                    matched = 1 
     82                    content = node.get_content().read().lower() 
     83                    for term in query: 
     84                        if term not in content: 
     85                            matched = 0 
     86                            break 
     87                    if matched: 
     88                        yield node 
     89 
     90            walker = full_walker 
     91 
     92        if not req.perm.has_permission('REPO_SEARCH'): 
     93            return 
    5394 
    5495        def match_name(name): 
     
    5899            return 1 
    59100 
    60         def walk_repo(path): 
    61             node = repo.get_node(path) 
    62             basename = posixpath.basename(path) 
    63  
     101        for node in walker(repo, query): 
     102            change = repo.get_changeset(node.rev) 
    64103            if node.kind == Node.DIRECTORY: 
    65                 if match_name(basename): 
    66                     change = repo.get_changeset(node.rev) 
    67                     yield (self.env.href.browser(path), 
    68                            path, change.date, change.author, 
    69                            'Directory') 
    70  
    71                 for subnode in node.get_entries(): 
    72                     for result in walk_repo(subnode.path): 
    73                         yield result 
    74             else: 
    75                 if not searchable(path): 
    76                     return 
    77  
    78                 # Search content 
    79                 match_content = 1 
    80                 content = node.get_content().read() 
    81                 for term in query: 
    82                     if term not in content: 
    83                         match_content = 0 
    84                         break 
    85                 if not (match_name(basename) or match_content): 
    86                     return 
    87                 change = repo.get_changeset(node.rev) 
    88104                yield (self.env.href.browser(path), 
    89105                       path, change.date, change.author, 
    90                        shorten_result(content, query)) 
    91  
    92         for result in walk_repo('/'): 
    93             yield result 
     106                       'Directory') 
     107            else: 
     108                yield (self.env.href.browser(node.path), 
     109                       node.path, change.date, change.author, 
     110                       shorten_result(node.get_content().read(), query))