/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-05-29 19:46:01 UTC
  • mfrom: (3456 +trunk)
  • mto: This revision was merged to the branch mainline in revision 3459.
  • Revision ID: john@arbash-meinel.com-20080529194601-r2gpmk536xin9c4a
merge bzr.dev, put the NEWS entry in the right place

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:
158
160
 
159
161
        if spec is None:
160
162
            return RevisionSpec(None, _internal=True)
161
 
 
162
 
        assert isinstance(spec, basestring), \
163
 
            "You should only supply strings not %s" % (type(spec),)
164
 
 
165
163
        for spectype in SPEC_TYPES:
166
164
            if spec.startswith(spectype.prefix):
167
165
                trace.mutter('Returning RevisionSpec %s for %s',
201
199
 
202
200
    def _match_on(self, branch, revs):
203
201
        trace.mutter('Returning RevisionSpec._match_on: None')
204
 
        return RevisionInfo(branch, 0, None)
 
202
        return RevisionInfo(branch, None, None)
205
203
 
206
204
    def _match_on_and_check(self, branch, revs):
207
205
        info = self._match_on(branch, revs)
208
206
        if info:
209
207
            return info
210
 
        elif info == (0, None):
211
 
            # special case - the empty tree
 
208
        elif info == (None, None):
 
209
            # special case - nothing supplied
212
210
            return info
213
211
        elif self.prefix:
214
212
            raise errors.InvalidRevisionSpec(self.user_spec, branch)
233
231
    # will do what you expect.
234
232
    in_store = in_history
235
233
    in_branch = in_store
236
 
        
 
234
 
 
235
    def as_revision_id(self, context_branch):
 
236
        """Return just the revision_id for this revisions spec.
 
237
 
 
238
        Some revision specs require a context_branch to be able to determine
 
239
        their value. Not all specs will make use of it.
 
240
        """
 
241
        return self._as_revision_id(context_branch)
 
242
 
 
243
    def _as_revision_id(self, context_branch):
 
244
        """Implementation of as_revision_id()
 
245
 
 
246
        Classes should override this function to provide appropriate
 
247
        functionality. The default is to just call '.in_history().rev_id'
 
248
        """
 
249
        return self.in_history(context_branch).rev_id
 
250
 
237
251
    def __repr__(self):
238
252
        # this is mostly for helping with testing
239
253
        return '<%s %s>' % (self.__class__.__name__,
281
295
 
282
296
    def _match_on(self, branch, revs):
283
297
        """Lookup a revision by revision number"""
 
298
        branch, revno, revision_id = self._lookup(branch, revs)
 
299
        return RevisionInfo(branch, revno, revision_id)
 
300
 
 
301
    def _lookup(self, branch, revs_or_none):
284
302
        loc = self.spec.find(':')
285
303
        if loc == -1:
286
304
            revno_spec = self.spec
315
333
            # the branch object.
316
334
            from bzrlib.branch import Branch
317
335
            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()
 
336
            revs_or_none = None
321
337
 
322
338
        if dotted:
323
339
            branch.lock_read()
329
345
            finally:
330
346
                branch.unlock()
331
347
            if len(revisions) != 1:
332
 
                return RevisionInfo(branch, None, None)
 
348
                return branch, None, None
333
349
            else:
334
350
                # there is no traditional 'revno' for dotted-decimal revnos.
335
351
                # so for  API compatability we return None.
336
 
                return RevisionInfo(branch, None, revisions[0])
 
352
                return branch, None, revisions[0]
337
353
        else:
 
354
            last_revno, last_revision_id = branch.last_revision_info()
338
355
            if revno < 0:
339
356
                # if get_rev_id supported negative revnos, there would not be a
340
357
                # need for this special case.
341
 
                if (-revno) >= len(revs):
 
358
                if (-revno) >= last_revno:
342
359
                    revno = 1
343
360
                else:
344
 
                    revno = len(revs) + revno + 1
 
361
                    revno = last_revno + revno + 1
345
362
            try:
346
 
                revision_id = branch.get_rev_id(revno, revs)
 
363
                revision_id = branch.get_rev_id(revno, revs_or_none)
347
364
            except errors.NoSuchRevision:
348
365
                raise errors.InvalidRevisionSpec(self.user_spec, branch)
349
 
        return RevisionInfo(branch, revno, revision_id)
350
 
        
 
366
        return branch, revno, revision_id
 
367
 
 
368
    def _as_revision_id(self, context_branch):
 
369
        # We would have the revno here, but we don't really care
 
370
        branch, revno, revision_id = self._lookup(context_branch, None)
 
371
        return revision_id
 
372
 
351
373
    def needs_branch(self):
352
374
        return self.spec.find(':') == -1
353
375
 
374
396
    Examples::
375
397
 
376
398
      revid:aaaa@bbbb-123456789 -> Select revision 'aaaa@bbbb-123456789'
377
 
    """    
 
399
    """
 
400
 
378
401
    prefix = 'revid:'
379
402
 
380
403
    def _match_on(self, branch, revs):
384
407
        revision_id = osutils.safe_revision_id(self.spec, warn=False)
385
408
        return RevisionInfo.from_revision_id(branch, revision_id, revs)
386
409
 
 
410
    def _as_revision_id(self, context_branch):
 
411
        return osutils.safe_revision_id(self.spec, warn=False)
 
412
 
387
413
SPEC_TYPES.append(RevisionSpec_revid)
388
414
 
389
415
 
398
424
 
399
425
      last:1        -> return the last revision
400
426
      last:3        -> return the revision 2 before the end.
401
 
    """    
 
427
    """
402
428
 
403
429
    prefix = 'last:'
404
430
 
405
431
    def _match_on(self, branch, revs):
 
432
        revno, revision_id = self._revno_and_revision_id(branch, revs)
 
433
        return RevisionInfo(branch, revno, revision_id)
 
434
 
 
435
    def _revno_and_revision_id(self, context_branch, revs_or_none):
 
436
        last_revno, last_revision_id = context_branch.last_revision_info()
 
437
 
406
438
        if self.spec == '':
407
 
            if not revs:
408
 
                raise errors.NoCommits(branch)
409
 
            return RevisionInfo(branch, len(revs), revs[-1])
 
439
            if not last_revno:
 
440
                raise errors.NoCommits(context_branch)
 
441
            return last_revno, last_revision_id
410
442
 
411
443
        try:
412
444
            offset = int(self.spec)
413
445
        except ValueError, e:
414
 
            raise errors.InvalidRevisionSpec(self.user_spec, branch, e)
 
446
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch, e)
415
447
 
416
448
        if offset <= 0:
417
 
            raise errors.InvalidRevisionSpec(self.user_spec, branch,
 
449
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
418
450
                                             'you must supply a positive value')
419
 
        revno = len(revs) - offset + 1
 
451
 
 
452
        revno = last_revno - offset + 1
420
453
        try:
421
 
            revision_id = branch.get_rev_id(revno, revs)
 
454
            revision_id = context_branch.get_rev_id(revno, revs_or_none)
422
455
        except errors.NoSuchRevision:
423
 
            raise errors.InvalidRevisionSpec(self.user_spec, branch)
424
 
        return RevisionInfo(branch, revno, revision_id)
 
456
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch)
 
