/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.436.115 by Jelmer Vernooij
Register commands lazily, use bzrlib,api to check bzr versions.
1
# Copyright (C) 2007 by Jelmer Vernooij <jelmer@samba.org>
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
0.436.131 by Jelmer Vernooij
Change license back to GPLv2+
5
# the Free Software Foundation; either version 2 of the License, or
0.436.115 by Jelmer Vernooij
Register commands lazily, use bzrlib,api to check bzr versions.
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
"""Bazaar command-line subcommands."""
18
0.436.143 by Jelmer Vernooij
Remove unnecessary imports.
19
from bzrlib.commands import (
20
    Command,
21
    display_command,
22
    )
23
from bzrlib.errors import (
24
    BzrCommandError,
25
    ConflictsInTree,
26
    NoSuchFile,
27
    NoSuchRevision,
28
    NoWorkingTree,
29
    UncommittedChanges,
30
    UnrelatedBranches,
31
    )
32
from bzrlib.option import (
33
    Option,
34
    )
35
from bzrlib.trace import (
36
    info,
37
    warning,
38
    )
0.436.115 by Jelmer Vernooij
Register commands lazily, use bzrlib,api to check bzr versions.
39
40
class cmd_rebase(Command):
41
    """Re-base a branch.
42
43
    Rebasing is the process of taking a branch and modifying the history so
44
    that it appears to start from a different point. This can be useful
45
    to clean up the history before submitting your changes. The tree at the
46
    end of the process will be the same as if you had merged the other branch,
47
    but the history will be different.
48
49
    The command takes the location of another branch on to which the branch in
50
    the current working directory will be rebased. If a branch is not specified
51
    then the parent branch is used, and this is usually the desired result.
52
53
    The first step identifies the revisions that are in the current branch that
54
    are not in the parent branch. The current branch is then set to be at the
55
    same revision as the target branch, and each revision is replayed on top
56
    of the branch. At the end of the process it will appear as though your
57
    current branch was branched off the current last revision of the target.
58
59
    Each revision that is replayed may cause conflicts in the tree. If this
60
    happens the command will stop and allow you to fix them up. Resolve the
61
    commits as you would for a merge, and then run 'bzr resolve' to marked
62
    them as resolved. Once you have resolved all the conflicts you should
63
    run 'bzr rebase-continue' to continue the rebase operation.
64
65
    If conflicts are encountered and you decide that you do not wish to continue
66
    you can run 'bzr rebase-abort'.
67
68
    The '--onto' option allows you to specify a different revision in the
69
    target branch to start at when replaying the revisions. This means that
70
    you can change the point at which the current branch will appear to be
71
    branched from when the operation completes.
72
    """
73
    takes_args = ['upstream_location?']
74
    takes_options = ['revision', 'merge-type', 'verbose',
75
        Option('dry-run',
76
            help="Show what would be done, but don't actually do anything."),
77
        Option('always-rebase-merges',
78
            help="Don't skip revisions that merge already present revisions."),
79
        Option('pending-merges',
80
            help="Rebase pending merges onto local branch."),
81
        Option('onto', help='Different revision to replay onto.',
82
            type=str)]
83
    
84
    @display_command
85
    def run(self, upstream_location=None, onto=None, revision=None,
86
            merge_type=None, verbose=False, dry_run=False,
87
            always_rebase_merges=False, pending_merges=False):
88
        from bzrlib.branch import Branch
89
        from bzrlib.revisionspec import RevisionSpec
90
        from bzrlib.workingtree import WorkingTree
0.436.157 by Jelmer Vernooij
use absolute imports everywhere.
91
        from bzrlib.plugins.rebase.rebase import (
92
            generate_simple_plan,
93
            rebase,
94
            rebase_plan_exists,
95
            read_rebase_plan,
96
            remove_rebase_plan,
97
            workingtree_replay,
98
            write_rebase_plan,
99
            regenerate_default_revid,
100
            rebase_todo,
101
            )
0.436.115 by Jelmer Vernooij
Register commands lazily, use bzrlib,api to check bzr versions.
102
        if revision is not None and pending_merges:
103
            raise BzrCommandError(
104
                "--revision and --pending-merges are mutually exclusive")
105
106
        wt = WorkingTree.open_containing(".")[0]
107
        wt.lock_write()
108
        if upstream_location is None:
109
            if pending_merges:
110
                upstream_location = "."
111
            else:
112
                upstream_location = wt.branch.get_parent()
113
                info("Rebasing on %s" % upstream_location)
114
        upstream = Branch.open_containing(upstream_location)[0]
