/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/reconfigure.py

  • Committer: John Arbash Meinel
  • Date: 2008-08-18 22:34:21 UTC
  • mto: (3606.5.6 1.6)
  • mto: This revision was merged to the branch mainline in revision 3641.
  • Revision ID: john@arbash-meinel.com-20080818223421-todjny24vj4faj4t
Add tests for the fetching behavior.

The proper parameter passed is 'unordered' add an assert for it, and
fix callers that were passing 'unsorted' instead.
Add tests that we make the right get_record_stream call based
on the value of _fetch_uses_deltas.
Fix the fetch request for signatures.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2007 Canonical Ltd
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
 
 
17
"""Reconfigure a bzrdir into a new tree/branch/repository layout"""
 
18
 
 
19
from bzrlib import (
 
20
    branch,
 
21
    bzrdir,
 
22
    errors,
 
23
    )
 
24
 
 
25
class Reconfigure(object):
 
26
 
 
27
    def __init__(self, bzrdir, new_bound_location=None):
 
28
        self.bzrdir = bzrdir
 
29
        self.new_bound_location = new_bound_location
 
30
        try:
 
31
            self.repository = self.bzrdir.find_repository()
 
32
        except errors.NoRepositoryPresent:
 
33
            self.repository = None
 
34
        else:
 
35
            if (self.repository.bzrdir.root_transport.base ==
 
36
                self.bzrdir.root_transport.base):
 
37
                self.local_repository = self.repository
 
38
            else:
 
39
                self.local_repository = None
 
40
        try:
 
41
            branch = self.bzrdir.open_branch()
 
42
            if branch.bzrdir.root_transport.base == bzrdir.root_transport.base:
 
43
                self.local_branch = branch
 
44
                self.referenced_branch = None
 
45
            else:
 
46
                self.local_branch = None
 
47
                self.referenced_branch = branch
 
48
        except errors.NotBranchError:
 
49
            self.local_branch = None
 
50
            self.referenced_branch = None
 
51
        try:
 
52
            self.tree = bzrdir.open_workingtree()
 
53
        except errors.NoWorkingTree:
 
54
            self.tree = None
 
55
        self._unbind = False
 
56
        self._bind = False
 
57
        self._destroy_reference = False
 
58
        self._create_reference = False
 
59
        self._destroy_branch = False
 
60
        self._create_branch = False
 
61
        self._destroy_tree = False
 
62
        self._create_tree = False
 
63
        self._create_repository = False
 
64
        self._destroy_repository = False
 
65
 
 
66
    @staticmethod
 
67
    def to_branch(bzrdir):
 
68
        """Return a Reconfiguration to convert this bzrdir into a branch
 
69
 
 
70
        :param bzrdir: The bzrdir to reconfigure
 
71
        :raise errors.AlreadyBranch: if bzrdir is already a branch
 
72
        """
 
73
        reconfiguration = Reconfigure(bzrdir)
 
74
        reconfiguration._plan_changes(want_tree=False, want_branch=True,
 
75
                                      want_bound=False, want_reference=False)
 
76
        if not reconfiguration.changes_planned():
 
77
            raise errors.AlreadyBranch(bzrdir)
 
78
        return reconfiguration
 
79
 
 
80
    @staticmethod
 
81
    def to_tree(bzrdir):
 
82
        """Return a Reconfiguration to convert this bzrdir into a tree
 
83
 
 
84
        :param bzrdir: The bzrdir to reconfigure
 
85
        :raise errors.AlreadyTree: if bzrdir is already a tree
 
86
        """
 
87
        reconfiguration = Reconfigure(bzrdir)
 
88
        reconfiguration._plan_changes(want_tree=True, want_branch=True,
 
89
                                      want_bound=False, want_reference=False)
 
90
        if not reconfiguration.changes_planned():
 
91
            raise errors.AlreadyTree(bzrdir)
 
92
        return reconfiguration
 
93
 
 
94
    @staticmethod
 
95
    def to_checkout(bzrdir, bound_location=None):
 
96
        """Return a Reconfiguration to convert this bzrdir into a checkout
 
97
 
 
98
        :param bzrdir: The bzrdir to reconfigure
 
99
        :param bound_location: The location the checkout should be bound to.
 
100
        :raise errors.AlreadyCheckout: if bzrdir is already a checkout
 
101
        """
 
102
        reconfiguration = Reconfigure(bzrdir, bound_location)
 
103
        reconfiguration._plan_changes(want_tree=True, want_branch=True,
 
104
                                      want_bound=True, want_reference=False)
 
105
        if not reconfiguration.changes_planned():
 
