/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: 2009-06-18 18:18:36 UTC
  • mto: This revision was merged to the branch mainline in revision 4461.
  • Revision ID: john@arbash-meinel.com-20090618181836-biodfkat9a8eyzjz
The new add_inventory_by_delta is returning a CHKInventory when mapping from NULL
Which is completely valid, but 'broke' one of the tests.
So to fix it, changed the test to use CHKInventories on both sides, and add an __eq__
member. The nice thing is that CHKInventory.__eq__ is fairly cheap, since it only
has to check the root keys.

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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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
            self.local_repository = None
 
35
        else:
 
36
            if (self.repository.bzrdir.root_transport.base ==
 
37
                self.bzrdir.root_transport.base):
 
38
                self.local_repository = self.repository
 
39
            else:
 
40
                self.local_repository = None
 
41
        try:
 
42
            branch = self.bzrdir.open_branch()
 
43
            if branch.bzrdir.root_transport.base == bzrdir.root_transport.base:
 
44
                self.local_branch = branch
 
45
                self.referenced_branch = None
 
46
            else:
 
47
                self.local_branch = None
 
48
                self.referenced_branch = branch
 
49
        except errors.NotBranchError:
 
50
            self.local_branch = None
 
51
            self.referenced_branch = None
 
52
        try:
 
53
            self.tree = bzrdir.open_workingtree()
 
54
        except errors.NoWorkingTree:
 
55
            self.tree = None
 
56
        self._unbind = False
 
57
        self._bind = False
 
58
        self._destroy_reference = False
 
59
        self._create_reference = False
 
60
        self._destroy_branch = False
 
61
        self._create_branch = False
 
62
        self._destroy_tree = False
 
63
        self._create_tree = False
 
64
        self._create_repository = False
 
65
        self._destroy_repository = False
 
66
        self._repository_trees = None
 
67
 
 
68
    @staticmethod
 
69
    def to_branch(bzrdir):
 
70
        """Return a Reconfiguration to convert this bzrdir into a branch
 
71
 
 
72
        :param bzrdir: The bzrdir to reconfigure
 
73
        :raise errors.AlreadyBranch: if bzrdir is already a branch
 
74
        """
 
75
        reconfiguration = Reconfigure(bzrdir)
 
76
        reconfiguration._plan_changes(want_tree=False, want_branch=True,
 
77
                                      want_bound=False, want_reference=False)
 
78
        if not reconfiguration.changes_planned():
 
79
            raise errors.AlreadyBranch(bzrdir)
 
80
        return reconfiguration
 
81
 
 
82
    @staticmethod
 
83
    def to_tree(bzrdir):
 
84
        """Return a Reconfiguration to convert this bzrdir into a tree
 
85
 
 
86
        :param bzrdir: The bzrdir to reconfigure
 
87
        :raise errors.AlreadyTree: if bzrdir is already a tree
 
88
        """
 
89
        reconfiguration = Reconfigure(bzrdir)
 
90
        reconfiguration._plan_changes(want_tree=True, want_branch=True,
 
91
                                      want_bound=False, want_reference=False)
 
92
        if not reconfiguration.changes_planned():
 
93
            raise errors.AlreadyTree(bzrdir)
 
94
        return reconfiguration
 
95
 
 
96
    @staticmethod
 
97
    def to_checkout(bzrdir, bound_location=None):
 
98
        """Return a Reconfiguration to convert this bzrdir into a checkout
 
99
 
 
100
        :param bzrdir: The bzrdir to reconfigure
 
101
        :param bound_location: The location the checkout should be bound to.
 
102
        :raise errors.AlreadyCheckout: if bzrdir is already a checkout
 
103
        """
 
104
        reconfiguration = Reconfigure(bzrdir, bound_location)
 
105
        reconfiguration._plan_changes(want_tree=True, want_branch=True,
 
106
                                      want_bound=True, want_reference=False)
 
107
        if not reconfiguration.changes_planned():
 
108
            raise errors.AlreadyCheckout(bzrdir)
 
109
        return reconfiguration
 
110
 
 
111
    @classmethod
 
112
    def to_lightweight_checkout(klass, bzrdir, reference_location=None):
 
113
        """Make a Reconfiguration to convert bzrdir into a lightweight checkout
 
114
 
 
115
        :param bzrdir: The bzrdir to reconfigure
 
116
        :param bound_location: The location the checkout should be bound to.
 
117
        :raise errors.AlreadyLightweightCheckout: if bzrdir is already a
 
118
            lightweight checkout
 
119
        """
 
120
        reconfiguration = klass(bzrdir, reference_location)
 
121
        reconfiguration._plan_changes(want_tree=True, want_branch=False,
 
122
                                      want_bound=False, want_reference=True)
 
123
        if not reconfiguration.changes_planned():
 
124
            raise errors.AlreadyLightweightCheckout(bzrdir)
 
125
        return reconfiguration
 