115
        upstream_repository = upstream.repository
116
        upstream_revision = upstream.last_revision()
117
        try:
118
            # Abort if there already is a plan file
119
            if rebase_plan_exists(wt):
120
                raise BzrCommandError("A rebase operation was interrupted. "
121
                    "Continue using 'bzr rebase-continue' or abort using 'bzr "
122
                    "rebase-abort'")
123
124
            start_revid = None
125
            stop_revid = None
126
            if revision is not None:
127
                if len(revision) == 1:
128
                    if revision[0] is not None:
129
                        stop_revid = revision[0].as_revision_id(wt.branch)
130
                elif len(revision) == 2:
131
                    if revision[0] is not None:
132
                        start_revid = revision[0].as_revision_id(wt.branch)
133
                    if revision[1] is not None:
134
                        stop_revid = revision[1].as_revision_id(wt.branch)
135
                else:
136
                    raise BzrCommandError(
137
                        "--revision takes only one or two arguments")
138
139
            if pending_merges:
140
                wt_parents = wt.get_parent_ids()
141
                if len(wt_parents) in (0, 1):
142
                    raise BzrCommandError("No pending merges present.")
143
                elif len(wt_parents) > 2:
144
                    raise BzrCommandError(
145
                        "Rebasing more than one pending merge not supported")
146
                stop_revid = wt_parents[1]
147
                assert stop_revid is not None, "stop revid invalid"
148
149
            # Pull required revisions
150
            wt.branch.repository.fetch(upstream_repository, upstream_revision)
151
            if onto is None:
152
                onto = upstream.last_revision()
153
            else:
154
                rev_spec = RevisionSpec.from_string(onto)
155
                onto = rev_spec.as_revision_id(upstream)
156
157
            wt.branch.repository.fetch(upstream_repository, onto)
158
159
            if stop_revid is None:
160
                stop_revid = wt.branch.last_revision()
161
            elif not pending_merges:
162
                stop_revid = wt.branch.repository.get_parent_map(
163
                    [stop_revid])[stop_revid][0]
164
            repo_graph = wt.branch.repository.get_graph()
165
            our_new, onto_unique = repo_graph.find_difference(stop_revid, onto)
166
167
            if start_revid is None:
168
                if not onto_unique:
169
                    self.outf.write("No revisions to rebase.\n")
170
                    return
171
                if not our_new:
172
                    self.outf.write("Base branch is descendant of current "
173
                        "branch. Pulling instead.\n")
174
                    wt.pull(upstream, onto)
175
                    return
176
            # else: include extra revisions needed to make start_revid mean
177
            # something.
178
179
            # Create plan
180
            replace_map = generate_simple_plan(
181
                our_new, start_revid, stop_revid,
182
                    onto, repo_graph,
183
                    lambda revid: regenerate_default_revid(
184
                        wt.branch.repository, revid),
185
                    not always_rebase_merges
186
                    )
187
188
            if verbose:
189
                todo = list(rebase_todo(wt.branch.repository, replace_map))
190
                info('%d revisions will be rebased:' % len(todo))
191
                for revid in todo:
192
                    info("%s" % revid)
193
194
            # Check for changes in the working tree.
195
            if (not pending_merges and 
196
                wt.basis_tree().changes_from(wt).has_changed()):
197
                raise UncommittedChanges(wt)
198
199
            if not dry_run:
200
                # Write plan file
201
                write_rebase_plan(wt, replace_map)
202
203
                # Start executing plan
204
                try:
205
                    rebase(wt.branch.repository, replace_map,
206
                           workingtree_replay(wt, merge_type=merge_type))
207
                except ConflictsInTree:
208
                    raise BzrCommandError("A conflict occurred replaying a "
209
                        "commit. Resolve the conflict and run "
210
                        "'bzr rebase-continue' or run 'bzr rebase-abort'.")
211
                # Remove plan file
212
                remove_rebase_plan(wt)
213
        finally:
214
            wt.unlock()
215
216
217
class cmd_rebase_abort(Command):
218
    """Abort an interrupted rebase."""
219
    
220
    @display_command
221
    def run(self):
0.436.157 by Jelmer Vernooij
use absolute imports everywhere.
222
        from bzrlib.plugins.rebase.rebase import (
223
            read_rebase_plan,
224
            remove_rebase_plan,
225
            complete_revert,
226
            )
0.436.115 by Jelmer Vernooij
Register commands lazily, use bzrlib,api to check bzr versions.
227
        from bzrlib.workingtree import WorkingTree