106
            raise errors.AlreadyCheckout(bzrdir)
 
107
        return reconfiguration
 
108
 
 
109
    @classmethod
 
110
    def to_lightweight_checkout(klass, bzrdir, reference_location=None):
 
111
        """Make a Reconfiguration to convert bzrdir into a lightweight checkout
 
112
 
 
113
        :param bzrdir: The bzrdir to reconfigure
 
114
        :param bound_location: The location the checkout should be bound to.
 
115
        :raise errors.AlreadyLightweightCheckout: if bzrdir is already a
 
116
            lightweight checkout
 
117
        """
 
118
        reconfiguration = klass(bzrdir, reference_location)
 
119
        reconfiguration._plan_changes(want_tree=True, want_branch=False,
 
120
                                      want_bound=False, want_reference=True)
 
121
        if not reconfiguration.changes_planned():
 
122
            raise errors.AlreadyLightweightCheckout(bzrdir)
 
123
        return reconfiguration
 
124
 
 
125
    @classmethod
 
126
    def to_use_shared(klass, bzrdir):
 
127
        """Convert a standalone branch into a repository branch"""
 
128
        reconfiguration = klass(bzrdir)
 
129
        reconfiguration._set_use_shared(use_shared=True)
 
130
        if not reconfiguration.changes_planned():
 
131
            raise errors.AlreadyUsingShared(bzrdir)
 
132
        return reconfiguration
 
133
 
 
134
    @classmethod
 
135
    def to_standalone(klass, bzrdir):
 
136
        """Convert a repository branch into a standalone branch"""
 
137
        reconfiguration = klass(bzrdir)
 
138
        reconfiguration._set_use_shared(use_shared=False)
 
139
        if not reconfiguration.changes_planned():
 
140
            raise errors.AlreadyStandalone(bzrdir)
 
141
        return reconfiguration
 
142
 
 
143
    def _plan_changes(self, want_tree, want_branch, want_bound,
 
144
                      want_reference):
 
145
        """Determine which changes are needed to assume the configuration"""
 
146
        if not want_branch and not want_reference:
 
147
            raise errors.ReconfigurationNotSupported(self.bzrdir)
 
148
        if want_branch and want_reference:
 
149
            raise errors.ReconfigurationNotSupported(self.bzrdir)
 
150
        if self.repository is None:
 
151
            if not want_reference:
 
152
                self._create_repository = True
 
153
        else:
 
154
            if want_reference and (self.repository.bzrdir.root_transport.base
 
155
                                   == self.bzrdir.root_transport.base):
 
156
                if not self.repository.is_shared():
 
157
                    self._destroy_repository = True
 
158
        if self.referenced_branch is None:
 
159
            if want_reference:
 
160
                self._create_reference = True
 
161
                if self.local_branch is not None:
 
162
                    self._destroy_branch = True
 
163
        else:
 
164
            if not want_reference:
 
165
                self._destroy_reference = True
 
166
        if self.local_branch is None:
 
167
            if want_branch is True:
 
168
                self._create_branch = True
 
169
                if want_bound:
 
170
                    self._bind = True
 
171
        else:
 
172
            if want_bound:
 
173
                if self.local_branch.get_bound_location() is None:
 
174
                    self._bind = True
 
175
            else:
 
176
                if self.local_branch.get_bound_location() is not None:
 
177
                    self._unbind = True
 
178
        if not want_tree and self.tree is not None:
 
179
            self._destroy_tree = True
 
180
        if want_tree and self.tree is None:
 
181
            self._create_tree = True
 
182
 
 
183
    def _set_use_shared(self, use_shared=None):
 
184
        if use_shared is None:
 
185
            return
 
186
        if use_shared:
 
187
            if self.local_repository is not None:
 
188
                self._destroy_repository = True
 
189
        else:
 
190
            if self.local_repository is None:
 
191
                self._create_repository = True
 
192
 
 
193
    def changes_planned(self):
 
194
        """Return True if changes are planned, False otherwise"""
 
195
        return (self._unbind or self._bind or self._destroy_tree
 
196
                or self._create_tree or self._destroy_reference
 
197
                or self._create_branch or self._create_repository
 
198
                or self._create_reference or self._destroy_repository)
 
199
 
 
200
    def _check(self):
 
201
        """Raise if reconfiguration would destroy local changes"""
 
202
        if self._destroy_tree:
 
203
            changes = self.tree.changes_from(self.tree.basis_tree())
 
204
            if changes.has_changed():
 
205
                raise errors.UncommittedChanges(self.tree)
 
206
        if self._create_reference and self.local_branch is not None:
 
