/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: James Westby
  • Date: 2007-09-18 18:55:00 UTC
  • mto: (2866.1.1 james.westby)
  • mto: This revision was merged to the branch mainline in revision 2867.
  • Revision ID: jw+debian@jameswestby.net-20070918185500-91alkjx8zolds1v8
Fix log against smart server branches that don't support tags. (#140615)

Add get_reverse_tag_dict to DisabledTags for branches that falsely
claim that they support tags (namely smart server branches). When the
remote branch was an old format without tags this caused log to fail.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007-2010 Canonical Ltd
 
1
# Copyright (C) 2007 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
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
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
 
Various types of reconfiguration operation are available either by
20
 
constructing a class or using a factory method on Reconfigure.
21
 
"""
22
 
 
 
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"""
23
18
 
24
19
from bzrlib import (
25
20
    branch,
26
 
    bzrdir,
27
21
    errors,
28
 
    trace,
29
 
    ui,
30
 
    urlutils,
31
22
    )
32
23
 
33
 
 
34
 
# TODO: common base class for all reconfigure operations, making no
35
 
# assumptions about what kind of change will be done.
36
 
 
37
 
 
38
 
class ReconfigureStackedOn(object):
39
 
    """Reconfigures a branch to be stacked on another branch."""
40
 
 
41
 
    def apply(self, bzrdir, stacked_on_url):
42
 
        branch = bzrdir.open_branch()
43
 
        # it may be a path relative to the cwd or a url; the branch wants
44
 
        # a path relative to itself...
45
 
        on_url = urlutils.relative_url(branch.base,
46
 
            urlutils.normalize_url(stacked_on_url))
47
 
        branch.lock_write()
48
 
        try:
49
 
            branch.set_stacked_on_url(on_url)
50
 
            if not trace.is_quiet():
51
 
                ui.ui_factory.note(
52
 
                    "%s is now stacked on %s\n"
53
 
                    % (branch.base, branch.get_stacked_on_url()))
54
 
        finally:
55
 
            branch.unlock()
56
 
 
57
 
 
58
 
class ReconfigureUnstacked(object):
59
 
 
60
 
    def apply(self, bzrdir):
61
 
        branch = bzrdir.open_branch()
62
 
        branch.lock_write()
63
 
        try:
64
 
            branch.set_stacked_on_url(None)
65
 
            if not trace.is_quiet():
66
 
                ui.ui_factory.note(
67
 
                    "%s is now not stacked\n"
68
 
                    % (branch.base,))
69
 
        finally:
70
 
            branch.unlock()
71
 
 
72
 
 
73
24
class Reconfigure(object):
74
25
 
75
26
    def __init__(self, bzrdir, new_bound_location=None):
76
27
        self.bzrdir = bzrdir
77
28
        self.new_bound_location = new_bound_location
78
 
        self.local_repository = None
79
29
        try:
80
30
            self.repository = self.bzrdir.find_repository()
81
31
        except errors.NoRepositoryPresent:
82
32
            self.repository = None
83
 
            self.local_repository = None
84
 
        else:
85
 
            if (self.repository.user_url == self.bzrdir.user_url):
86
 
                self.local_repository = self.repository
87
 
            else:
88
 
                self.local_repository = None
89
33
        try:
90
34
            branch = self.bzrdir.open_branch()
91
 
            if branch.user_url == bzrdir.user_url:
 
35
            if branch.bzrdir.root_transport.base == bzrdir.root_transport.base:
92
36
                self.local_branch = branch
93
37
                self.referenced_branch = None
94
38
            else:
104
48
        self._unbind = False
105
49
        self._bind = False
106
50
        self._destroy_reference = False
107
 
        self._create_reference = False
108
 
        self._destroy_branch = False
109
51
        self._create_branch = False
110
52
        self._destroy_tree = False
111
53
        self._create_tree = False
112
54
        self._create_repository = False
113
 
        self._destroy_repository = False
114
 
        self._repository_trees = None
115
55
 
116
56
    @staticmethod
117
57
    def to_branch(bzrdir):
119
59
 
120
60
        :param bzrdir: The bzrdir to reconfigure