228
        wt = WorkingTree.open_containing('.')[0]
229
        wt.lock_write()
230
        try:
231
            # Read plan file and set last revision
232
            try:
233
                last_rev_info = read_rebase_plan(wt)[0]
234
            except NoSuchFile:
235
                raise BzrCommandError("No rebase to abort")
236
            complete_revert(wt, [last_rev_info[1]])
237
            remove_rebase_plan(wt)
238
        finally:
239
            wt.unlock()
240
241
242
class cmd_rebase_continue(Command):
243
    """Continue an interrupted rebase after resolving conflicts."""
244
    takes_options = ['merge-type']
245
    
246
    @display_command
247
    def run(self, merge_type=None):
0.436.157 by Jelmer Vernooij
use absolute imports everywhere.
248
        from bzrlib.plugins.rebase.rebase import (
249
            commit_rebase,
250
            rebase,
251
            rebase_plan_exists,
252
            read_rebase_plan,
253
            read_active_rebase_revid,
254
            remove_rebase_plan,
255
            workingtree_replay,
256
            )
0.436.115 by Jelmer Vernooij
Register commands lazily, use bzrlib,api to check bzr versions.
257
        from bzrlib.workingtree import WorkingTree
258
        wt = WorkingTree.open_containing('.')[0]
259
        wt.lock_write()
260
        try:
261
            # Abort if there are any conflicts
262
            if len(wt.conflicts()) != 0:
263
                raise BzrCommandError("There are still conflicts present. "
264
                                      "Resolve the conflicts and then run "
265
                                      "'bzr resolve' and try again.")
266
            # Read plan file
267
            try:
268
                replace_map = read_rebase_plan(wt)[1]
269
            except NoSuchFile:
270
                raise BzrCommandError("No rebase to continue")
271
            oldrevid = read_active_rebase_revid(wt)
272
            if oldrevid is not None:
273
                oldrev = wt.branch.repository.get_revision(oldrevid)
274
                commit_rebase(wt, oldrev, replace_map[oldrevid][0])
275
            try:
276
                # Start executing plan from current Branch.last_revision()
277
                rebase(wt.branch.repository, replace_map,
278
                        workingtree_replay(wt, merge_type=merge_type))
279
            except ConflictsInTree:
280
                raise BzrCommandError("A conflict occurred replaying a commit."
281
                    " Resolve the conflict and run 'bzr rebase-continue' or "
282
                    "run 'bzr rebase-abort'.")
283
            # Remove plan file  
284
            remove_rebase_plan(wt)
285
        finally:
286
            wt.unlock()
287
288
289
class cmd_rebase_todo(Command):
290
    """Print list of revisions that still need to be replayed as part of the 
291
    current rebase operation.
292
293
    """
294
    
295
    def run(self):
0.436.157 by Jelmer Vernooij
use absolute imports everywhere.
296
        from bzrlib.plugins.rebase.rebase import (
297
            rebase_todo,
298
            read_rebase_plan,
299
            read_active_rebase_revid,
300
            )
0.436.115 by Jelmer Vernooij
Register commands lazily, use bzrlib,api to check bzr versions.
301
        from bzrlib.workingtree import WorkingTree
302
        wt = WorkingTree.open_containing('.')[0]
303
        wt.lock_read()
304
        try:
305
            try:
306
                replace_map = read_rebase_plan(wt)[1]
307
            except NoSuchFile:
308
                raise BzrCommandError("No rebase in progress")
309
            currentrevid = read_active_rebase_revid(wt)
310
            if currentrevid is not None:
311
                info("Currently replaying: %s" % currentrevid)
312
            for revid in rebase_todo(wt.branch.repository, replace_map):
313
                info("%s -> %s" % (revid, replace_map[revid][0]))
314
        finally:
315
            wt.unlock()
316
317
318
class cmd_replay(Command):
319
    """Replay commits from another branch on top of this one.
320
321
    """
322
    
323
    takes_options = ['revision', 'merge-type']
324
    takes_args = ['location']
325
    hidden = True
326
327
    def run(self, location, revision=None, merge_type=None):
328
        from bzrlib.branch import Branch
329
        from bzrlib.workingtree import WorkingTree
330
        from bzrlib import ui
0.436.157 by Jelmer Vernooij
use absolute imports everywhere.
331
        from bzrlib.plugins.rebase.rebase import (
332
            regenerate_default_revid,
333
            replay_delta_workingtree,
334
            )
0.436.115 by Jelmer Vernooij
Register commands lazily, use bzrlib,api to check bzr versions.
335
336
        from_branch = Branch.open_containing(location)[0]