207
            reference_branch = branch.Branch.open(self._select_bind_location())
 
208
            if (reference_branch.last_revision() !=
 
209
                self.local_branch.last_revision()):
 
210
                raise errors.UnsyncedBranches(self.bzrdir, reference_branch)
 
211
 
 
212
    def _select_bind_location(self):
 
213
        """Select a location to bind or create a reference to.
 
214
 
 
215
        Preference is:
 
216
        1. user specified location
 
217
        2. branch reference location (it's a kind of bind location)
 
218
        3. current bind location
 
219
        4. previous bind location (it was a good choice once)
 
220
        5. push location (it's writeable, so committable)
 
221
        6. parent location (it's pullable, so update-from-able)
 
222
        """
 
223
        if self.new_bound_location is not None:
 
224
            return self.new_bound_location
 
225
        if self.local_branch is not None:
 
226
            bound = self.local_branch.get_bound_location()
 
227
            if bound is not None:
 
228
                return bound
 
229
            old_bound = self.local_branch.get_old_bound_location()
 
230
            if old_bound is not None:
 
231
                return old_bound
 
232
            push_location = self.local_branch.get_push_location()
 
233
            if push_location is not None:
 
234
                return push_location
 
235
            parent = self.local_branch.get_parent()
 
236
            if parent is not None:
 
237
                return parent
 
238
        elif self.referenced_branch is not None:
 
239
            return self.referenced_branch.base
 
240
        raise errors.NoBindLocation(self.bzrdir)
 
241
 
 
242
    def apply(self, force=False):
 
243
        """Apply the reconfiguration
 
244
 
 
245
        :param force: If true, the reconfiguration is applied even if it will
 
246
            destroy local changes.
 
247
        :raise errors.UncommittedChanges: if the local tree is to be destroyed
 
248
            but contains uncommitted changes.
 
249
        :raise errors.NoBindLocation: if no bind location was specified and
 
250
            none could be autodetected.
 
251
        """
 
252
        if not force:
 
253
            self._check()
 
254
        if self._create_repository:
 
255
            repo = self.bzrdir.create_repository()
 
256
            if self.local_branch and not self._destroy_branch:
 
257
                repo.fetch(self.local_branch.repository,
 
258
                           self.local_branch.last_revision())
 
259
        else:
 
260
            repo = self.repository
 
261
        if self._create_branch and self.referenced_branch is not None:
 
262
            repo.fetch(self.referenced_branch.repository,
 
263
                       self.referenced_branch.last_revision())
 
264
        if self._create_reference:
 
265
            reference_branch = branch.Branch.open(self._select_bind_location())
 
266
        if self._destroy_repository:
 
267
            if self._create_reference:
 
268
                reference_branch.repository.fetch(self.repository)
 
269
            elif self.local_branch is not None and not self._destroy_branch:
 
270
                up = self.local_branch.bzrdir.root_transport.clone('..')
 
271
                up_bzrdir = bzrdir.BzrDir.open_containing_from_transport(up)[0]
 
272
                new_repo = up_bzrdir.find_repository()
 
273
                new_repo.fetch(self.repository)
 
274
        last_revision_info = None
 
275
        if self._destroy_reference:
 
276
            last_revision_info = self.referenced_branch.last_revision_info()
 
277
            self.bzrdir.destroy_branch()
 
278
        if self._destroy_branch:
 
279
            last_revision_info = self.local_branch.last_revision_info()
 
280
            if self._create_reference:
 
281
                self.local_branch.tags.merge_to(reference_branch.tags)
 
282
            self.bzrdir.destroy_branch()
 
283
        if self._create_branch:
 
284
            local_branch = self.bzrdir.create_branch()
 
285
            if last_revision_info is not None:
 
286
                local_branch.set_last_revision_info(*last_revision_info)
 
287
            if self._destroy_reference:
 
288
                self.referenced_branch.tags.merge_to(local_branch.tags)
 
289
        else:
 
290
            local_branch = self.local_branch
 
291
        if self._create_reference:
 
292
            format = branch.BranchReferenceFormat().initialize(self.bzrdir,
 
293
                reference_branch)
 
294
        if self._destroy_tree:
 
295
            self.bzrdir.destroy_workingtree()
 
296
        if self._create_tree:
 
297
            self.bzrdir.create_workingtree()
 
298
        if self._unbind:
 
299
            self.local_branch.unbind()
 
300
        if self._bind:
 
301
            bind_location = self._select_bind_location()
 
302
            local_branch.bind(branch.Branch.open(bind_location))
 
303
        if self._destroy_repository:
 
304
            self.bzrdir.destroy_repository()