121
61
        :raise errors.AlreadyBranch: if bzrdir is already a branch
 
62
        :raise errors.ReconfigurationNotSupported: if bzrdir does not contain
 
63
            a branch or branch reference
122
64
        """
123
65
        reconfiguration = Reconfigure(bzrdir)
124
66
        reconfiguration._plan_changes(want_tree=False, want_branch=True,
125
 
                                      want_bound=False, want_reference=False)
 
67
                                      want_bound=False)
126
68
        if not reconfiguration.changes_planned():
127
69
            raise errors.AlreadyBranch(bzrdir)
128
70
        return reconfiguration
133
75
 
134
76
        :param bzrdir: The bzrdir to reconfigure
135
77
        :raise errors.AlreadyTree: if bzrdir is already a tree
 
78
        :raise errors.ReconfigurationNotSupported: if bzrdir does not contain
 
79
            a branch or branch reference
136
80
        """
137
81
        reconfiguration = Reconfigure(bzrdir)
138
82
        reconfiguration._plan_changes(want_tree=True, want_branch=True,
139
 
                                      want_bound=False, want_reference=False)
 
83
                                      want_bound=False)
140
84
        if not reconfiguration.changes_planned():
141
85
            raise errors.AlreadyTree(bzrdir)
142
86
        return reconfiguration
148
92
        :param bzrdir: The bzrdir to reconfigure
149
93
        :param bound_location: The location the checkout should be bound to.
150
94
        :raise errors.AlreadyCheckout: if bzrdir is already a checkout
 
95
        :raise errors.ReconfigurationNotSupported: if bzrdir does not contain
 
96
            a branch or branch reference
151
97
        """
152
98
        reconfiguration = Reconfigure(bzrdir, bound_location)
153
99
        reconfiguration._plan_changes(want_tree=True, want_branch=True,
154
 
                                      want_bound=True, want_reference=False)
 
100
                                      want_bound=True)
155
101
        if not reconfiguration.changes_planned():
156
102
            raise errors.AlreadyCheckout(bzrdir)
157
103
        return reconfiguration
158
104
 
159
 
    @classmethod
160
 
    def to_lightweight_checkout(klass, bzrdir, reference_location=None):
161
 
        """Make a Reconfiguration to convert bzrdir into a lightweight checkout
162
 
 
163
 
        :param bzrdir: The bzrdir to reconfigure
164
 
        :param bound_location: The location the checkout should be bound to.
165
 
        :raise errors.AlreadyLightweightCheckout: if bzrdir is already a
166
 
            lightweight checkout
167
 
        """
168
 
        reconfiguration = klass(bzrdir, reference_location)
169
 
        reconfiguration._plan_changes(want_tree=True, want_branch=False,
170
 
                                      want_bound=False, want_reference=True)
171
 
        if not reconfiguration.changes_planned():
172
 
            raise errors.AlreadyLightweightCheckout(bzrdir)
173
 
        return reconfiguration
174
 
 
175
 
    @classmethod
176
 
    def to_use_shared(klass, bzrdir):
177
 
        """Convert a standalone branch into a repository branch"""
178
 
        reconfiguration = klass(bzrdir)
179
 
        reconfiguration._set_use_shared(use_shared=True)
180
 
        if not reconfiguration.changes_planned():
181
 
            raise errors.AlreadyUsingShared(bzrdir)
182
 
        return reconfiguration
183
 
 
184
 
    @classmethod
185
 
    def to_standalone(klass, bzrdir):
186
 
        """Convert a repository branch into a standalone branch"""
187
 
        reconfiguration = klass(bzrdir)
188
 
        reconfiguration._set_use_shared(use_shared=False)
189
 
        if not reconfiguration.changes_planned():
190
 
            raise errors.AlreadyStandalone(bzrdir)
191
 
        return reconfiguration
192
 
 
193
 
    @classmethod
194
 
    def set_repository_trees(klass, bzrdir, with_trees):
195
 
        """Adjust a repository's working tree presence default"""
196
 
        reconfiguration = klass(bzrdir)
197
 
        if not reconfiguration.repository.is_shared():
198
 
            raise errors.ReconfigurationNotSupported(reconfiguration.bzrdir)
