~loggerhead-team/loggerhead/trunk-rich

« back to all changes in this revision

Viewing changes to loggerhead/history.py

  • Committer: Michael Hudson
  • Date: 2008-06-20 02:26:54 UTC
  • mto: This revision was merged to the branch mainline in revision 164.
  • Revision ID: michael.hudson@canonical.com-20080620022654-mcru0b7jjuuhlgue
don't need this any more

Show diffs side-by-side

added added

removed removed

Lines of Context:
191
191
class History (object):
192
192
 
193
193
    def __init__(self):
194
 
        self._change_cache = None
195
194
        self._file_change_cache = None
196
 
        self._index = None
197
195
        self._lock = threading.RLock()
198
196
 
199
197
    @classmethod
200
 
    def from_branch(cls, branch, name=None):
 
198
    def from_branch(cls, branch):
201
199
        z = time.time()
202
200
        self = cls()
203
201
        self._branch = branch
204
202
        self._last_revid = self._branch.last_revision()
205
203
 
206
 
        if name is None:
207
 
            name = self._branch.nick
208
 
        self._name = name
209
 
        self.log = logging.getLogger('loggerhead.%s' % (name,))
 
204
        self.log = logging.getLogger('loggerhead.%s' % (self._branch.nick,))
210
205
 
211
206
        graph = branch.repository.get_graph()