457
        return revno, revision_id
 
458
 
 
459
    def _as_revision_id(self, context_branch):
 
460
        # We compute the revno as part of the process, but we don't really care
 
461
        # about it.
 
462
        revno, revision_id = self._revno_and_revision_id(context_branch, None)
 
463
        return revision_id
425
464
 
426
465
SPEC_TYPES.append(RevisionSpec_last)
427
466
 
474
513
                                                 branch)
475
514
        return RevisionInfo(branch, revno, revision_id)
476
515
 
 
516
    def _as_revision_id(self, context_branch):
 
517
        base_revspec = RevisionSpec.from_string(self.spec)
 
518
        base_revision_id = base_revspec.as_revision_id(context_branch)
 
519
        if base_revision_id == revision.NULL_REVISION:
 
520
            raise errors.InvalidRevisionSpec(self.user_spec, branch,
 
521
                                         'cannot go before the null: revision')
 
522
        context_repo = context_branch.repository
 
523
        context_repo.lock_read()
 
524
        try:
 
525
            parent_map = context_repo.get_parent_map([base_revision_id])
 
526
        finally:
 
527
            context_repo.unlock()
 
528
        if base_revision_id not in parent_map:
 
529
            # Ghost, or unknown revision id
 
530
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
 
531
                'cannot find the matching revision')
 
532
        parents = parent_map[base_revision_id]
 
533
        if len(parents) < 1:
 
534
            raise errors.InvalidRevisionSpec(self.user_spec, context_branch,
 
535
                'No parents for revision.')
 
536
        return parents[0]
 
537
 
477
538
SPEC_TYPES.append(RevisionSpec_before)
478
539
 
479
540
 
493
554
            branch.tags.lookup_tag(self.spec),