199
 
        if with_trees and reconfiguration.repository.make_working_trees():
200
 
            raise errors.AlreadyWithTrees(bzrdir)
201
 
        elif (not with_trees
202
 
              and not reconfiguration.repository.make_working_trees()):
203
 
            raise errors.AlreadyWithNoTrees(bzrdir)
204
 
        else:
205
 
            reconfiguration._repository_trees = with_trees
206
 
        return reconfiguration
207
 
 
208
 
    def _plan_changes(self, want_tree, want_branch, want_bound,
209
 
                      want_reference):
 
105
    def _plan_changes(self, want_tree, want_branch, want_bound):
210
106
        """Determine which changes are needed to assume the configuration"""
211
 
        if not want_branch and not want_reference:
212
 
            raise errors.ReconfigurationNotSupported(self.bzrdir)
213
 
        if want_branch and want_reference:
214
 
            raise errors.ReconfigurationNotSupported(self.bzrdir)
215
107
        if self.repository is None:
216
 
            if not want_reference:
217
 
                self._create_repository = True
218
 
        else:
219
 
            if want_reference and (
220
 
                self.repository.user_url == self.bzrdir.user_url):
221
 
                if not self.repository.is_shared():
222
 
                    self._destroy_repository = True
223
 
        if self.referenced_branch is None:
224
 
            if want_reference:
225
 
                self._create_reference = True
226
 
                if self.local_branch is not None:
227
 
                    self._destroy_branch = True
228
 
        else:
229
 
            if not want_reference:
230
 
                self._destroy_reference = True
 
108
            self._create_repository = True
231
109
        if self.local_branch is None:
232
110
            if want_branch is True:
233
 
                self._create_branch = True
234
 
                if want_bound:
235
 
                    self._bind = True
 
111
                if self.referenced_branch is not None:
 
112
                    self._destroy_reference = True
 
113
                    self._create_branch = True
 
114
                    if want_bound:
 
115
                        self._bind = True
 
116
                else:
 
117
                    raise errors.ReconfigurationNotSupported(self.bzrdir)
236
118
        else:
237
119
            if want_bound:
238
120
                if self.local_branch.get_bound_location() is None:
245
127
        if want_tree and self.tree is None:
246
128
            self._create_tree = True
247
129
 
248
 
    def _set_use_shared(self, use_shared=None):
249
 
        if use_shared is None:
250
 
            return
251
 
        if use_shared:
252
 
            if self.local_repository is not None:
253
 
                self._destroy_repository = True
254
 
        else:
255
 
            if self.local_repository is None:
256
 
                self._create_repository = True
257
 
 
258
130
    def changes_planned(self):
259
131
        """Return True if changes are planned, False otherwise"""
260
132
        return (self._unbind or self._bind or self._destroy_tree
261
133
                or self._create_tree or self._destroy_reference
262
 
                or self._create_branch or self._create_repository
263
 
                or self._create_reference or self._destroy_repository)
 
134
                or self._create_branch or self._create_repository)
264
135
 
265
136
    def _check(self):
266
137
        """Raise if reconfiguration would destroy local changes"""
267
 
        if self._destroy_tree and self.tree.has_changes():
 
138
        if self._destroy_tree:
 
139
            changes = self.tree.changes_from(self.tree.basis_tree())
 
140
            if changes.has_changed():
268
141
                raise errors.UncommittedChanges(self.tree)
269
 
        if self._create_reference and self.local_branch is not None:
270
 
            reference_branch = branch.Branch.open(self._select_bind_location())
271
 
            if (reference_branch.last_revision() !=
272
 
                self.local_branch.last_revision()):
273
 
                raise errors.UnsyncedBranches(self.bzrdir, reference_branch)
274
142
 
275
143
    def _select_bind_location(self):
276
 
        """Select a location to bind or create a reference to.
 
144
        """Select a location to bind to.
277
145
 
278
146
        Preference is:
279
147
        1. user specified location
