~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/remote.py

  • Committer: Andrew Bennetts
  • Date: 2007-02-28 07:08:25 UTC
  • mfrom: (2018.13.1 hpss)
  • mto: (2018.5.80 hpss)
  • mto: This revision was merged to the branch mainline in revision 2435.
  • Revision ID: andrew.bennetts@canonical.com-20070228070825-q2dvkjb0a11ouhtx
Update to current hpss branch?  Fix lots of test failures.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
from bzrlib import branch, errors, repository
24
24
from bzrlib.branch import BranchReferenceFormat
25
25
from bzrlib.bzrdir import BzrDir, BzrDirFormat, RemoteBzrDirFormat
 
26
from bzrlib.config import BranchConfig
 
27
from bzrlib.decorators import needs_read_lock, needs_write_lock
26
28
from bzrlib.errors import NoSuchRevision
27
29
from bzrlib.revision import NULL_REVISION
28
30
from bzrlib.smart import client, vfs
40
42
            use of a real bzrdir.
41
43
        """
42
44
        BzrDir.__init__(self, transport, RemoteBzrDirFormat())
43
 
        if _client is not None:
44
 
            self.client = _client
45
 
            return
46
 
 
47
 
        self.client = transport.get_smart_client()
48
45
        # this object holds a delegated bzrdir that uses file-level operations
49
46
        # to talk to the other side
50
47
        # XXX: We should go into find_format, but not allow it to find
51
48
        # RemoteBzrDirFormat and make sure it finds the real underlying format.
52
49
        self._real_bzrdir = None
53
 
        
 
50
 
 
51
        if _client is None:
 
52
            self._medium = transport.get_smart_client()
 
53
            self._client = client.SmartClient(self._medium)
 
54
        else:
 
55
            self._client = _client
 
56
            self._medium = None
 
57
            return
 
58
 
54
59
        self._ensure_real()
55
 
        smartclient = client.SmartClient(self.client)
56
 
        path = self._path_for_remote_call(smartclient)
 
60
        path = self._path_for_remote_call(self._client)
57
61
        #self._real_bzrdir._format.probe_transport(transport)
58
 
        response = smartclient.call('probe_dont_use', path)
 
62
        response = self._client.call('probe_dont_use', path)
59
63
        if response == ('no',):
60
64
            raise errors.NotBranchError(path=transport.base)
61
65
 
83
87
 
84
88
    def open_branch(self, _unsupported=False):
85
89
        assert _unsupported == False, 'unsupported flag support not implemented yet.'
86
 
        smartclient = client.SmartClient(self.client)
87
 
        path = self._path_for_remote_call(smartclient)
88
 
        response = smartclient.call('BzrDir.open_branch', path)
89
 
        assert response[0] == 'ok', 'unexpected response code %s' % (response,)
90
 
        if response[0] != 'ok':
91
 
            # this should probably be a regular translate no ?
 
90
        path = self._path_for_remote_call(self._client)
 
91
        response = self._client.call('BzrDir.open_branch', path)
 
92
        if response[0] == 'ok':
 
93
            if response[1] == '':
 
94
                # branch at this location.
 
95
                return RemoteBranch(self, self.find_repository())
 
96
            else:
 
97
                # a branch reference, use the existing BranchReference logic.
 
98
                format = BranchReferenceFormat()
 
99
                return format.open(self, _found=True, location=response[1])
 
100
        elif response == ('nobranch',):
92
101
            raise errors.NotBranchError(path=self.root_transport.base)
93
 
        if response[1] == '':
94
 
            # branch at this location.
95
 
            return RemoteBranch(self, self.find_repository())
96
102
        else:
97
 
            # a branch reference, use the existing BranchReference logic.
98
 
            format = BranchReferenceFormat()
99
 
            return format.open(self, _found=True, location=response[1])
100
 
 
 
103
            assert False, 'unexpected response code %r' % (response,)
 
104
                
101
105
    def open_repository(self):
102
 
        smartclient = client.SmartClient(self.client)
103
 
        path = self._path_for_remote_call(smartclient)
104
 
        response = smartclient.call('BzrDir.find_repository', path)
 
106
        path = self._path_for_remote_call(self._client)
 
107
        response = self._client.call('BzrDir.find_repository', path)
105
108
        assert response[0] in ('ok', 'norepository'), \
106
109
            'unexpected response code %s' % (response,)
107
110
        if response[0] == 'norepository':
185
188
            self._real_repository = None
186
189
        self.bzrdir = remote_bzrdir
187
190
        if _client is None:
188
 
            self._client = client.SmartClient(self.bzrdir.client)
 
191
            self._client = client.SmartClient(self.bzrdir._medium)
189
192
        else:
190
193
            self._client = _client
191
194
        self._format = RemoteRepositoryFormat()
201
204
        """