212
207
        parent_map = dict(((key, value) for key, value in
257
252
        return revision_graph
258
253
 
259
254
    @classmethod
260
 
    def from_folder(cls, path, name=None):
 
255
    def from_folder(cls, path):
261
256
        b = bzrlib.branch.Branch.open(path)
262
257
        b.lock_read()
263
258
        try:
264
 
            return cls.from_branch(b, name)
 
259
            return cls.from_branch(b)
265
260
        finally:
266
261
            b.unlock()
267
262
 
277
272
            return True
278
273
        return self._branch.last_revision() != self._last_revid
279
274
 
280
 
    def use_cache(self, cache):
281
 
        self._change_cache = cache
282
 
 
283
275
    def use_file_cache(self, cache):
284
276
        self._file_change_cache = cache
285
277
 
286
 
    def use_search_index(self, index):
287
 
        self._index = index
288
 
 
289
278
    @property
290
279
    def has_revisions(self):
291
280
        return not bzrlib.revision.is_null(self.last_revid)
292
281
 
293
 
    @with_branch_lock
294
 
    def detach(self):
295
 
        # called when a new history object needs to be created, because the
296
 
        # branch history has changed.  we need to immediately close and stop
297
 
        # using our caches, because a new history object will be created to
298
 
        # replace us, using the same cache files.
299
 
        # (may also be called during server shutdown.)
300
 
        if self._change_cache is not None:
301
 
            self._change_cache.close()
302
 
            self._change_cache = None
303
 
        if self._index is not None:
304
 
            self._index.close()
305
 
            self._index = None
306
 
 
307
 
    def flush_cache(self):
308
 
        if self._change_cache is None:
309
 
            return
310
 
        self._change_cache.flush()
311
 
 
312
 
    def check_rebuild(self):
313
 
        if self._change_cache is not None:
314
 
            self._change_cache.check_rebuild()
315
 
        #if self._index is not None:
316
 
        #    self._index.check_rebuild()
317
 
 
318
282
    last_revid = property(lambda self: self._last_revid, None, None)
319
283
 
320
284
    @with_branch_lock
321
285
    def get_config(self):
322
286
        return self._branch.get_config()
323
287
 
324
 
 
325
288
    def get_revno(self, revid):
326
289
        if revid not in self._revision_info:
327
290
            # ghost parent?
385
348
        return revid_list[index:]
386
349
 
387
350
    @with_branch_lock
388
 
    def get_revision_history_matching(self, revid_list, text):
389
 
        self.log.debug('searching %d revisions for %r', len(revid_list), text)
390
 
        z = time.time()
391
 
        # this is going to be painfully slow. :(
392
 
        out = []
393
 
        text = text.lower()
394
 
        for revid in revid_list:
395
 
            change = self.get_changes([ revid ])[0]
396
 
            if text in change.comment.lower():
397
 
                out.append(revid)
398
 
        self.log.debug('searched %d revisions for %r in %r secs', len(revid_list), text, time.time() - z)
399
 
        return out
400
 
 
401
 
    def get_revision_history_matching_indexed(self, revid_list, text):
402
 
        self.log.debug('searching %d revisions for %r', len(revid_list), text)
403
 
        z = time.time()
404
 
        if self._index is None:
405
 
            return self.get_revision_history_matching(revid_list, text)
406
 
        out = self._index.find(text, revid_list)
407
 
        self.log.debug('searched %d revisions for %r in %r secs: %d results', len(revid_list), text, time.time() - z, len(out))
408
 
        # put them in some coherent order :)
409
 
        out = [r for r in self._full_history if r in out]
410
 
        return out
411
 
 
412
 
    @with_branch_lock
413
351
    def get_search_revid_list(self, query, revid_list):
414
352
        """
415
353
        given a "quick-search" query, try a few obvious possible meanings:
451
389
                revid_list = list(self.get_revids_from(None, self._last_revid))
452
390
            return self.get_revision_history_since(revid_list, date)
453
391
 
454
 
        # check comment fields.
455
 
        if revid_list is None:
456
 
            revid_list = self._full_history
457
 
        return self.get_revision_history_matching_indexed(revid_list, query)
458
 
 
459
392
    revno_re = re.compile(r'^[\d\.]+$')
460
393
    # the date regex are without a final '$' so that queries like
461
394
    # "2006-11-30 12:15" still mostly work.  (i think it's better to give
540
473
            revid_list = None
541
474
 
542
475
        revid_list = self.get_search_revid_list(query, revid_list)
543
 
        if len(revid_list) > 0:
 
476
        if revid_list and len(revid_list) > 0:
544
477
            if revid not in revid_list:
545
478
                revid = revid_list[0]
546
479
            return revid, start_revid, revid_list
547
480
        else:
548
 
            # no results
549
481
            return None, None, []
550
482
 
551
483
    @with_branch_lock
567
499
            path = '/' + path
568
500
        return self._branch.repository.get_revision_inventory(revid).path2id(path)
569
501
 
570
 
 
571
502
    def get_merge_point_list(self, revid):
572
503
        """
573
504
        Return the list of revids that have merged this node.
647
578
 
648
579
        Revisions not present and NULL_REVISION will be ignored.
649
580
        """
650
 
        if self._change_cache is None:
651
 
            changes = self.get_changes_uncached(revid_list)
652
 
        else:
653
 
            changes = self._change_cache.get_changes(revid_list)
 
581
        changes = self.get_changes_uncached(revid_list)
654
582
        if len(changes) == 0:
655
583
            return changes
656
584
 
660
588
            merge_revids = self.simplify_merge_point_list(self.get_merge_point_list(change.revid))
661
589
            change.merge_points = [util.Container(revid=r, revno=self.get_revno(r)) for r in merge_revids]
662
590
            if len(change.parents) > 0:
663
 
                if isinstance(change.parents[0], util.Container):
664
 
                    # old cache stored a potentially-bogus revno
665
 
                    change.parents = [util.Container(revid=p.revid, revno=self.get_revno(p.revid)) for p in change.parents]
666
 
                else:
667
 
                    change.parents = [util.Container(revid=r, revno=self.get_revno(r)) for r in change.parents]
 
591
                change.parents = [util.Container(revid=r, 
 
592
                    revno=self.get_revno(r)) for r in change.parents]
668
593
            change.revno = self.get_revno(change.revid)
669
594
 
670
595
        parity = 0
674
599
 
675
600
        return changes
676
601
 
677
 
    # alright, let's profile this sucka. (FIXME remove this eventually...)
678
 
    def _get_changes_profiled(self, revid_list):
679
 
        from loggerhead.lsprof import profile
680
 
        import cPickle
681
 
        ret, stats = profile(self.get_changes_uncached, revid_list)
682
 
        stats.sort()
683
 
        stats.freeze()
684
 
        cPickle.dump(stats, open('lsprof.stats', 'w'), 2)
685
 
        self.log.info('lsprof complete!')
686
 
        return ret
687
 
 
688
602
    @with_branch_lock
689
603
    @with_bzrlib_read_lock
690
604
    def get_changes_uncached(self, revid_list):
 
605
        # FIXME: deprecated method in getting a null revision
691
606
        revid_list = filter(lambda revid: not bzrlib.revision.is_null(revid),
692
607
                            revid_list)
693
 
        repo = self._branch.repository
694
 
        parent_map = repo.get_graph().get_parent_map(revid_list)
 
608
        parent_map = self._branch.repository.get_graph().get_parent_map(revid_list)
695
609
        # We need to return the answer in the same order as the input,
696
610
        # less any ghosts.
697
611
        present_revids = [revid for revid in revid_list
698
612
                          if revid in parent_map]
699
 
        rev_list = repo.get_revisions(present_revids)
 
613
        rev_list = self._branch.repository.get_revisions(present_revids)
700
614
 
701
615
        return [self._change_from_revision(rev) for rev in rev_list]
702
616