~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/bzrdir.py

  • Committer: Patch Queue Manager
  • Date: 2014-02-12 18:22:22 UTC
  • mfrom: (6589.2.1 trunk)
  • Revision ID: pqm@pqm.ubuntu.com-20140212182222-beouo25gaf1cny76
(vila) The XDG Base Directory Specification uses the XDG_CACHE_HOME,
 not XDG_CACHE_DIR. (Andrew Starr-Bochicchio)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006 Canonical Ltd
 
1
# Copyright (C) 2006-2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
16
16
 
17
17
"""Server-side bzrdir related request implmentations."""
18
18
 
 
19
from __future__ import absolute_import
19
20
 
20
 
from bzrlib import branch, errors, repository
21
 
from bzrlib.bzrdir import BzrDir, BzrDirFormat, BzrDirMetaFormat1
 
21
from bzrlib import (
 
22
    bencode,
 
23
    branch,
 
24
    errors,
 
25
    repository,
 
26
    urlutils,
 
27
    )
 
28
from bzrlib.bzrdir import (
 
29
    BzrDir,
 
30
    BzrDirFormat,
 
31
    BzrProber,
 
32
    )
 
33
from bzrlib.controldir import (
 
34
    network_format_registry,
 
35
    )
22
36
from bzrlib.smart.request import (
23
37
    FailedSmartServerResponse,
24
38
    SmartServerRequest,
29
43
class SmartServerRequestOpenBzrDir(SmartServerRequest):
30
44
 
31
45
    def do(self, path):
32
 
        from bzrlib.bzrdir import BzrDirFormat
33
46
        try:
34
47
            t = self.transport_from_client_path(path)
35
48
        except errors.PathNotChild:
40
53
            # clients that don't anticipate errors from this method.
41
54
            answer = 'no'
42
55
        else:
43
 
            default_format = BzrDirFormat.get_default_format()
44
 
            real_bzrdir = default_format.open(t, _found=True)
 
56
            bzr_prober = BzrProber()
45
57
            try:
46
 
                real_bzrdir._format.probe_transport(t)
 
58
                bzr_prober.probe_transport(t)
47
59
            except (errors.NotBranchError, errors.UnknownFormatError):
48
60
                answer = 'no'
49
61
            else:
51
63
        return SuccessfulSmartServerResponse((answer,))
52
64
 
53
65
 
 
66
class SmartServerRequestOpenBzrDir_2_1(SmartServerRequest):
 
67
 
 
68
    def do(self, path):
 
69
        """Is there a BzrDir present, and if so does it have a working tree?
 
70
 
 
71
        New in 2.1.
 
72
        """
 
73
        try:
 
74
            t = self.transport_from_client_path(path)
 
75
        except errors.PathNotChild:
 
76
            # The client is trying to ask about a path that they have no access
 
77
            # to.
 
78
            return SuccessfulSmartServerResponse(('no',))
 
79
        try:
 
80
            bd = BzrDir.open_from_transport(t)
 
81
        except errors.NotBranchError:
 
82
            answer = ('no',)
 
83
        else:
 
84
            answer = ('yes',)
 
85
            if bd.has_workingtree():
 
86
                answer += ('yes',)
 
87
            else:
 
88
                answer += ('no',)
 
89
        return SuccessfulSmartServerResponse(answer)
 
90
 
 
91
 
54
92
class SmartServerRequestBzrDir(SmartServerRequest):
55
93
 
56
94
    def do(self, path, *args):
57
 
        """Open a BzrDir at path, and return self.do_bzrdir_request(*args)."""
 
95
        """Open a BzrDir at path, and return `self.do_bzrdir_request(*args)`."""
58
96
        try:
59
97
            self._bzrdir = BzrDir.open_from_transport(
60
98
                self.transport_from_client_path(path))
61
 
        except errors.NotBranchError:
62
 
            return FailedSmartServerResponse(('nobranch', ))
 
99
        except errors.NotBranchError, e:
 
100
            return FailedSmartServerResponse(('nobranch',))
63
101
        return self.do_bzrdir_request(*args)
64
102
 
65
103
    def _boolean_to_yes_no(self, a_boolean):
80
118
        """Get the relative path for repository from current_transport."""
81
119
        # the relpath of the bzrdir in the found repository gives us the
82
120
        # path segments to pop-out.
83
 
        relpath = repository.bzrdir.root_transport.relpath(
 
121
        relpath = repository.user_transport.relpath(
84
122
            current_transport.base)
85
123
        if len(relpath):
86
124
            segments = ['..'] * len(relpath.split('/'))
89
127
        return '/'.join(segments)
90
128
 
91
129
 
 
130
class SmartServerBzrDirRequestDestroyBranch(SmartServerRequestBzrDir):
 
131
 
 
132
    def do_bzrdir_request(self, name=None):
 
133
        """Destroy the branch with the specified name.
 
134
 
 
135
        New in 2.5.0.
 
136
        :return: On success, 'ok'.
 
137
        """
 
138
        try:
 
139
            self._bzrdir.destroy_branch(name)
 
140
        except errors.NotBranchError, e:
 
141
            return FailedSmartServerResponse(('nobranch',))
 
142
        return SuccessfulSmartServerResponse(('ok',))
 
143
 
 
144
 
 
145
class SmartServerBzrDirRequestHasWorkingTree(SmartServerRequestBzrDir):
 
146
 
 
147
    def do_bzrdir_request(self, name=None):
 
148
        """Check whether there is a working tree present.
 
149
 
 
150
        New in 2.5.0.
 
151
 
 
152
        :return: If there is a working tree present, 'yes'.
 
153
            Otherwise 'no'.
 
154
        """
 
155
        if self._bzrdir.has_workingtree():
 
156
            return SuccessfulSmartServerResponse(('yes', ))
 
157
        else:
 
158
            return SuccessfulSmartServerResponse(('no', ))
 
159
 
 
160
 
 
161
class SmartServerBzrDirRequestDestroyRepository(SmartServerRequestBzrDir):
 
162
 
 
163
    def do_bzrdir_request(self, name=None):
 
164
        """Destroy the repository.
 
165
 
 
166
        New in 2.5.0.
 
167
 
 
168
        :return: On success, 'ok'.
 
169
        """
 
170
        try:
 
171
            self._bzrdir.destroy_repository()
 
172
        except errors.NoRepositoryPresent, e:
 
173
            return FailedSmartServerResponse(('norepository',))
 
174
        return SuccessfulSmartServerResponse(('ok',))
 
175
 
 
176
 
92
177
class SmartServerBzrDirRequestCloningMetaDir(SmartServerRequestBzrDir):
93
178
 
94
179
    def do_bzrdir_request(self, require_stacking):
118
203
        control_format = self._bzrdir.cloning_metadir(
119
204
            require_stacking=require_stacking)
120
205
        control_name = control_format.network_name()
121
 
        # XXX: There should be a method that tells us that the format does/does
122
 
        # not have subformats.
123
 
        if isinstance(control_format, BzrDirMetaFormat1):
 
206
        if not control_format.fixed_components:
124
207
            branch_name = ('branch',
125
208
                control_format.get_branch_format().network_name())
126
209
            repository_name = control_format.repository_format.network_name()
132
215
            branch_name))