202
205
        if not self._real_repository:
203
206
            self.bzrdir._ensure_real()
204
 
            self._real_repository = self.bzrdir._real_bzrdir.open_repository()
 
207
            #self._real_repository = self.bzrdir._real_bzrdir.open_repository()
 
208
            self._set_real_repository(self.bzrdir._real_bzrdir.open_repository())
205
209
 
206
210
    def get_revision_graph(self, revision_id=None):
207
211
        """See Repository.get_revision_graph()."""
224
228
                
225
229
            return revision_graph
226
230
        else:
227
 
            assert response[1] != ''
 
231
            response_body = response[1].read_body_bytes()
 
232
            assert response_body == ''
228
233
            raise NoSuchRevision(self, revision_id)
229
234
 
230
235
    def has_revision(self, revision_id):
231
236
        """See Repository.has_revision()."""
 
237
        if revision_id is None:
 
238
            # The null revision is always present.
 
239
            return True
232
240
        path = self.bzrdir._path_for_remote_call(self._client)
233
241
        response = self._client.call('Repository.has_revision', path, revision_id.encode('utf8'))
234
242
        assert response[0] in ('ok', 'no'), 'unexpected response code %s' % (response,)
235
243
        return response[0] == 'ok'
236
244
 
237
 
    def gather_stats(self, revid, committers=None):
 
245
    def gather_stats(self, revid=None, committers=None):
238
246
        """See Repository.gather_stats()."""
239
247
        path = self.bzrdir._path_for_remote_call(self._client)
240
248
        if revid in (None, NULL_REVISION):
241
249
            fmt_revid = ''
242
250
        else:
243
251
            fmt_revid = revid.encode('utf8')
244
 
        if committers is None:
 
252
        if committers is None or not committers:
245
253
            fmt_committers = 'no'
246
254
        else:
247
255
            fmt_committers = 'yes'
285
293
        else:
286
294
            self._lock_count += 1
287
295
 
288
 
    def _lock_write(self, token):
 
296
    def _remote_lock_write(self, token):
289
297
        path = self.bzrdir._path_for_remote_call(self._client)
290
298
        if token is None:
291
299
            token = ''
300
308
 
301
309
    def lock_write(self, token=None):
302
310
        if not self._lock_mode:
303
 
            self._lock_token = self._lock_write(token)
 
311
            self._lock_token = self._remote_lock_write(token)
304
312
            assert self._lock_token, 'Remote server did not return a token!'
305
313
            if self._real_repository is not None:
306
314
                self._real_repository.lock_write(token=self._lock_token)
311
319
            self._lock_mode = 'w'
312
320
            self._lock_count = 1
313
321
        elif self._lock_mode == 'r':
314
 
            raise errors.ReadOnlyTransaction
 
322
            raise errors.ReadOnlyError(self)
315
323
        else:
316
324
            self._lock_count += 1
317
325
        return self._lock_token
333
341
            # if we are already locked, the real repository must be able to
334
342
            # acquire the lock with our token.
335
343
            self._real_repository.lock_write(self._lock_token)
 
344
        elif self._lock_mode == 'r':
 
345
            self._real_repository.lock_read()
336
346
 
337
347
    def _unlock(self, token):
338
348
        path = self.bzrdir._path_for_remote_call(self._client)
364
374
        self._ensure_real()
365
375
        return self._real_repository.break_lock()
