/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/revisionspec.py

  • Committer: John Arbash Meinel
  • Date: 2008-07-08 14:55:19 UTC
  • mfrom: (3530 +trunk)
  • mto: This revision was merged to the branch mainline in revision 3532.
  • Revision ID: john@arbash-meinel.com-20080708145519-paqg4kjwbpgs2xmq
Merge bzr.dev 3530

Show diffs side-by-side

added added

removed removed

Lines of Context:
100
100
 
101
101
        Use this if you don't know or care what the revno is.
102
102
        """
 
103
        if revision_id == revision.NULL_REVISION:
 
104
            return RevisionInfo(branch, 0, revision_id)
103
105
        try:
104
106
            revno = revs.index(revision_id) + 1
105
107
        except ValueError:
133
135
    """
134
136
 
135
137
    prefix = None
 
138
    wants_revision_history = True
136
139
 
137
140
    def __new__(cls, spec, _internal=False):
138
141
        if _internal:
158
161
 
159
162
        if spec is None:
160
163
            return RevisionSpec(None, _internal=True)
161
 
 
162
 
        assert isinstance(spec, basestring), \
163
 
            "You should only supply strings not %s" % (type(spec),)
164
 
 
165
164
        for spectype in SPEC_TYPES:
166
165
            if spec.startswith(spectype.prefix):