133
216
 
134
217
 
 
218
class SmartServerBzrDirRequestCheckoutMetaDir(SmartServerRequestBzrDir):
 
219
    """Get the format to use for checkouts.
 
220
 
 
221
    New in 2.5.
 
222
 
 
223
    :return: on success, a 3-tuple of network names for (control,
 
224
        repository, branch) directories, where '' signifies "not present".
 
225
        If this BzrDir contains a branch reference then this will fail with
 
226
        BranchReference; clients should resolve branch references before
 
227
        calling this RPC (they should not try to create a checkout of a
 
228
        checkout).
 
229
    """
 
230
 
 
231
    def do_bzrdir_request(self):
 
232
        try:
 
233
            branch_ref = self._bzrdir.get_branch_reference()
 
234
        except errors.NotBranchError:
 
235
            branch_ref = None
 
236
        if branch_ref is not None:
 
237
            # The server shouldn't try to resolve references, and it quite
 
238
            # possibly can't reach them anyway.  The client needs to resolve
 
239
            # the branch reference to determine the cloning_metadir.
 
240
            return FailedSmartServerResponse(('BranchReference',))
 
241
        control_format = self._bzrdir.checkout_metadir()
 
242
        control_name = control_format.network_name()
 
243
        if not control_format.fixed_components:
 
244
            branch_name = control_format.get_branch_format().network_name()
 
245
            repo_name = control_format.repository_format.network_name()
 
246
        else:
 
247
            branch_name = ''
 
248
            repo_name = ''
 
249
        return SuccessfulSmartServerResponse(
 
250
            (control_name, repo_name, branch_name))
 
251
 
 
252
 
135
253
class SmartServerRequestCreateBranch(SmartServerRequestBzrDir):
136
254
 
137
255
    def do(self, path, network_name):
149
267
 
150
268
        :param path: The path to the bzrdir.
151
269
        :param network_name: The network name of the branch type to create.
152
 
        :return: (ok, network_name)
 
270
        :return: ('ok', branch_format, repo_path, rich_root, tree_ref,
 
271
            external_lookup, repo_format)