337
338
        if revision is not None:
339
            if len(revision) == 1:
340
                if revision[0] is not None:
341
                    todo = [revision[0].as_revision_id(from_branch)]
342
            elif len(revision) == 2:
343
                from_revno, from_revid = revision[0].in_history(from_branch)
344
                to_revno, to_revid = revision[1].in_history(from_branch)
345
                if to_revid is None:
346
                    to_revno = from_branch.revno()
347
                todo = []
348
                for revno in range(from_revno, to_revno + 1):
349
                    todo.append(from_branch.get_rev_id(revno))
350
            else:
351
                raise BzrCommandError(
352
                    "--revision takes only one or two arguments")
353
        else:
354
            raise BzrCommandError("--revision is mandatory")
355
356
        wt = WorkingTree.open(".")
357
        wt.lock_write()
358
        pb = ui.ui_factory.nested_progress_bar()
359
        try:
360
            for revid in todo:
361
                pb.update("replaying commits", todo.index(revid), len(todo))
362
                wt.branch.repository.fetch(from_branch.repository, revid)
363
                newrevid = regenerate_default_revid(wt.branch.repository, revid)
364
                replay_delta_workingtree(wt, revid, newrevid,
365
                                         [wt.last_revision()],
366
                                         merge_type=merge_type)
367
        finally:
368
            pb.finished()
369
            wt.unlock()
0.436.139 by Jelmer Vernooij
Import foreign-mapping-upgrade.
370
371
372
class cmd_foreign_mapping_upgrade(Command):
373
    """Upgrade revisions mapped from a foreign version control system.
374
    
375
    This will change the identity of revisions whose parents 
376
    were mapped from revisions in the other version control system.
377
378
    You are recommended to run "bzr check" in the local repository 
379
    after running this command.
380
    """
381
    takes_args = ['from_repository?']
382
    takes_options = ['verbose', 
383
            Option("idmap-file", help="Write map with old and new revision ids.", type=str)]
384
385
    def run(self, from_repository=None, verbose=False, idmap_file=None):
0.436.143 by Jelmer Vernooij
Remove unnecessary imports.
386
        from bzrlib import (
387
            urlutils,
388
            )
0.436.139 by Jelmer Vernooij
Import foreign-mapping-upgrade.
389
        from bzrlib.branch import Branch
390
        from bzrlib.repository import Repository
391
        from bzrlib.workingtree import WorkingTree
0.436.143 by Jelmer Vernooij
Remove unnecessary imports.
392
        from bzrlib.plugins.rebase.upgrade import (
393
            upgrade_branch,
394
            upgrade_workingtree,
395
            )
0.436.139 by Jelmer Vernooij
Import foreign-mapping-upgrade.
396
        try:
397
            wt_to = WorkingTree.open(".")
398
            branch_to = wt_to.branch
399
        except NoWorkingTree:
400
            wt_to = None
401
            branch_to = Branch.open(".")
402
403
        stored_loc = branch_to.get_parent()
404
        if from_repository is None:
405
            if stored_loc is None:
406
                raise BzrCommandError("No pull location known or"
407
                                             " specified.")
408
            else:
409
                display_url = urlutils.unescape_for_display(stored_loc,
410
                        self.outf.encoding)
411
                self.outf.write("Using saved location: %s\n" % display_url)
412
                from_repository = Branch.open(stored_loc).repository
413
        else:
414
            from_repository = Repository.open(from_repository)
415
416
        vcs = getattr(from_repository, "vcs", None)
417
        if vcs is None:
418
            raise BzrCommandError("Repository at %s is not a foreign repository.a" % from_repository.base)
419
420
        new_mapping = from_repository.get_mapping()
421
422
        if wt_to is not None:
423
            renames = upgrade_workingtree(wt_to, from_repository, 
424
                                          new_mapping=new_mapping,
425
                                          allow_changes=True, verbose=verbose)
426
        else:
427
            renames = upgrade_branch(branch_to, from_repository, 
428
                                     new_mapping=new_mapping,
429
                                     allow_changes=True, verbose=verbose)
430
431
        if renames == {}:
432
            info("Nothing to do.")
433
434
        if idmap_file is not None:
435
            f = open(idmap_file, 'w')
436
            try:
437
                for oldid, newid in renames.iteritems():
438
                    f.write("%s\t%s\n" % (oldid, newid))
439
            finally:
440
                f.close()
441
442
        if wt_to is not None:
443
            wt_to.set_last_revision(branch_to.last_revision())