366
376
 
 
377
    ### These methods are just thin shims to the VFS object for now.
 
378
 
 
379
    def revision_tree(self, revision_id):
 
380
        self._ensure_real()
 
381
        return self._real_repository.revision_tree(revision_id)
 
382
 
 
383
    def get_commit_builder(self, branch, parents, config, timestamp=None,
 
384
                           timezone=None, committer=None, revprops=None,
 
385
                           revision_id=None):
 
386
        # FIXME: It ought to be possible to call this without immediately
 
387
        # triggering _ensure_real.  For now it's the easiest thing to do.
 
388
        self._ensure_real()
 
389
        builder = self._real_repository.get_commit_builder(branch, parents,
 
390
                config, timestamp=timestamp, timezone=timezone,
 
391
                committer=committer, revprops=revprops, revision_id=revision_id)
 
392
        # Make the builder use this RemoteRepository rather than the real one.
 
393
        builder.repository = self
 
394
        return builder
 
395
 
 
396
    @needs_write_lock
 
397
    def add_inventory(self, revid, inv, parents):
 
398
        self._ensure_real()
 
399
        return self._real_repository.add_inventory(revid, inv, parents)
 
400
 
 
401
    @needs_write_lock
 
402
    def add_revision(self, rev_id, rev, inv=None, config=None):
 
403
        self._ensure_real()
 
404
        return self._real_repository.add_revision(
 
405
            rev_id, rev, inv=inv, config=config)
 
406
 
 
407
    @needs_read_lock
 
408
    def get_inventory(self, revision_id):
 
409
        self._ensure_real()
 
410
        return self._real_repository.get_inventory(revision_id)
 
411
 
 
412
    @needs_read_lock
 
413
    def get_revision(self, revision_id):
 
414
        self._ensure_real()
 
415
        return self._real_repository.get_revision(revision_id)
 
416
 
 
417
    @property
 
418
    def weave_store(self):
 
419
        self._ensure_real()
 
420
        return self._real_repository.weave_store
 
421
 
 
422
    def get_transaction(self):
 
423
        self._ensure_real()
 
424
        return self._real_repository.get_transaction()
 
425
 
 
426
    @needs_read_lock
 
427
    def clone(self, a_bzrdir, revision_id=None, basis=None):
 
428
        self._ensure_real()
 
429
        return self._real_repository.clone(
 
430
            a_bzrdir, revision_id=revision_id, basis=basis)
 
431
 
 
432
    def make_working_trees(self):
 
433
        return False
 
434
 
 
435
    def fetch(self, source, revision_id=None, pb=None):
 
436
        self._ensure_real()
 
437
        return self._real_repository.fetch(
 
438
            source, revision_id=revision_id, pb=pb)
 
439
 
 
440
    @property
 
441
    def control_weaves(self):
 
442
        self._ensure_real()
 
443
        return self._real_repository.control_weaves
 
444
 
 
445
    @needs_read_lock
 
446
    def get_ancestry(self, revision_id):
 
447
        self._ensure_real()
 
448
        return self._real_repository.get_ancestry(revision_id)
 
449
 
 
450
    @needs_read_lock
 
451
    def get_inventory_weave(self):
 
452
        self._ensure_real()
 
453
        return self._real_repository.get_inventory_weave()
 
454
 
 
455
    def fileids_altered_by_revision_ids(self, revision_ids):
 
456
        self._ensure_real()
 
457
        return self._real_repository.fileids_altered_by_revision_ids(revision_ids)
 
458
 
 
459
    @needs_read_lock
 
460
    def get_signature_text(self, revision_id):
 
461
        self._ensure_real()
 
462
        return self._real_repository.get_signature_text(revision_id)
 
463
 
 
464
    @needs_read_lock
 
465
    def get_revision_graph_with_ghosts(self, revision_ids=None):
 
466
        self._ensure_real()
 
467
        return self._real_repository.get_revision_graph_with_ghosts(
 
468
            revision_ids=revision_ids)
 
469
 
 
470
    @needs_read_lock
 
471
    def get_inventory_xml(self, revision_id):
 
472
        self._ensure_real()
 