153
272
        """
154
273
        bzrdir = BzrDir.open_from_transport(
155
274
            self.transport_from_client_path(path))
156
275
        format = branch.network_format_registry.get(network_name)
157
276
        bzrdir.branch_format = format
158
 
        result = format.initialize(bzrdir)
 
277
        result = format.initialize(bzrdir, name="")
159
278
        rich_root, tree_ref, external_lookup = self._format_to_capabilities(
160
279
            result.repository._format)
161
280
        branch_format = result._format.network_name()
312
431
        return SuccessfulSmartServerResponse((), content)
313
432
 
314
433
 
 
434
class SmartServerBzrDirRequestGetBranches(SmartServerRequestBzrDir):
 
435
 
 
436
    def do_bzrdir_request(self):
 
437
        """Get the branches in a control directory.
 
438
        
 
439
        The body is a bencoded dictionary, with values similar to the return
 
440
        value of the open branch request.
 
441
        """
 
442
        branches = self._bzrdir.get_branches()
 
443
        ret = {}
 
444
        for name, b in branches.iteritems():
 
445
            if name is None:
 
446
                name = ""
 
447
            ret[name] = ("branch", b._format.network_name())
 
448
        return SuccessfulSmartServerResponse(
 
449
            ("success", ), bencode.bencode(ret))
 
450
 
 
451
 
315
452
class SmartServerRequestInitializeBzrDir(SmartServerRequest):
316
453
 
317
454
    def do(self, path):
325
462
        return SuccessfulSmartServerResponse(('ok', ))
326
463
 
327
464
 
 
465
class SmartServerRequestBzrDirInitializeEx(SmartServerRequestBzrDir):
 
466
 
 
467
    def parse_NoneTrueFalse(self, arg):
 
468
        if not arg:
 
469
            return None
 
470
        if arg == 'False':
 
471
            return False
 
472
        if arg == 'True':
 
473
            return True
 
474
        raise AssertionError("invalid arg %r" % arg)
 
475
 
 
476
    def parse_NoneString(self, arg):
 
477
        return arg or None
 
478
 
 
479
    def _serialize_NoneTrueFalse(self, arg):
 
480
        if arg is False:
 
481
            return 'False'
 
482
        if not arg:
 
483
            return ''
 
484
        return 'True'
 
485
 
 
486
    def do(self, bzrdir_network_name, path, use_existing_dir, create_prefix,
 
487
        force_new_repo, stacked_on, stack_on_pwd, repo_format_name,
 
488
        make_working_trees, shared_repo):
 
489
        """Initialize a bzrdir at path as per
 
490
        BzrDirFormat.initialize_on_transport_ex.
 
491
 
 
492
        New in 1.16.  (Replaces BzrDirFormat.initialize_ex verb from 1.15).
 
493
 
 
494
        :return: return SuccessfulSmartServerResponse((repo_path, rich_root,
 
495
            tree_ref, external_lookup, repo_network_name,
 
496
            repo_bzrdir_network_name, bzrdir_format_network_name,
 
497
            NoneTrueFalse(stacking), final_stack, final_stack_pwd,
 
498
            repo_lock_token))
 