280
148
        2. branch reference location (it's a kind of bind location)
281
 
        3. current bind location
282
 
        4. previous bind location (it was a good choice once)
283
 
        5. push location (it's writeable, so committable)
284
 
        6. parent location (it's pullable, so update-from-able)
 
149
        3. previous bind location (it was a good choice once)
 
150
        4. push location (it's writeable, so committable)
 
151
        5. parent location (it's pullable, so update-from-able)
285
152
        """
286
153
        if self.new_bound_location is not None:
287
154
            return self.new_bound_location
288
155
        if self.local_branch is not None:
289
 
            bound = self.local_branch.get_bound_location()
290
 
            if bound is not None:
291
 
                return bound
292
156
            old_bound = self.local_branch.get_old_bound_location()
293
157
            if old_bound is not None:
294
158
                return old_bound
315
179
        if not force:
316
180
            self._check()
317
181
        if self._create_repository:
318
 
            if self.local_branch and not self._destroy_branch:
319
 
                old_repo = self.local_branch.repository
320
 
            elif self._create_branch and self.referenced_branch is not None:
321
 
                old_repo = self.referenced_branch.repository
322
 
            else:
323
 
                old_repo = None
324
 
            if old_repo is not None:
325
 
                repository_format = old_repo._format
326
 
            else:
327
 
                repository_format = None
328
 
            if repository_format is not None:
329
 
                repo = repository_format.initialize(self.bzrdir)
330
 
            else:
331
 
                repo = self.bzrdir.create_repository()
332
 
            if self.local_branch and not self._destroy_branch:
333
 
                repo.fetch(self.local_branch.repository,
334
 
                           self.local_branch.last_revision())
 
182
            repo = self.bzrdir.create_repository()
335
183
        else:
336
184
            repo = self.repository
337
 
        if self._create_branch and self.referenced_branch is not None:
 
185
        if self._create_branch:
338
186
            repo.fetch(self.referenced_branch.repository,
339
187
                       self.referenced_branch.last_revision())
340
 
        if self._create_reference:
341
 
            reference_branch = branch.Branch.open(self._select_bind_location())
342
 
        if self._destroy_repository:
343
 
            if self._create_reference:
344
 
                reference_branch.repository.fetch(self.repository)
345
 
            elif self.local_branch is not None and not self._destroy_branch:
346
 
                up = self.local_branch.user_transport.clone('..')
347
 
                up_bzrdir = bzrdir.BzrDir.open_containing_from_transport(up)[0]
348
 
                new_repo = up_bzrdir.find_repository()
349
 
                new_repo.fetch(self.repository)
350
 
        last_revision_info = None
351
188
        if self._destroy_reference:
352
 
            last_revision_info = self.referenced_branch.last_revision_info()
353
 
            self.bzrdir.destroy_branch()
354
 
        if self._destroy_branch:
355
 
            last_revision_info = self.local_branch.last_revision_info()
356
 
            if self._create_reference:
357
 
                self.local_branch.tags.merge_to(reference_branch.tags)
 
189
            reference_info = self.referenced_branch.last_revision_info()
358
190
            self.bzrdir.destroy_branch()
359
191
        if self._create_branch:
360
192
            local_branch = self.bzrdir.create_branch()
361
 
            if last_revision_info is not None:
362
 
                local_branch.set_last_revision_info(*last_revision_info)
363
 
            if self._destroy_reference:
364
 
                self.referenced_branch.tags.merge_to(local_branch.tags)
365
 
                self.referenced_branch.update_references(local_branch)
 
193
            local_branch.set_last_revision_info(*reference_info)
366
194
        else:
367
195
            local_branch = self.local_branch
368
 
        if self._create_reference:
369
 
            format = branch.BranchReferenceFormat().initialize(self.bzrdir,
370
 
                target_branch=reference_branch)
371
196
        if self._destroy_tree:
372
197
            self.bzrdir.destroy_workingtree()
373
198
        if self._create_tree:
377
202
        if self._bind:
378
203
            bind_location = self._select_bind_location()
379
204
            local_branch.bind(branch.Branch.open(bind_location))
380
 
        if self._destroy_repository:
381
 
            self.bzrdir.destroy_repository()
382
 
        if self._repository_trees is not None:
383
 
            repo.set_make_working_trees(self._repository_trees)