bloodhound-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pe...@apache.org
Subject svn commit: r1457645 - in /incubator/bloodhound/trunk/bloodhound_search: bhsearch/search_resources/changeset_search.py bhsearch/tests/__init__.py bhsearch/tests/search_resources/changeset_search.py bhsearch/whoosh_backend.py setup.py
Date Mon, 18 Mar 2013 05:14:28 GMT
Author: peter
Date: Mon Mar 18 05:14:28 2013
New Revision: 1457645

URL: http://svn.apache.org/r1457645
Log:
#392: Indexing and searching of changesets

Added:
    incubator/bloodhound/trunk/bloodhound_search/bhsearch/search_resources/changeset_search.py
    incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/search_resources/changeset_search.py
Modified:
    incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/__init__.py
    incubator/bloodhound/trunk/bloodhound_search/bhsearch/whoosh_backend.py
    incubator/bloodhound/trunk/bloodhound_search/setup.py

Added: incubator/bloodhound/trunk/bloodhound_search/bhsearch/search_resources/changeset_search.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_search/bhsearch/search_resources/changeset_search.py?rev=1457645&view=auto
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_search/bhsearch/search_resources/changeset_search.py
(added)
+++ incubator/bloodhound/trunk/bloodhound_search/bhsearch/search_resources/changeset_search.py
Mon Mar 18 05:14:28 2013
@@ -0,0 +1,136 @@
+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing,
+#  software distributed under the License is distributed on an
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+#  specific language governing permissions and limitations
+#  under the License.
+
+from bhsearch import BHSEARCH_CONFIG_SECTION
+from trac.versioncontrol.api import IRepositoryChangeListener
+from bhsearch.api import (IIndexParticipant, BloodhoundSearchApi, IndexFields,
+                          ISearchParticipant)
+from bhsearch.search_resources.base import BaseIndexer, BaseSearchParticipant
+from genshi.builder import tag
+from trac.config import ListOption, Option
+from trac.core import implements
+from trac.versioncontrol.api import RepositoryManager
+
+CHANGESET_TYPE = u"changeset"
+
+
+class ChangesetFields(IndexFields):
+    MESSAGE = "message"
+    REPOSITORY = "repository"
+    REVISION = "revision"
+    CHANGES = "changes"
+
+
+class ChangesetIndexer(BaseIndexer):
+    implements(IRepositoryChangeListener, IIndexParticipant)
+
+    # IRepositoryChangeListener methods
+    def changeset_added(self, repos, changeset):
+        # pylint: disable=unused-argument
+        self._index_changeset(changeset)
+
+    def changeset_modified(self, repos, changeset, old_changeset):
+        # pylint: disable=unused-argument
+        self._index_changeset(changeset)
+
+    def _index_changeset(self, changeset):
+        try:
+            doc = self.build_doc(changeset)
+            search_api = BloodhoundSearchApi(self.env)
+            search_api.add_doc(doc)
+        except Exception, e:
+            if self.silence_on_error:
+                self.log.error("Error occurs during changeset indexing. \
+                    The error will not be propagated. Exception: %s", e)
+            else:
+                raise
+
+    #IIndexParticipant members
+    def build_doc(self, trac_doc):
+        changeset = trac_doc
+
+        doc = {
+            IndexFields.ID: u'%s/%s' % (changeset.rev,
+                                        changeset.repos.reponame),
+            IndexFields.TYPE: CHANGESET_TYPE,
+            ChangesetFields.MESSAGE: changeset.message,
+            IndexFields.AUTHOR: changeset.author,
+            IndexFields.TIME: changeset.date,
+            ChangesetFields.REPOSITORY: changeset.repos.reponame,
+            ChangesetFields.REVISION: changeset.repos.short_rev(changeset.rev)
+        }
+        return doc
+
+    def get_entries_for_index(self):
+        repository_manager = RepositoryManager(self.env)
+        for repository in repository_manager.get_real_repositories():
+            rev = repository.oldest_rev
+            stop = repository.youngest_rev
+            while True:
+                changeset = repository.get_changeset(rev)
+                yield self.build_doc(changeset)
+                if rev == stop:
+                    break
+                rev = repository.next_rev(rev)
+
+
+class ChangesetSearchParticipant(BaseSearchParticipant):
+    implements(ISearchParticipant)
+
+    participant_type = CHANGESET_TYPE
+    required_permission = 'CHANGESET_VIEW'
+
+    default_facets = [
+        ChangesetFields.REPOSITORY,
+        ChangesetFields.AUTHOR,
+    ]
+    default_grid_fields = [
+        ChangesetFields.REPOSITORY,
+        ChangesetFields.REVISION,
+        ChangesetFields.AUTHOR,
+        ChangesetFields.MESSAGE
+    ]
+    prefix = CHANGESET_TYPE
+
+    default_facets = ListOption(
+        BHSEARCH_CONFIG_SECTION,
+        prefix + '_default_facets',
+        default=",".join(default_facets),
+        doc="""Default facets applied to search view of specific resource""")
+
+    default_view = Option(
+        BHSEARCH_CONFIG_SECTION,
+        prefix + '_default_view',
+        doc = """If true, show grid as default view for specific resource in
+            Bloodhound Search results""")
+
+    default_grid_fields = ListOption(
+        BHSEARCH_CONFIG_SECTION,
+        prefix + '_default_grid_fields',
+        default=",".join(default_grid_fields),
+        doc="""Default fields for grid view for specific resource""")
+
+    #ISearchParticipant members
+    def get_title(self):
+        return "Changeset"
+
+    def format_search_results(self, res):
+        message = res['hilited_message'] or res['message']
+        return tag(u'Changeset [', res['revision'], u']: ', message)