499
        """
 
500
        target_transport = self.transport_from_client_path(path)
 
501
        format = network_format_registry.get(bzrdir_network_name)
 
502
        use_existing_dir = self.parse_NoneTrueFalse(use_existing_dir)
 
503
        create_prefix = self.parse_NoneTrueFalse(create_prefix)
 
504
        force_new_repo = self.parse_NoneTrueFalse(force_new_repo)
 
505
        stacked_on = self.parse_NoneString(stacked_on)
 
506
        stack_on_pwd = self.parse_NoneString(stack_on_pwd)
 
507
        make_working_trees = self.parse_NoneTrueFalse(make_working_trees)
 
508
        shared_repo = self.parse_NoneTrueFalse(shared_repo)
 
509
        if stack_on_pwd == '.':
 
510
            stack_on_pwd = target_transport.base
 
511
        repo_format_name = self.parse_NoneString(repo_format_name)
 
512
        repo, bzrdir, stacking, repository_policy = \
 
513
            format.initialize_on_transport_ex(target_transport,
 
514
            use_existing_dir=use_existing_dir, create_prefix=create_prefix,
 
515
            force_new_repo=force_new_repo, stacked_on=stacked_on,
 
516
            stack_on_pwd=stack_on_pwd, repo_format_name=repo_format_name,
 
517
            make_working_trees=make_working_trees, shared_repo=shared_repo)
 
518
        if repo is None:
 
519
            repo_path = ''
 
520
            repo_name = ''
 
521
            rich_root = tree_ref = external_lookup = ''
 
522
            repo_bzrdir_name = ''
 
523
            final_stack = None
 
524
            final_stack_pwd = None
 
525
            repo_lock_token = ''
 
526
        else:
 
527
            repo_path = self._repo_relpath(bzrdir.root_transport, repo)
 
528
            if repo_path == '':
 
529
                repo_path = '.'
 
530
            rich_root, tree_ref, external_lookup = self._format_to_capabilities(
 
531
                repo._format)
 
532
            repo_name = repo._format.network_name()
 
533
            repo_bzrdir_name = repo.bzrdir._format.network_name()
 
534
            final_stack = repository_policy._stack_on
 
535
            final_stack_pwd = repository_policy._stack_on_pwd
 
536
            # It is returned locked, but we need to do the lock to get the lock
 
537
            # token.
 
538
            repo.unlock()
 
539
            repo_lock_token = repo.lock_write().repository_token or ''
 
540
            if repo_lock_token:
 
541
                repo.leave_lock_in_place()
 
542
            repo.unlock()
 
543
        final_stack = final_stack or ''
 
544
        final_stack_pwd = final_stack_pwd or ''
 
545
 
 
546
        # We want this to be relative to the bzrdir.
 
547
        if final_stack_pwd:
 
548
            final_stack_pwd = urlutils.relative_url(
 
549
                target_transport.base, final_stack_pwd)
 
550
 
 
551
        # Can't meaningfully return a root path.
 
552
        if final_stack.startswith('/'):
 
553
            client_path = self._root_client_path + final_stack[1:]
 
554
            final_stack = urlutils.relative_url(
 
555
                self._root_client_path, client_path)
 
556
            final_stack_pwd = '.'
 
557
 
 
558
        return SuccessfulSmartServerResponse((repo_path, rich_root, tree_ref,
 
559
            external_lookup, repo_name, repo_bzrdir_name,
 
560
            bzrdir._format.network_name(),
 
561
            self._serialize_NoneTrueFalse(stacking), final_stack,
 
562
            final_stack_pwd, repo_lock_token))
 
563
 
 
564
 
328
565
class SmartServerRequestOpenBranch(SmartServerRequestBzrDir):
329
566
 
330
567
    def do_bzrdir_request(self):
335
572
                return SuccessfulSmartServerResponse(('ok', ''))
336
573
            else:
337
574
                return SuccessfulSmartServerResponse(('ok', reference_url))
338
 
        except errors.NotBranchError:
339
 
            return FailedSmartServerResponse(('nobranch', ))
 
575
        except errors.NotBranchError, e:
 
576
            return FailedSmartServerResponse(('nobranch',))
340
577
 
341
578
 
342
579
class SmartServerRequestOpenBranchV2(SmartServerRequestBzrDir):
351
588
                return SuccessfulSmartServerResponse(('branch', format))
352
589
            else:
353
590
                return SuccessfulSmartServerResponse(('ref', reference_url))
354
 
        except errors.NotBranchError:
355
 
            return FailedSmartServerResponse(('nobranch', ))
 
591
        except errors.NotBranchError, e:
 
592
            return FailedSmartServerResponse(('nobranch',))
 
593
 
 
594
 
 
595
class SmartServerRequestOpenBranchV3(SmartServerRequestBzrDir):
 
596
 
 
597
    def do_bzrdir_request(self):
 
598
        """Open a branch at path and return the reference or format.
 
599
        
 
600
        This version introduced in 2.1.
 
601
 
 
602
        Differences to SmartServerRequestOpenBranchV2:
 
603
          * can return 2-element ('nobranch', extra), where 'extra' is a string
 
604
            with an explanation like 'location is a repository'.  Previously
 
605
            a 'nobranch' response would never have more than one element.
 
606
        """
 
607
        try:
 
608
            reference_url = self._bzrdir.get_branch_reference()
 
609
            if reference_url is None:
 
610
                br = self._bzrdir.open_branch(ignore_fallbacks=True)
 
611
                format = br._format.network_name()
 
612
                return SuccessfulSmartServerResponse(('branch', format))
 
613
            else:
 
614
                return SuccessfulSmartServerResponse(('ref', reference_url))
 
615
        except errors.NotBranchError, e:
 
616
            # Stringify the exception so that its .detail attribute will be
 
617
            # filled out.
 
618
            str(e)
 
619
            resp = ('nobranch',)
 
620
            detail = e.detail
 
621
            if detail:
 
622
                if detail.startswith(': '):
 
623
                    detail = detail[2:]
 
624
                resp += (detail,)
 
625
            return FailedSmartServerResponse(resp)
 
626