Switch to unified view

a/Allura/allura/model/repository.py b/Allura/allura/model/repository.py
...
...
16
from ming import schema as S
16
from ming import schema as S
17
from ming.utils import LazyProperty
17
from ming.utils import LazyProperty
18
from ming.orm import FieldProperty, session, Mapper
18
from ming.orm import FieldProperty, session, Mapper
19
from ming.orm.declarative import MappedClass
19
from ming.orm.declarative import MappedClass
20
20
21
22
from allura.lib.patience import SequenceMatcher
21
from allura.lib.patience import SequenceMatcher
23
from allura.lib import helpers as h
22
from allura.lib import helpers as h
24
from allura.lib import utils
23
from allura.lib import utils
25
24
26
from .artifact import Artifact, VersionedArtifact, Feed
25
from .artifact import Artifact, VersionedArtifact, Feed
27
from .auth import User
26
from .auth import User
28
from .session import repository_orm_session, project_orm_session
27
from .session import repository_orm_session, project_orm_session, main_doc_session
29
from .notification import Notification
28
from .notification import Notification
30
29
31
log = logging.getLogger(__name__)
30
log = logging.getLogger(__name__)
32
config = utils.ConfigProxy(
31
config = utils.ConfigProxy(
33
    common_suffix='forgemail.domain',
32
    common_suffix='forgemail.domain',
...
...
47
46
48
    def commit(self, revision): # pragma no cover
47
    def commit(self, revision): # pragma no cover
49
        raise NotImplementedError, 'commit'
48
        raise NotImplementedError, 'commit'
50
49
51
    def new_commits(self, all_commits=False): # pragma no cover
50
    def new_commits(self, all_commits=False): # pragma no cover
52
        '''Return any commit object_ids in the native repo that are not (yet) stored
51
        '''Return a list of (oid, commit) in topological order (heads first).
53
        in the database in topological order (parents first)'''
52
53
        "commit" is a repo-native object, NOT a Commit object.
54
        If all_commits is False, only return commits not already indexed.
55
        '''
54
        raise NotImplementedError, 'commit'
56
        raise NotImplementedError, 'new_commits'
57
58
    def commit_parents(self, commit):
59
        '''Return a list of (oid, commit) for the parents of the given (native)
60
        commit'''
61
        raise NotImplementedError, 'commit_parents'
55
62
56
    def commit_context(self, object_id): # pragma no cover
63
    def commit_context(self, object_id): # pragma no cover
57
        '''Returns {'prev':Commit, 'next':Commit}'''
64
        '''Returns {'prev':Commit, 'next':Commit}'''
58
        raise NotImplementedError, 'context'
65
        raise NotImplementedError, 'context'
59
66
...
...
279
                content_type, encoding = 'text/plain', None
286
                content_type, encoding = 'text/plain', None
280
            if content_type is None:
287
            if content_type is None:
281
                content_type, encoding = 'application/octet-stream', None
288
                content_type, encoding = 'application/octet-stream', None
282
        return content_type, encoding
289
        return content_type, encoding
283
290
291
    def refresh_ancestor_graph(self, commits):
292
        '''Make sure the CommitAncestor collection is up-to-date based on
293
        the given list of (oid, native_commit) commits
294
        '''
295
        PAGESIZE = 1024
296
        ca_doc = mapper(CommitAncestor).doc_cls
297
        sess = main_doc_session
298
        ancestor_cache = {} # ancestor_cache[oid] = [ a_oid0, a_oid1...]
299
        def _ancestors(oid, ci, indent=''):
300
            if oid in ancestor_cache:
301
                return ancestor_cache[oid]
302
            stored_ancestors = []
303
            for ca in sess.find(ca_doc, dict(object_id=oid)):
304
                stored_ancestors.extend(ca.ancestor_ids)
305
            if stored_ancestors:
306
                # Ancestors already stored in MongoDB
307
                ancestor_cache[oid] = stored_ancestors
308
                return stored_ancestors
309
            ancestor_ids = set()
310
            for p_oid, p_ci in self._impl.commit_parents(ci):
311
                ancestor_ids.add(p_oid)
312
                ancestor_ids.update(_ancestors(p_oid, p_ci, indent + '    '))
313
            result = ancestor_cache[oid] = list(ancestor_ids)
314
            for i in xrange(0, len(result), PAGESIZE):
315
                sess.insert(ca_doc(
316
                        dict(
317
                            object_id=oid,
318
                            ancestor_ids=result[i:i+PAGESIZE])))
319
320
        # Compute graph in chunks to save memory
321
        for i, (oid, ci) in enumerate(reversed(commits)):
322
            _ancestors(oid, ci)
323
            if i and i % PAGESIZE == 0:
324
                log.info('=== Clear ancestor cache === ')
325
                ancestor_cache = {}
326
284
    def refresh(self, all_commits=False, notify=True):
327
    def refresh(self, all_commits=False, notify=True):
285
        '''Find any new commits in the repository and update'''
328
        '''Find any new commits in the repository and update'''
286
        self._impl.refresh_heads()
329
        self._impl.refresh_heads()
287
        self.status = 'analyzing'
330
        self.status = 'analyzing'
288
        session(self).flush()
331
        session(self).flush()
289
        sess = session(Commit)
332
        sess = session(Commit)
290
        log.info('Refreshing repository %s', self)
333
        log.info('Refreshing repository %s', self)
291
        commit_ids = self._impl.new_commits(all_commits)
334
        commits = self._impl.new_commits(all_commits)
292
        log.info('... %d new commits', len(commit_ids))
335
        log.info('... %d new commits', len(commits))
336
        self.refresh_ancestor_graph(commits)
337
338
339
        return
293
        # Refresh history
340
        # Refresh history
294
        i=0
341
        i=0
295
        seen_object_ids = set()
342
        seen_object_ids = set()
296
        commit_msgs = []
343
        commit_msgs = []
297
        for i, oid in enumerate(commit_ids):
344
        for i, oid in enumerate(commit_ids):
...
...
621
        lc, new = cls.upsert('$' + object_id)
668
        lc, new = cls.upsert('$' + object_id)
622
        if not lc.object_ids:
669
        if not lc.object_ids:
623
            lc.object_ids, lc.candidates = repo._impl.log(object_id, 0, 50)
670
            lc.object_ids, lc.candidates = repo._impl.log(object_id, 0, 50)
624
        return lc
671
        return lc
625
672
673
class CommitAncestor(MappedClass):
674
    class __mongometa__:
675
        session = repository_orm_session
676
        name='commit_ancestor'
677
        indexes = [
678
            ('object_id'), ('ancestor_id') ]
679
680
    _id = FieldProperty(S.ObjectId)
681
    object_id = FieldProperty(str)
682
    ancestor_ids = FieldProperty([str])
683
684
    @LazyProperty
685
    def ancestor(self):
686
        ci = Commit.query.get(object_id=self.ancestor_id)
687
        if ci is None: return ci
688
        ci.set_context(self.repo)
689
626
class Commit(RepoObject):
690
class Commit(RepoObject):
627
    class __mongometa__:
691
    class __mongometa__:
628
        polymorphic_identity='commit'
692
        polymorphic_identity='commit'
629
    type_s = 'Commit'
693
    type_s = 'Commit'
630
694