Modified: incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/__init__.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/__init__.py?rev=1457645&r1=1457644&r2=1457645&view=diff
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/__init__.py (original)
+++ incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/__init__.py Mon Mar 18 05:14:28
2013
@@ -21,7 +21,8 @@ import unittest
 from bhsearch.tests import (whoosh_backend, index_with_whoosh, web_ui,
                             api, query_parser)
 from bhsearch.tests.search_resources import (ticket_search, wiki_search,
-                                             milestone_search, base)
+                                             milestone_search, base,
+                                             changeset_search)
 
 def suite():
     test_suite = unittest.TestSuite()
@@ -33,8 +34,9 @@ def suite():
     test_suite.addTest(ticket_search.suite())
     test_suite.addTest(wiki_search.suite())
     test_suite.addTest(milestone_search.suite())
+    test_suite.addTest(changeset_search.suite())
     test_suite.addTest(base.suite())
     return test_suite
 
 if __name__ == '__main__':
-    unittest.main(defaultTest='suite')
\ No newline at end of file
+    unittest.main(defaultTest='suite')

Added: incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/search_resources/changeset_search.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/search_resources/changeset_search.py?rev=1457645&view=auto
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/search_resources/changeset_search.py
(added)
+++ incubator/bloodhound/trunk/bloodhound_search/bhsearch/tests/search_resources/changeset_search.py
Mon Mar 18 05:14:28 2013
@@ -0,0 +1,172 @@
+#!/usr/bin/env python
+# -*- coding: UTF-8 -*-
+
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing,
+#  software distributed under the License is distributed on an
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+#  specific language governing permissions and limitations
+#  under the License.
+import unittest
+
+from bhsearch.api import BloodhoundSearchApi
+from bhsearch.search_resources.changeset_search import (
+    ChangesetSearchParticipant)
+from bhsearch.tests.base import BaseBloodhoundSearchTest
+from bhsearch.whoosh_backend import WhooshBackend
+from trac.core import Component, implements
+from trac.versioncontrol.api import (IRepositoryConnector, RepositoryManager,
+                                     Repository)
+from trac.versioncontrol import Changeset
+
+
+class ChangesetIndexerEventsTestCase(BaseBloodhoundSearchTest):
+    def setUp(self):
+        super(ChangesetIndexerEventsTestCase, self).setUp()
+        self.whoosh_backend = WhooshBackend(self.env)
+        self.whoosh_backend.recreate_index()
+        self.search_api = BloodhoundSearchApi(self.env)
+        self.repository_manager = RepositoryManager(self.env)
+        self.inject_dummy_repository()
+
+    def test_can_index_added_changeset(self):
+        rev = self.insert_changeset("Changed document 1.")
+
+        results = self.search_api.query("*:*")
+
+        self.assertEqual(1, results.hits)
+        doc = results.docs[0]
+        self.assertEqual('%s/dummy' % rev, doc["id"])
+        self.assertEqual('dummy', doc["repository"])
+        self.assertEqual('1', doc["revision"])
+        self.assertEqual("Changed document 1.", doc["message"])
+
+    def test_can_index_modified_changeset(self):
+        rev = self.insert_changeset("Changed document 1.")
+        self.modify_changeset(rev, "Added document 1.")
+
+        results = self.search_api.query("*:*")
+
+        self.assertEqual(1, results.hits)
+        doc = results.docs[0]
+        self.assertEqual('%s/dummy' % rev, doc["id"])
+        self.assertEqual('dummy', doc["repository"])
+        self.assertEqual('1', doc["revision"])
+        self.assertEqual("Added document 1.", doc["message"])
+
+    def insert_changeset(self, message, author=None, date=None, revision=None):
+        rev = self.repository.add_changeset(revision, message, author, date)
+        self.repository_manager.notify("changeset_added", 'dummy', [rev])
+        return rev
+
+    def modify_changeset(self, rev, message=None, author=None, date=None):
+        changeset = self.repository.get_changeset(rev)
+        if message is not None:
+            changeset.message = message
+        if author is not None:
+            changeset.author = author
+        if date is not None:
+            changeset.date = date
+        self.repository_manager.notify("changeset_modified", "dummy", [rev])
+
+    def inject_dummy_repository(self):
+        # pylint: disable=protected-access,attribute-defined-outside-init
+        self.repository = DummyRepositry()
+        self.repository_connector = DummyRepositoryConnector(self.env)
+        self.repository_connector.repository = self.repository
+        self.repository_manager._all_repositories = {
+            'dummy': dict(dir='dirname', type='dummy')}
+        self.repository_manager._connectors = {
+            'dummy': (self.repository_connector, 100)}
+
+
+class ChangesetSearchParticipantTestCase(BaseBloodhoundSearchTest):
+    def setUp(self):
+        super(ChangesetSearchParticipantTestCase, self).setUp()
+        self.changeset_search = ChangesetSearchParticipant(self.env)
+
+    def test_can_get_default_grid_fields(self):
+        grid_fields = self.changeset_search.get_default_view_fields("grid")
+        print grid_fields
+        self.assertGreater(len(grid_fields), 0)
+
+    def test_can_get_default_facets(self):
+        default_facets = self.changeset_search.get_default_facets()
+        print default_facets
+        self.assertIsNotNone(default_facets)
+
+    def test_can_get_is_grid_view_defaults(self):
+        default_grid_fields = self.changeset_search.get_default_view_fields(
+            "grid")
+        print default_grid_fields
+        self.assertIsNotNone(default_grid_fields)
+
+
+class DummyRepositoryConnector(Component):
+    implements(IRepositoryConnector)
+
+    repository = None
+
+    def get_supported_types(self):
+        return ('dummy', 100)
+
+    def get_repository(self, repos_type, repos_dir, params):
+        # pylint: disable=unused-argument
+        return self.repository
+
+
+class DummyRepositry(Repository):
+    # pylint: disable=abstract-method
+    name = "dummy.git"
+
+    def __init__(self):
+        super(DummyRepositry, self).__init__(
+            "DummyRepo", dict(name='dummy', id='id'), None)
+        self.changesets = {}
+        self.revisions = []
+        self.last_rev = 0
+
+    def add_changeset(self, rev, message, author, date, changes=()):
+        if rev is None:
+            rev = self.last_rev = self.last_rev + 1
+        changeset = Changeset(self, str(rev), message, author, date)
+        changeset.get_changes = lambda: changes
+        self.changesets[changeset.rev] = changeset
+        self.revisions.append(changeset.rev)
+        return str(rev)
+
+    def get_changeset(self, rev):
+        return self.changesets[rev]
+
+    def get_changesets(self, start, stop):
+        for rev in self.revisions:
+            yield self.changesets[rev]
+
+    def normalize_rev(self, rev):
+        return rev
+
+    def get_changes(self, old_path, old_rev, new_path, new_rev,
+                    ignore_ancestry=1):
+        return ()
+
+
+def suite():
+    test_suite = unittest.TestSuite()
+    test_suite.addTest(
+        unittest.makeSuite(ChangesetIndexerEventsTestCase, 'test'))
+    test_suite.addTest(
+        unittest.makeSuite(ChangesetSearchParticipantTestCase, 'test'))
+    return test_suite
+
+if __name__ == '__main__':
+    unittest.main()