473
        return self._real_repository.get_inventory_xml(revision_id)
 
474
 
 
475
    def deserialise_inventory(self, revision_id, xml):
 
476
        self._ensure_real()
 
477
        return self._real_repository.deserialise_inventory(revision_id, xml)
 
478
 
 
479
    def reconcile(self, other=None, thorough=False):
 
480
        self._ensure_real()
 
481
        return self._real_repository.reconcile(other=other, thorough=thorough)
 
482
        
 
483
    def all_revision_ids(self):
 
484
        self._ensure_real()
 
485
        return self._real_repository.all_revision_ids()
 
486
    
 
487
    @needs_read_lock
 
488
    def get_deltas_for_revisions(self, revisions):
 
489
        self._ensure_real()
 
490
        return self._real_repository.get_deltas_for_revisions(revisions)
 
491
 
 
492
    @needs_read_lock
 
493
    def get_revision_delta(self, revision_id):
 
494
        self._ensure_real()
 
495
        return self._real_repository.get_revision_delta(revision_id)
 
496
 
 
497
    @needs_read_lock
 
498
    def revision_trees(self, revision_ids):
 
499
        self._ensure_real()
 
500
        return self._real_repository.revision_trees(revision_ids)
 
501
 
 
502
    @needs_read_lock
 
503
    def get_revision_reconcile(self, revision_id):
 
504
        self._ensure_real()
 
505
        return self._real_repository.get_revision_reconcile(revision_id)
 
506
 
 
507
    @needs_read_lock
 
508
    def check(self, revision_ids):
 
509
        self._ensure_real()
 
510
        return self._real_repository.check(revision_ids)
 
511
 
 
512
    def copy_content_into(self, destination, revision_id=None, basis=None):
 
513
        self._ensure_real()
 
514
        return self._real_repository.copy_content_into(
 
515
            destination, revision_id=revision_id, basis=basis)
 
516
 
 
517
    def set_make_working_trees(self, new_value):
 
518
        raise NotImplementedError(self.set_make_working_trees)
 
519
 
 
520
    @needs_write_lock
 
521
    def sign_revision(self, revision_id, gpg_strategy):
 
522
        self._ensure_real()
 
523
        return self._real_repository.sign_revision(revision_id, gpg_strategy)
 
524
 
 
525
    @needs_read_lock
 
526
    def get_revisions(self, revision_ids):
 
527
        self._ensure_real()
 
528
        return self._real_repository.get_revisions(revision_ids)
 
529
 
 
530
    def supports_rich_root(self):
 
531
        # Perhaps this should return True depending on the real repository, but
 
532
        # for now we just take the easy option and assume we can't handle rich
 
533
        # root data.
 
534
        return False
 
535
 
367
536
 