167
166
                trace.mutter('Returning RevisionSpec %s for %s',
201
200
 
202
201
    def _match_on(self, branch, revs):
203
202
        trace.mutter('Returning RevisionSpec._match_on: None')
204
 
        return RevisionInfo(branch, 0, None)
 
203
        return RevisionInfo(branch, None, None)
205
204
 
206
205
    def _match_on_and_check(self, branch, revs):
207
206
        info = self._match_on(branch, revs)
208
207
        if info:
209
208
            return info
210
 
        elif info == (0, None):
211
 
            # special case - the empty tree
 
209
        elif info == (None, None):
 
210
            # special case - nothing supplied
212
211
            return info
213
212
        elif self.prefix:
214
213
            raise errors.InvalidRevisionSpec(self.user_spec, branch)
217
216
 
218
217
    def in_history(self, branch):
219
218
        if branch:
220
 
            revs = branch.revision_history()
 
219
            if self.wants_revision_history:
 
220
                revs = branch.revision_history()
 
221
            else:
 
222
                revs = None
221
223
        else:
222
224
            # this should never trigger.
223
225
            # TODO: make it a deprecated code path. RBC 20060928
233
235
    # will do what you expect.
234
236
    in_store = in_history
235
237
    in_branch = in_store
236
 
        
 
238
 
 
239
    def as_revision_id(self, context_branch):
 
240
        """Return just the revision_id for this revisions spec.
 
241
 
 
242
        Some revision specs require a context_branch to be able to determine
 
243
        their value. Not all specs will make use of it.
 
244
        """
 
245
        return self._as_revision_id(context_branch)
 
246
 
 
247
    def _as_revision_id(self, context_branch):
 
248
        """Implementation of as_revision_id()
 
249
 
 
250
        Classes should override this function to provide appropriate
 
251
        functionality. The default is to just call '.in_history().rev_id'
 
252
        """
 
253
        return self.in_history(context_branch).rev_id
 
254
 
237
255
    def __repr__(self):
238
256
        # this is mostly for helping with testing
239
257
        return '<%s %s>' % (self.__class__.__name__,
278
296
                                   your history is very long.
279
297
    """
280
298
    prefix = 'revno:'
 
299
    wants_revision_history = False
281
300
 
282
301
    def _match_on(self, branch, revs):
283
302
        """Lookup a revision by revision number"""
 
303
        branch, revno, revision_id = self._lookup(branch, revs)
 
304
        return RevisionInfo(branch, revno, revision_id)
 
305
 
 
306
    def _lookup(self, branch, revs_or_none):
284
307
        loc = self.spec.find(':')
285
308
        if loc == -1:
286
309
            revno_spec = self.spec
315
338
            # the branch object.
316
339
            from bzrlib.branch import Branch
317
340
            branch = Branch.open(branch_spec)
318
 
            # Need to use a new revision history
319
 
            # because we are using a specific branch
320
 
            revs = branch.revision_history()
 
341
            revs_or_none = None
321
342
 
322
343
        if dotted:
323
344
            branch.lock_read()
329
350
            finally:
330
351
                branch.unlock()
331
352
            if len(revisions) != 1:
332
 
                return RevisionInfo(branch, None, None)
 
353
                return branch, None, None
333
354
            else:
334
355
                # there is no traditional 'revno' for dotted-decimal revnos.
335
356
                # so for  API compatability we return None.
336
 
                return RevisionInfo(branch, None, revisions[0])
 
357
                return branch, None, revisions[0]
337
358
        else:
 
359
            last_revno, last_revision_id = branch.last_revision_info()
338
360
            if revno < 0:
339
361
                # if get_rev_id supported negative revnos, there would not be a
340
362
                # need for this special case.
341
 
                if (-revno) >= len(revs):
 
363
                if (-revno) >= last_revno:
342
364
                    revno = 1
343
365
                else:
344
 
                    revno = len(revs) + revno + 1
 
366
                    revno = last_revno + revno + 1
345
367
            try:
346
 
                revision_id = branch.get_rev_id(revno, revs)
 
368
                revision_id = branch.get_rev_id(revno, revs_or_none)
347
369
            except errors.NoSuchRevision:
348
370
                raise errors.InvalidRevisionSpec(self.user_spec, branch)
349
 
        return RevisionInfo(branch, revno, revision_id)
350
 
        
 
371
        return branch, revno, revision_id
 
372
 
 
373
    def _as_revision_id(self, context_branch):
 
374
        # We would have the revno here, but we don't really care
 
375
        branch, revno, revision_id = self._lookup(context_branch, None)
 
376
        return revision_id
 
377
 
351
378
    def needs_branch(self):
352
379
        return self.spec.find(':') == -1
353
380
 
374
401
    Examples::
375
402
 
376
403
      revid:aaaa@bbbb-123456789 -> Select revision 'aaaa@bbbb-123456789'
377
 
    """    
 
404
    """
 
405
 
378
406
    prefix = 'revid:'
379
407
 
380
408
    def _match_on(self, branch, revs):
384
412
        revision_id = osutils.safe_revision_id(self.spec, warn=False)
385
413
        return RevisionInfo.from_revision_id(branch, revision_id, revs)
386
414
 
 
415
    def _as_revision_id(self, context_branch):
 
416
        return osutils.safe_revision_id(self.spec, warn=False)
 
417
 
387
418
SPEC_TYPES.append(RevisionSpec_revid)
388
419
 
389
420
 
398
429
 
399
430
      last:1        -> return the last revision
400
431
      last:3        -> return the revision 2 before the end.
401
 
    """    
 
432
    """
402
433
 
403
434
    prefix = 'last:'
404
435
 
405
436
    def _match_on(self, branch, revs):
 
437
        revno, revision_id = self._revno_and_revision_id(branch, revs)
 
438
        return RevisionInfo(branch, revno, revision_id)
 
439
 
 
440
    def _revno_and_revision_id(self, context_branch, revs_or_none):
 
441
        last_revno, last_revision_id = context_branch.last_revision_info()
 
442
 
406
443
        if self.spec == '':
407
 
            if not revs:
408
 
                raise errors.NoCommits(branch)
409
 
            return RevisionInfo(branch, len(revs), revs[-1])
 
444
            if not last_revno:
 
445
                raise errors.NoCommits(context_branch)
 
446
            return last_revno, last_revision_id
410
447
 
411
448
        try:
412
449
            offset = int(self.spec)
413
450
        except ValueError, e:
414
 
            raise errors.InvalidRevisionSpec(self.user_spec, branch, e)
 
451
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch, e)
415
452
 
416
453
        if offset <= 0:
417
 
            raise errors.InvalidRevisionSpec(self.user_spec, branch,
 
454
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
418
455
                                             'you must supply a positive value')
419
 
        revno = len(revs) - offset + 1
 
456
 
 
457
        revno = last_revno - offset + 1
420
458
        try:
421
 
            revision_id = branch.get_rev_id(revno, revs)
 
459
            revision_id = context_branch.get_rev_id(revno, revs_or_none)
422
460
        except errors.NoSuchRevision:
423
 
            raise errors.InvalidRevisionSpec(self.user_spec, branch)
424
 
        return RevisionInfo(branch, revno, revision_id)
 
461
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch)
 
462
        return revno, revision_id
 
463
 
 
464
    def _as_revision_id(self, context_branch):
 
465
        # We compute the revno as part of the process, but we don't really care
 
466
        # about it.
 
467
        revno, revision_id = self._revno_and_revision_id(context_branch, None)
 
468
        return revision_id
425
469
 
426
470
SPEC_TYPES.append(RevisionSpec_last)
427
471
 
474
518
                                                 branch)
475
519
        return RevisionInfo(branch, revno, revision_id)
476
520
 
 
521
    def _as_revision_id(self, context_branch):
 
522
        base_revspec = RevisionSpec.from_string(self.spec)
 
523
        base_revision_id = base_revspec.as_revision_id(context_branch)
 
524
        if base_revision_id == revision.NULL_REVISION:
 
525
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
 
526
                                         'cannot go before the null: revision')
 
527
        context_repo = context_branch.repository
 
528
        context_repo.lock_read()
 
529
        try:
 
530
            parent_map = context_repo.get_parent_map([base_revision_id])
 
531
        finally:
 
532
            context_repo.unlock()
 
533
        if base_revision_id not in parent_map:
 
534
            # Ghost, or unknown revision id
 
535
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
 
536
                'cannot find the matching revision')
 
537
        parents = parent_map[base_revision_id]
 
538
        if len(parents) < 1:
 
539
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
 
540
                'No parents for revision.')
 
541
        return parents[0]
 
542
 
477
543
SPEC_TYPES.append(RevisionSpec_before)
478
544
 
479
545
 
493
559
            branch.tags.lookup_tag(self.spec),
494
560
            revs)
495
561
 
 
562
    def _as_revision_id(self, context_branch):
 
563
        return context_branch.tags.lookup_tag(self.spec)
 
564
 
496
565
SPEC_TYPES.append(RevisionSpec_tag)
497
566
 
498
567
 
596
665
        finally:
597
666
            branch.unlock()
598
667
        if rev == len(revs):
599
 
            return RevisionInfo(branch, None)
 
668
            raise errors.InvalidRevisionSpec(self.user_spec, branch)
600
669
        else:
601
670
            return RevisionInfo(branch, rev + 1)
602
671
 
629
698
        trace.mutter('matching ancestor: on: %s, %s', self.spec, branch)
630
699
        return self._find_revision_info(branch, self.spec)
631
700
 
 
701
    def _as_revision_id(self, context_branch):
 
702
        return self._find_revision_id(context_branch, self.spec)
 
703
 
632
704
    @staticmethod
633
705
    def _find_revision_info(branch, other_location):
 
706
        revision_id = RevisionSpec_ancestor._find_revision_id(branch,
 
707
                                                              other_location)
 
708
        try:
 
709
            revno = branch.revision_id_to_revno(revision_id)
 
710
        except errors.NoSuchRevision:
 
711
            revno = None
 
712
        return RevisionInfo(branch, revno, revision_id)
 
713
 
 
714
    @staticmethod
 
715
    def _find_revision_id(branch, other_location):
634
716
        from bzrlib.branch import Branch
635
717
 
636
 
        other_branch = Branch.open(other_location)
637
 
        revision_a = branch.last_revision()
638
 
        revision_b = other_branch.last_revision()
639
 
        for r, b in ((revision_a, branch), (revision_b, other_branch)):
640
 
            if r in (None, revision.NULL_REVISION):
641
 
                raise errors.NoCommits(b)
642
718
        branch.lock_read()
643
 
        other_branch.lock_read()
644
719
        try:
645
 
            graph = branch.repository.get_graph(other_branch.repository)
646
 
            revision_a = revision.ensure_null(revision_a)
647
 
            revision_b = revision.ensure_null(revision_b)
648
 
            if revision.NULL_REVISION in (revision_a, revision_b):
649
 
                rev_id = revision.NULL_REVISION
650
 
            else:
 
720
            revision_a = revision.ensure_null(branch.last_revision())
 
721
            if revision_a == revision.NULL_REVISION:
 
722
                raise errors.NoCommits(branch)
 
723
            other_branch = Branch.open(other_location)
 
724
            other_branch.lock_read()
 
725
            try:
 
726
                revision_b = revision.ensure_null(other_branch.last_revision())
 
727
                if revision_b == revision.NULL_REVISION:
 
728
                    raise errors.NoCommits(other_branch)
 
729
                graph = branch.repository.get_graph(other_branch.repository)
651
730
                rev_id = graph.find_unique_lca(revision_a, revision_b)
652
 
                if rev_id == revision.NULL_REVISION:
653
 
                    raise errors.NoCommonAncestor(revision_a, revision_b)
654
 
            try:
655
 
                revno = branch.revision_id_to_revno(rev_id)
656
 
            except errors.NoSuchRevision:
657
 
                revno = None
658
 
            return RevisionInfo(branch, revno, rev_id)
 
731
            finally:
 
732
                other_branch.unlock()
 
733
            if rev_id == revision.NULL_REVISION:
 
734
                raise errors.NoCommonAncestor(revision_a, revision_b)
 
735
            return rev_id
659
736
        finally:
660
737
            branch.unlock()
661
 
            other_branch.unlock()
662
738
 
663
739
 
664
740
SPEC_TYPES.append(RevisionSpec_ancestor)
690
766
        except errors.NoSuchRevision:
691
767
            revno = None
692
768
        return RevisionInfo(branch, revno, revision_b)
693
 
        
 
769
 
 
770
    def _as_revision_id(self, context_branch):
 
771
        from bzrlib.branch import Branch
 
772
        other_branch = Branch.open(self.spec)
 
773
        last_revision = other_branch.last_revision()
 
774
        last_revision = revision.ensure_null(last_revision)
 
775
        context_branch.fetch(other_branch, last_revision)
 
776
        if last_revision == revision.NULL_REVISION:
 
777
            raise errors.NoCommits(other_branch)
 
778
        return last_revision
 
779
 
694
780
SPEC_TYPES.append(RevisionSpec_branch)
695
781
 
696
782
 
715
801
 
716
802
    prefix = 'submit:'
717
803
 
718
 
    def _match_on(self, branch, revs):
719
 
        trace.mutter('matching ancestor: on: %s, %s', self.spec, branch)
 
804
    def _get_submit_location(self, branch):
720
805
        submit_location = branch.get_submit_branch()
721
806
        location_type = 'submit branch'
722
807
        if submit_location is None:
725
810
        if submit_location is None:
726
811
            raise errors.NoSubmitBranch(branch)
727
812
        trace.note('Using %s %s', location_type, submit_location)
728
 
        return self._find_revision_info(branch, submit_location)
 
813
        return submit_location
 
814
 
 
815
    def _match_on(self, branch, revs):
 
816
        trace.mutter('matching ancestor: on: %s, %s', self.spec, branch)
 
817
        return self._find_revision_info(branch,
 
818
            self._get_submit_location(branch))
 
819
 
 
820
    def _as_revision_id(self, context_branch):
 
821
        return self._find_revision_id(context_branch,
 
822
            self._get_submit_location(context_branch))
729
823
 
730
824
 
731
825
SPEC_TYPES.append(RevisionSpec_submit)