Modified: incubator/bloodhound/trunk/bloodhound_search/bhsearch/whoosh_backend.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_search/bhsearch/whoosh_backend.py?rev=1457645&r1=1457644&r2=1457645&view=diff
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_search/bhsearch/whoosh_backend.py (original)
+++ incubator/bloodhound/trunk/bloodhound_search/bhsearch/whoosh_backend.py Mon Mar 18 05:14:28
2013
@@ -71,6 +71,12 @@ class WhooshBackend(Component):
         changes=TEXT(analyzer=analysis.StandardAnalyzer(stoplist=None)),
         owner=TEXT(stored=True,
                    analyzer=analysis.SimpleAnalyzer()),
+        repository=TEXT(stored=True,
+                        analyzer=analysis.SimpleAnalyzer()),
+        revision=TEXT(stored=True,
+                      analyzer=analysis.SimpleAnalyzer()),
+        message=TEXT(stored=True,
+                     analyzer=analysis.SimpleAnalyzer()),
     )
 
     max_fragment_size = IntOption('bhsearch', 'max_fragment_size', 240,

Modified: incubator/bloodhound/trunk/bloodhound_search/setup.py
URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_search/setup.py?rev=1457645&r1=1457644&r2=1457645&view=diff
==============================================================================
--- incubator/bloodhound/trunk/bloodhound_search/setup.py (original)
+++ incubator/bloodhound/trunk/bloodhound_search/setup.py Mon Mar 18 05:14:28 2013
@@ -116,6 +116,8 @@ ENTRY_POINTS = {
         'bhsearch.web_ui = bhsearch.web_ui',
         'bhsearch.api = bhsearch.api',
         'bhsearch.admin = bhsearch.admin',
+        'bhsearch.search_resources.changeset_search =\
+            bhsearch.search_resources.changeset_search',
         'bhsearch.search_resources.ticket_search =\
             bhsearch.search_resources.ticket_search',
         'bhsearch.search_resources.wiki_search = \



Mime
View raw message