368
537
class RemoteBranchLockableFiles(object):
369
538
    """A 'LockableFiles' implementation that talks to a smart server.
395
564
    def get_format_description(self):
396
565
        return 'Remote BZR Branch'
397
566
 
 
567
    def get_format_string(self):
 
568
        return 'Remote BZR Branch'
 
569
 
398
570
    def open(self, a_bzrdir):
399
571
        assert isinstance(a_bzrdir, RemoteBzrDir)
400
572
        return a_bzrdir.open_branch()
422
594
        if _client is not None:
423
595
            self._client = _client
424
596
        else:
425
 
            self._client = client.SmartClient(self.bzrdir.client)
 
597
            self._client = client.SmartClient(self.bzrdir._medium)
426
598
        self.repository = remote_repository
427
599
        if real_branch is not None:
428
600
            self._real_branch = real_branch
454
626
            self.repository._set_real_repository(self._real_branch.repository)
455
627
            # Give the branch the remote repository to let fast-pathing happen.
456
628
            self._real_branch.repository = self.repository
 
629
            # XXX: deal with _lock_mode == 'w'
 
630
            if self._lock_mode == 'r':
 
631
                self._real_branch.lock_read()
457
632
 
458
633
    def get_physical_lock_status(self):
459
634
        """See Branch.get_physical_lock_status()."""
462
637
        return self._real_branch.get_physical_lock_status()
463
638
 
464
639
    def lock_read(self):
465
 
        self._ensure_real()
466
 
        return self._real_branch.lock_read()
 
640
        if not self._lock_mode:
 
641
            self._lock_mode = 'r'
 
642
            self._lock_count = 1
 
643
            if self._real_branch is not None:
 
644
                self._real_branch.lock_read()
 
645
        else:
 
646
            self._lock_count += 1
467
647
 
468
 
    def _lock_write(self, tokens):
 
648
    def _remote_lock_write(self, tokens):
469
649
        if tokens is None:
470
650
            branch_token = repo_token = ''
471
651
        else:
481
661
        elif response[0] == 'TokenMismatch':
482
662
            raise errors.TokenMismatch(tokens, '(remote tokens)')
483
663
        else:
484
 
            assert False, 'unexpected response code %s' % (response,)
 
664
            assert False, 'unexpected response code %r' % (response,)
485
665
            
486
666
    def lock_write(self, tokens=None):
487
667
        if not self._lock_mode:
488
 
            remote_tokens = self._lock_write(tokens)
 
668
            remote_tokens = self._remote_lock_write(tokens)
489
669
            self._lock_token, self._repo_lock_token = remote_tokens
490
670
            assert self._lock_token, 'Remote server did not return a token!'
 
671
            # TODO: We really, really, really don't want to call _ensure_real
 
672
            # here, but it's the easiest way to ensure coherency between the
 
673
            # state of the RemoteBranch and RemoteRepository objects and the
 
674
            # physical locks.  If we don't materialise the real objects here,
 
675
            # then getting everything in the right state later is complex, so
 
676
            # for now we just do it the lazy way.
 
677
            #   -- Andrew Bennetts, 2007-02-22.
 
678
            self._ensure_real()
491
679
            if self._real_branch is not None:
492
680
                self._real_branch.lock_write(tokens=remote_tokens)
493
681
            if tokens is not None:
516
704
        if response == ('ok',):
517
705
            return
518
706
        elif response[0] == 'TokenMismatch':
519
 
            raise errors.TokenMismatch(token, '(remote token)')
 
707
            raise errors.TokenMismatch(
 
708
                str((branch_token, repo_token)), '(remote tokens)')
520
709
        else:
521
710
            assert False, 'unexpected response code %s' % (response,)
522
711
 
571
760
            return []
572
761
        return result
573
762
 
 
763
    @needs_write_lock
574
764
    def set_revision_history(self, rev_history):
575
765
        # Send just the tip revision of the history; the server will generate
576
766
        # the full history from that.  If the revision doesn't exist in this
580
770
            rev_id = ''
581
771
        else:
582
772
            rev_id = rev_history[-1]
583
 
        response = self._client.call('Branch.set_last_revision', path, rev_id)
 
773
        response = self._client.call('Branch.set_last_revision',
 
774
            path, self._lock_token, self._repo_lock_token, rev_id)
584
775
        if response[0] == 'NoSuchRevision':
585
776
            raise NoSuchRevision(self, rev_id)
586
777
        else:
595
786
        self._ensure_real()
596
787
        return self._real_branch.set_parent(url)
597
788
        
 
789
    def get_config(self):
 
790
        return RemoteBranchConfig(self)
 
791
 
 
792
    @needs_write_lock
 
793
    def append_revision(self, *revision_ids):
 
794
        self._ensure_real()
 
795
        return self._real_branch.append_revision(*revision_ids)
 
796
 
 
797
    @needs_write_lock
 
798
    def pull(self, source, overwrite=False, stop_revision=None):
 
799
        self._ensure_real()
 
800
        self._real_branch.pull(
 
801
            source, overwrite=overwrite, stop_revision=stop_revision)
 
802
 
598
803
 
599
804
class RemoteWorkingTree(object):
600
805
 
608
813
        return getattr(self.real_workingtree, name)
609
814
 
610
815
 
 
816
class RemoteBranchConfig(BranchConfig):
 
817
 
 
818
    def username(self):
 
819
        self.branch._ensure_real()
 
820
        return self.branch._real_branch.get_config().username()
 
821