494
555
            revs)
495
556
 
 
557
    def _as_revision_id(self, context_branch):
 
558
        return context_branch.tags.lookup_tag(self.spec)
 
559
 
496
560
SPEC_TYPES.append(RevisionSpec_tag)
497
561
 
498
562
 
596
660
        finally:
597
661
            branch.unlock()
598
662
        if rev == len(revs):
599
 
            return RevisionInfo(branch, None)
 
663
            raise errors.InvalidRevisionSpec(self.user_spec, branch)
600
664
        else:
601
665
            return RevisionInfo(branch, rev + 1)
602
666
 
629
693
        trace.mutter('matching ancestor: on: %s, %s', self.spec, branch)
630
694
        return self._find_revision_info(branch, self.spec)
631
695
 
 
696
    def _as_revision_id(self, context_branch):
 
697
        return self._find_revision_id(context_branch, self.spec)
 
698
 
632
699
    @staticmethod
633
700
    def _find_revision_info(branch, other_location):
 
701
        revision_id = RevisionSpec_ancestor._find_revision_id(branch,
 
702
                                                              other_location)
 
703
        try:
 
704
            revno = branch.revision_id_to_revno(revision_id)
 
705
        except errors.NoSuchRevision:
 
706
            revno = None
 
707
        return RevisionInfo(branch, revno, revision_id)
 
708
 
 
709
    @staticmethod
 
710
    def _find_revision_id(branch, other_location):
634
711
        from bzrlib.branch import Branch
635
712
 
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
713
        branch.lock_read()
643
 
        other_branch.lock_read()
644
714
        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:
 
715
            revision_a = revision.ensure_null(branch.last_revision())
 
716
            if revision_a == revision.NULL_REVISION:
 
717
                raise errors.NoCommits(branch)
 
718
            other_branch = Branch.open(other_location)
 
719
            other_branch.lock_read()
 
720
            try:
 
721
                revision_b = revision.ensure_null(other_branch.last_revision())
 
722
                if revision_b == revision.NULL_REVISION:
 
723
                    raise errors.NoCommits(other_branch)
 
724
                graph = branch.repository.get_graph(other_branch.repository)
651
725
                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)
 
726
            finally:
 
727
                other_branch.unlock()
 
728
            if rev_id == revision.NULL_REVISION:
 
729
                raise errors.NoCommonAncestor(revision_a, revision_b)
 
730
            return rev_id
659
731
        finally:
660
732
            branch.unlock()
661
 
            other_branch.unlock()
662
733
 
663
734
 
664
735
SPEC_TYPES.append(RevisionSpec_ancestor)
690
761
        except errors.NoSuchRevision:
691
762
            revno = None
692
763
        return RevisionInfo(branch, revno, revision_b)
693
 
        
 
764
 
 
765
    def _as_revision_id(self, context_branch):
 
766
        from bzrlib.branch import Branch
 
767
        other_branch = Branch.open(self.spec)
 
768
        last_revision = other_branch.last_revision()
 
769
        last_revision = revision.ensure_null(last_revision)
 
770
        context_branch.fetch(other_branch, last_revision)
 
771
        if last_revision == revision.NULL_REVISION:
 
772
            raise errors.NoCommits(other_branch)
 
773
        return last_revision
 
774
 
694
775
SPEC_TYPES.append(RevisionSpec_branch)
695
776
 
696
777
 
715
796
 
716
797
    prefix = 'submit:'
717
798
 
718
 
    def _match_on(self, branch, revs):
719
 
        trace.mutter('matching ancestor: on: %s, %s', self.spec, branch)
 
799
    def _get_submit_location(self, branch):
720
800
        submit_location = branch.get_submit_branch()
721
801
        location_type = 'submit branch'
722
802
        if submit_location is None:
725
805
        if submit_location is None:
726
806
            raise errors.NoSubmitBranch(branch)
727
807
        trace.note('Using %s %s', location_type, submit_location)
728
 
        return self._find_revision_info(branch, submit_location)
 
808
        return submit_location
 
809
 
 
810
    def _match_on(self, branch, revs):
 
811
        trace.mutter('matching ancestor: on: %s, %s', self.spec, branch)
 
812
        return self._find_revision_info(branch,
 
813
            self._get_submit_location(branch))
 
814
 
 
815
    def _as_revision_id(self, context_branch):
 
816
        return self._find_revision_id(context_branch,
 
817
            self._get_submit_location(context_branch))
729
818
 
730
819
 
731
820
SPEC_TYPES.append(RevisionSpec_submit)