126
 
 
127
    @classmethod
 
128
    def to_use_shared(klass, bzrdir):
 
129
        """Convert a standalone branch into a repository branch"""
 
130
        reconfiguration = klass(bzrdir)
 
131
        reconfiguration._set_use_shared(use_shared=True)
 
132
        if not reconfiguration.changes_planned():
 
133
            raise errors.AlreadyUsingShared(bzrdir)
 
134
        return reconfiguration
 
135
 
 
136
    @classmethod
 
137
    def to_standalone(klass, bzrdir):
 
138
        """Convert a repository branch into a standalone branch"""
 
139
        reconfiguration = klass(bzrdir)
 
140
        reconfiguration._set_use_shared(use_shared=False)
 
141
        if not reconfiguration.changes_planned():
 
142
            raise errors.AlreadyStandalone(bzrdir)
 
143
        return reconfiguration
 
144
 
 
145
    @classmethod
 
146
    def set_repository_trees(klass, bzrdir, with_trees):
 
147
        """Adjust a repository's working tree presence default"""
 
148
        reconfiguration = klass(bzrdir)
 
149
        if not reconfiguration.repository.is_shared():
 
150
            raise errors.ReconfigurationNotSupported(reconfiguration.bzrdir)
 
151
        if with_trees and reconfiguration.repository.make_working_trees():
 
152
            raise errors.AlreadyWithTrees(bzrdir)
 
153
        elif (not with_trees
 
154
              and not reconfiguration.repository.make_working_trees()):
 
155
            raise errors.AlreadyWithNoTrees(bzrdir)
 
156
        else:
 
157
            reconfiguration._repository_trees = with_trees
 
158
        return reconfiguration
 
159
 
 
160
    def _plan_changes(self, want_tree, want_branch, want_bound,
 
161
                      want_reference):
 
162
        """Determine which changes are needed to assume the configuration"""
 
163
        if not want_branch and not want_reference:
 
164
            raise errors.ReconfigurationNotSupported(self.bzrdir)
 
165
        if want_branch and want_reference:
 
166
            raise errors.ReconfigurationNotSupported(self.bzrdir)
 
167
        if self.repository is None:
 
168
            if not want_reference:
 
169
                self._create_repository = True
 
170
        else:
 
171
            if want_reference and (self.repository.bzrdir.root_transport.base
 
172
                                   == self.bzrdir.root_transport.base):
 
173
                if not self.repository.is_shared():
 
174
                    self._destroy_repository = True
 
175
        if self.referenced_branch is None:
 
176
            if want_reference:
 
177
                self._create_reference = True
 
178
                if self.local_branch is not None:
 
179
                    self._destroy_branch = True
 
180
        else:
 
181
            if not want_reference:
 
182
                self._destroy_reference = True
 
183
        if self.local_branch is None:
 
184
            if want_branch is True:
 
185
                self._create_branch = True
 
186
                if want_bound:
 
187
                    self._bind = True
 
188
        else:
 
189
            if want_bound:
 
190
                if self.local_branch.get_bound_location() is None:
 
191
                    self._bind = True
 
192
            else:
 
193
                if self.local_branch.get_bound_location() is not None:
 
194
                    self._unbind = True
 
195
        if not want_tree and self.tree is not None:
 
196
            self._destroy_tree = True
 
197
        if want_tree and self.tree is None:
 
198
            self._create_tree = True
 
199
 
 
200
    def _set_use_shared(self, use_shared=None):
 
201
        if use_shared is None:
 
202
            return
 
203
        if use_shared:
 
204
            if self.local_repository is not None:
 
205
                self._destroy_repository = True
 
206
        else:
 
207
            if self.local_repository is None:
 
208
                self._create_repository = True
 
209
 
 
210
    def changes_planned(self):
 
211
        """Return True if changes are planned, False otherwise"""
 
212
        return (self._unbind or self._bind or self._destroy_tree
 
213
                or self._create_tree or self._destroy_reference
 
214
                or self._create_branch or self._create_repository
 
215
                or self._create_reference or self._destroy_repository)
 
216
 
 
217
    def _check(self):
 
218
        """Raise if reconfiguration would destroy local changes"""
 
219
        if self._destroy_tree:
 
220
            changes = self.tree.changes_from(self.tree.basis_tree())
 
221
            if changes.has_changed():
 
222
                raise errors.UncommittedChanges(self.tree)
 
223
        if self._create_reference and self.local_branch is not None:
 
224
            reference_branch = branch.Branch.open(self._select_bind_location())
 
225
            if (reference_branch.last_revision() !=
 
226
                self.local_branch.last_revision()):
 
227
                raise errors.UnsyncedBranches(self.bzrdir, reference_branch)
 
228
 
 
229
    def _select_bind_location(self):
 
230
        """Select a location to bind or create a reference to.
 
231
 
 
232
        Preference is:
 
233
        1. user specified location
 
234
        2. branch reference location (it's a kind of bind location)
 
235
        3. current bind location
 
236
        4. previous bind location (it was a good choice once)
 
237
        5. push location (it's writeable, so committable)
 
238
        6. parent location (it's pullable, so update-from-able)
 
239
        """
 
240
        if self.new_bound_location is not None:
 
241
            return self.new_bound_location
 
242
        if self.local_branch is not None:
 
243
            bound = self.local_branch.get_bound_location()
 
244
            if bound is not None:
 
245
                return bound
 
246
            old_bound = self.local_branch.get_old_bound_location()
 
247
            if old_bound is not None:
 
248
                return old_bound
 
249
            push_location = self.local_branch.get_push_location()
 
250
            if push_location is not None:
 
251
                return push_location
 
252
            parent = self.local_branch.get_parent()
 
253
            if parent is not None:
 
254
                return parent
 
255
        elif self.referenced_branch is not None:
 
256
            return self.referenced_branch.base
 
257
        raise errors.NoBindLocation(self.bzrdir)
 
258
 
 
259
    def apply(self, force=False):
 
260
        """Apply the reconfiguration
 
261
 
 
262
        :param force: If true, the reconfiguration is applied even if it will
 
263
            destroy local changes.
 
264
        :raise errors.UncommittedChanges: if the local tree is to be destroyed
 
265
            but contains uncommitted changes.
 
266
        :raise errors.NoBindLocation: if no bind location was specified and
 
267
            none could be autodetected.
 
268
        """
 
269
        if not force:
 
270
            self._check()
 
271
        if self._create_repository:
 
272
            if self.local_branch and not self._destroy_branch:
 
273
                old_repo = self.local_branch.repository
 
274
            elif self._create_branch and self.referenced_branch is not None:
 
275
                old_repo = self.referenced_branch.repository
 
276
            else:
 
277
                old_repo = None
 
278
            if old_repo is not None:
 
279
                repository_format = old_repo._format
 
280
            else:
 
281
                repository_format = None
 
282
            if repository_format is not None:
 
283
                repo = repository_format.initialize(self.bzrdir)
 
284
            else:
 
285
                repo = self.bzrdir.create_repository()
 
286
            if self.local_branch and not self._destroy_branch:
 
287
                repo.fetch(self.local_branch.repository,
 
288
                           self.local_branch.last_revision())
 
289
        else:
 
290
            repo = self.repository
 
291
        if self._create_branch and self.referenced_branch is not None:
 
292
            repo.fetch(self.referenced_branch.repository,
 
293
                       self.referenced_branch.last_revision())
 
294
        if self._create_reference:
 
295
            reference_branch = branch.Branch.open(self._select_bind_location())
 
296
        if self._destroy_repository:
 
297
            if self._create_reference:
 
298
                reference_branch.repository.fetch(self.repository)
 
299
            elif self.local_branch is not None and not self._destroy_branch:
 
300
                up = self.local_branch.bzrdir.root_transport.clone('..')
 
301
                up_bzrdir = bzrdir.BzrDir.open_containing_from_transport(up)[0]
 
302
                new_repo = up_bzrdir.find_repository()
 
303
                new_repo.fetch(self.repository)
 
304
        last_revision_info = None
 
305
        if self._destroy_reference:
 
306
            last_revision_info = self.referenced_branch.last_revision_info()
 
307
            self.bzrdir.destroy_branch()
 
308
        if self._destroy_branch:
 
309
            last_revision_info = self.local_branch.last_revision_info()
 
310
            if self._create_reference:
 
311
                self.local_branch.tags.merge_to(reference_branch.tags)
 
312
            self.bzrdir.destroy_branch()
 
313
        if self._create_branch:
 
314
            local_branch = self.bzrdir.create_branch()
 
315
            if last_revision_info is not None:
 
316
                local_branch.set_last_revision_info(*last_revision_info)
 
317
            if self._destroy_reference:
 
318
                self.referenced_branch.tags.merge_to(local_branch.tags)
 
319
                self.referenced_branch.update_references(local_branch)
 
320
        else:
 
321
            local_branch = self.local_branch
 
322
        if self._create_reference:
 
323
            format = branch.BranchReferenceFormat().initialize(self.bzrdir,
 
324
                reference_branch)
 
325
        if self._destroy_tree:
 
326
            self.bzrdir.destroy_workingtree()
 
327
        if self._create_tree:
 
328
            self.bzrdir.create_workingtree()
 
329
        if self._unbind:
 
330
            self.local_branch.unbind()
 
331
        if self._bind:
 
332
            bind_location = self._select_bind_location()
 
333
            local_branch.bind(branch.Branch.open(bind_location))
 
334
        if self._destroy_repository:
 
335
            self.bzrdir.destroy_repository()
 
336
        if self._repository_trees is not None:
 
337
            repo.set_make_working_trees(self._repository_trees)