/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.436.25 by Jelmer Vernooij
Add setup.py.
1
# Copyright (C) 2007 by Jelmer Vernooij <jelmer@samba.org>
0.436.2 by Jelmer Vernooij
Add stubs for testsuite, rebase-continue and rebase-abort commands.
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
0.436.25 by Jelmer Vernooij
Add setup.py.
16
"""Rebase support.
17
18
The Bazaar rebase plugin adds support for rebasing branches to Bazaar.
19
It adds the command 'rebase' to Bazaar. When conflicts occur when replaying
20
patches, the user can resolve the conflict and continue the rebase using the
21
'rebase-continue' command or abort using the 'rebase-abort' command.
22
"""
0.436.1 by Jelmer Vernooij
Add framework for git-rebase plugin.
23
0.436.4 by Jelmer Vernooij
Add some tests.
24
from bzrlib.commands import Command, Option, display_command, register_command
0.436.16 by Jelmer Vernooij
Some more work on maptree.
25
from bzrlib.errors import (BzrCommandError, ConflictsInTree, NoSuchFile, 
0.436.58 by Jelmer Vernooij
Raise exception about pending changes /before/ writing plan.
26
                           UnrelatedBranches, NoSuchRevision, 
27
                           UncommittedChanges)
0.436.49 by Jelmer Vernooij
Fix locking.
28
from bzrlib.trace import info, warning
0.436.1 by Jelmer Vernooij
Add framework for git-rebase plugin.
29
0.436.60 by Jelmer Vernooij
Open 0.3 for development.
30
version_info = (0, 3, 0, 'dev', 0)
0.436.49 by Jelmer Vernooij
Fix locking.
31
if version_info[3] == 'final':
32
    version_string = '%d.%d.%d' % version_info[:3]
33
else:
34
    version_string = '%d.%d.%d%s%d' % version_info
35
__version__ = version_string
0.436.25 by Jelmer Vernooij
Add setup.py.
36
__author__ = 'Jelmer Vernooij <jelmer@samba.org>'
37
0.436.49 by Jelmer Vernooij
Fix locking.
38
min_compatible_bzr_version = (0, 92)
39
40
def check_bzrlib_version(desired):
41
    """Check that bzrlib is compatible.
42
43
    If version is < all compatible version, assume incompatible.
44
    """
45
    import bzrlib
46
    bzrlib_version = bzrlib.version_info[:2]
47
    if bzrlib.version_info[3] == 'dev':
48
        return
49
    if bzrlib_version < desired:
50
        warning('Installed bzr version %s is too old to be used with bzr-rebase'
51
                ' %s.' % (bzrlib.__version__, __version__))
52
        # Not using BzrNewError, because it may not exist.
53
        raise Exception, ('Version mismatch', desired)
54
55
56
check_bzrlib_version(min_compatible_bzr_version)
57
0.436.43 by Jelmer Vernooij
Factor out common revid code - maybe some of this can use aaron's common ancestor code instead?
58
def find_last_common_revid(revhistory1, revhistory2):
59
    for revid in reversed(revhistory1):
60
        if revid in revhistory2:
61
            return revid
62
63
    raise UnrelatedBranches()
64
65
0.436.1 by Jelmer Vernooij
Add framework for git-rebase plugin.
66
class cmd_rebase(Command):
67
    """Re-base a branch.
68
0.437.5 by James Westby
Add some help text to the rebase command.
69
    Rebasing is the process of taking a branch and modifying the history so
70
    that it appears to start from a different point. This can be useful
71
    to clean up the history before submitting your changes. The tree at the
72
    end of the process will be the same as if you had merged the other branch,
73
    but the history will be different.
74
75
    The command takes the location of another branch on to which the branch in
76
    the current working directory will be rebased. If a branch is not specified
77
    then the parent branch is used, and this is usually the desired result.
78
79
    The first step identifies the revisions that are in the current branch that
80
    are not in the parent branch. The current branch is then set to be at the
81
    same revision as the target branch, and each revision is replayed on top
82
    of the branch. At the end of the process it will appear as though your
83
    current branch was branched off the current last revision of the target.
84
85
    Each revision that is replayed may cause conflicts in the tree. If this
86
    happens the command will stop and allow you to fix them up. Resolve the
87
    commits as you would for a merge, and then run 'bzr resolve' to marked
88
    them as resolved. Once you have resolved all the conflicts you should
89
    run 'bzr rebase-continue' to continue the rebase operation.
90
91
    If conflicts are encountered and you decide that you do not wish to continue
92
    you can run 'bzr rebase-abort'.
93
94
    The '--onto' option allows you to specify a different revision in the
95
    target branch to start at when replaying the revisions. This means that
96
    you can change the point at which the current branch will appear to be
97
    branched from when the operation completes.
0.436.1 by Jelmer Vernooij
Add framework for git-rebase plugin.
98
    """
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
99
    takes_args = ['upstream_location?']
0.436.19 by Jelmer Vernooij
- Add blackbox tests
100
    takes_options = ['revision', 'merge-type', 'verbose',
0.436.29 by Jelmer Vernooij
Add --dry-run option to rebase command.
101
        Option('dry-run',
0.436.57 by Jelmer Vernooij
Allow overridding whether merges of already merged revisions should be replayed.
102
            help="Show what would be done, but don't actually do anything."),
103
        Option('always-rebase-merges',
104
            help="Don't skip revisions that merge already present revisions."),
0.436.29 by Jelmer Vernooij
Add --dry-run option to rebase command.
105
        Option('onto', help='Different revision to replay onto.',
0.436.57 by Jelmer Vernooij
Allow overridding whether merges of already merged revisions should be replayed.
106
            type=str)]
0.436.1 by Jelmer Vernooij
Add framework for git-rebase plugin.
107
    
108
    @display_command
0.436.16 by Jelmer Vernooij
Some more work on maptree.
109
    def run(self, upstream_location=None, onto=None, revision=None, 
0.436.57 by Jelmer Vernooij
Allow overridding whether merges of already merged revisions should be replayed.
110
            merge_type=None, verbose=False, dry_run=False, 
111
            always_rebase_merges=False):
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
112
        from bzrlib.branch import Branch
113
        from bzrlib.revisionspec import RevisionSpec
114
        from bzrlib.workingtree import WorkingTree
0.436.16 by Jelmer Vernooij
Some more work on maptree.
115
        from rebase import (generate_simple_plan, rebase, rebase_plan_exists, 
116
                            read_rebase_plan, remove_rebase_plan, 
0.437.4 by James Westby
Import rebase_todo as it is needed for --verbose.
117
                            workingtree_replay, write_rebase_plan,
0.436.39 by Jelmer Vernooij
Some more refactoring, add test that demonstrates #126743.
118
                            regenerate_default_revid,
0.437.4 by James Westby
Import rebase_todo as it is needed for --verbose.
119
                            rebase_todo)
0.436.66 by Jelmer Vernooij
Don't require use of the rebase command in root of the branch.
120
        wt = WorkingTree.open_containing(".")[0]
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
121
        wt.lock_write()
122
        if upstream_location is None:
0.436.68 by Jelmer Vernooij
Prefer push location over parent when rebasing.
123
            upstream_location = wt.branch.get_push_location()
124
            if upstream_location is None:
125
                upstream_location = wt.branch.get_parent()
0.438.3 by Jelmer Vernooij
Add stop_revid argumen to generate_simple_plan.
126
            info("Rebasing on %s" % upstream_location)
0.436.65 by Jelmer Vernooij
Don't require running in the branch root.
127
        upstream = Branch.open_containing(upstream_location)[0]
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
128
        upstream_repository = upstream.repository
129
        upstream_revision = upstream.last_revision()
0.436.3 by Jelmer Vernooij
Fill in commands.
130
        try:
131
            # Abort if there already is a plan file
132
            if rebase_plan_exists(wt):
133
                raise BzrCommandError("A rebase operation was interrupted. Continue using 'bzr rebase-continue' or abort using 'bzr rebase-abort'")
134
0.436.43 by Jelmer Vernooij
Factor out common revid code - maybe some of this can use aaron's common ancestor code instead?
135
            start_revid = None
136
            stop_revid = None
137
            if revision is not None:
138
                if len(revision) == 1:
139
                    if revision[0] is not None:
140
                        stop_revid = revision[0].in_history(wt.branch).rev_id
141
                elif len(revision) == 2:
142
                    if revision[0] is not None:
143
                        start_revid = revision[0].in_history(wt.branch).rev_id
144
                    if revision[1] is not None:
145
                        stop_revid = revision[1].in_history(wt.branch).rev_id
146
                else:
147
                    raise BzrCommandError(
148
                        "--revision takes only one or two arguments")
149
0.436.3 by Jelmer Vernooij
Fill in commands.
150
            # Pull required revisions
0.436.29 by Jelmer Vernooij
Add --dry-run option to rebase command.
151
            wt.branch.repository.fetch(upstream_repository, upstream_revision)
0.436.3 by Jelmer Vernooij
Fill in commands.
152
            if onto is None:
153
                onto = upstream.last_revision()
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
154
            else:
0.437.2 by James Westby
Lookup the onto revision in the upstream branch.
155
                rev_spec = RevisionSpec.from_string(onto)
156
                onto = rev_spec.in_history(upstream).rev_id
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
157
158
            wt.branch.repository.fetch(upstream_repository, onto)
159
0.436.43 by Jelmer Vernooij
Factor out common revid code - maybe some of this can use aaron's common ancestor code instead?
160
            if stop_revid is not None:
161
                wt.branch.generate_revision_history(stop_revid)
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
162
            revhistory = wt.branch.revision_history()
0.436.43 by Jelmer Vernooij
Factor out common revid code - maybe some of this can use aaron's common ancestor code instead?
163
164
            if start_revid is None:
165
                common_revid = find_last_common_revid(revhistory, 
166
                                                 upstream.revision_history())
167
                if common_revid == upstream.last_revision():
0.436.67 by Jelmer Vernooij
Inform user about already being rebased rather than erroring.
168
                    self.outf.write("No revisions to rebase.")
169
                    return
0.436.51 by Jelmer Vernooij
Give proper warning when there is no common base.
170
                try:
171
                    start_revid = wt.branch.get_rev_id(
172
                            wt.branch.revision_id_to_revno(common_revid)+1)
173
                except NoSuchRevision:
174
                    raise BzrCommandError("No common revision, please specify --revision")
0.436.12 by Jelmer Vernooij
Give sane error when branch is already rebased.
175
0.436.3 by Jelmer Vernooij
Fill in commands.
176
            # Create plan
0.436.4 by Jelmer Vernooij
Add some tests.
177
            replace_map = generate_simple_plan(
0.436.43 by Jelmer Vernooij
Factor out common revid code - maybe some of this can use aaron's common ancestor code instead?
178
                    revhistory, start_revid, stop_revid, onto,
0.438.1 by Jelmer Vernooij
Split out function for determining rebase base.
179
                    wt.branch.repository.get_ancestry(onto),
0.436.39 by Jelmer Vernooij
Some more refactoring, add test that demonstrates #126743.
180
                    wt.branch.repository.revision_parents,
0.436.57 by Jelmer Vernooij
Allow overridding whether merges of already merged revisions should be replayed.
181
                    lambda revid: regenerate_default_revid(wt.branch.repository, revid),
182
                    not always_rebase_merges
0.436.39 by Jelmer Vernooij
Some more refactoring, add test that demonstrates #126743.
183
                    )
0.436.3 by Jelmer Vernooij
Fill in commands.
184
0.436.19 by Jelmer Vernooij
- Add blackbox tests
185
            if verbose:
0.436.29 by Jelmer Vernooij
Add --dry-run option to rebase command.
186
                todo = list(rebase_todo(wt.branch.repository, replace_map))
187
                info('%d revisions will be rebased:' % len(todo))
188
                for revid in todo:
189
                    info("%s" % revid)
190
0.436.58 by Jelmer Vernooij
Raise exception about pending changes /before/ writing plan.
191
            # Check for changes in the working tree.
192
            if wt.basis_tree().changes_from(wt).has_changed():
193
                raise UncommittedChanges(wt)
194
0.436.29 by Jelmer Vernooij
Add --dry-run option to rebase command.
195
            if not dry_run:
196
                # Write plan file
197
                write_rebase_plan(wt, replace_map)
198
199
                # Start executing plan
200
                try:
201
                    rebase(wt.branch.repository, replace_map, 
202
                           workingtree_replay(wt, merge_type=merge_type))
203
                except ConflictsInTree:
204
                    raise BzrCommandError("A conflict occurred replaying a commit. Resolve the conflict and run 'bzr rebase-continue' or run 'bzr rebase-abort'.")
205
                # Remove plan file
206
                remove_rebase_plan(wt)
0.436.3 by Jelmer Vernooij
Fill in commands.
207
        finally:
208
            wt.unlock()
0.436.2 by Jelmer Vernooij
Add stubs for testsuite, rebase-continue and rebase-abort commands.
209
0.436.12 by Jelmer Vernooij
Give sane error when branch is already rebased.
210
0.436.2 by Jelmer Vernooij
Add stubs for testsuite, rebase-continue and rebase-abort commands.
211
class cmd_rebase_abort(Command):
212
    """Abort an interrupted rebase
213
214
    """
215
    
216
    @display_command
217
    def run(self):
0.436.10 by Jelmer Vernooij
Add more agressive version of revert.
218
        from rebase import read_rebase_plan, remove_rebase_plan, complete_revert
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
219
        from bzrlib.workingtree import WorkingTree
0.439.1 by Jelmer Vernooij
Allow use in non-root directories for rebase-continue, rebase-todo and rebase-abort.
220
        wt = WorkingTree.open_containing('.')[0]
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
221
        wt.lock_write()
0.436.3 by Jelmer Vernooij
Fill in commands.
222
        try:
223
            # Read plan file and set last revision
0.436.9 by Jelmer Vernooij
Add rebase-todo command, fix rebase-continue.
224
            try:
225
                last_rev_info = read_rebase_plan(wt)[0]
226
            except NoSuchFile:
227
                raise BzrCommandError("No rebase to abort")
0.436.10 by Jelmer Vernooij
Add more agressive version of revert.
228
            complete_revert(wt, [last_rev_info[1]])
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
229
            remove_rebase_plan(wt)
0.436.3 by Jelmer Vernooij
Fill in commands.
230
        finally:
231
            wt.unlock()
0.436.2 by Jelmer Vernooij
Add stubs for testsuite, rebase-continue and rebase-abort commands.
232
233
234
class cmd_rebase_continue(Command):
235
    """Continue an interrupted rebase after resolving conflicts
236
237
    """
0.436.13 by Jelmer Vernooij
Add progress bar, some optimizations. Make merge type configurable.
238
    takes_options = ['merge-type']
0.436.2 by Jelmer Vernooij
Add stubs for testsuite, rebase-continue and rebase-abort commands.
239
    
240
    @display_command
0.436.13 by Jelmer Vernooij
Add progress bar, some optimizations. Make merge type configurable.
241
    def run(self, merge_type=None):
0.436.16 by Jelmer Vernooij
Some more work on maptree.
242
        from rebase import (commit_rebase, rebase, rebase_plan_exists, 
243
                            read_rebase_plan, read_active_rebase_revid, 
244
                            remove_rebase_plan, workingtree_replay)
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
245
        from bzrlib.workingtree import WorkingTree
0.439.1 by Jelmer Vernooij
Allow use in non-root directories for rebase-continue, rebase-todo and rebase-abort.
246
        wt = WorkingTree.open_containing('.')[0]
0.436.7 by Jelmer Vernooij
Add more test, make basic rebase work.
247
        wt.lock_write()
0.436.3 by Jelmer Vernooij
Fill in commands.
248
        try:
249
            # Abort if there are any conflicts
250
            if len(wt.conflicts()) != 0:
0.437.3 by James Westby
Provide a hint in the conflicts present message to rebase-continue.
251
                raise BzrCommandError("There are still conflicts present. "
252
                                      "Resolve the conflicts and then run "
253
                                      "'bzr resolve' and try again.")
0.436.3 by Jelmer Vernooij
Fill in commands.
254
            # Read plan file
0.436.9 by Jelmer Vernooij
Add rebase-todo command, fix rebase-continue.
255
            try:
256
                replace_map = read_rebase_plan(wt)[1]
257
            except NoSuchFile:
258
                raise BzrCommandError("No rebase to continue")
259
            oldrevid = read_active_rebase_revid(wt)
260
            if oldrevid is not None:
261
                oldrev = wt.branch.repository.get_revision(oldrevid)
262
                commit_rebase(wt, oldrev, replace_map[oldrevid][0])
0.436.3 by Jelmer Vernooij
Fill in commands.
263
            try:
264
                # Start executing plan from current Branch.last_revision()
0.436.16 by Jelmer Vernooij
Some more work on maptree.
265
                rebase(wt.branch.repository, replace_map, 
266
                        workingtree_replay(wt, merge_type=merge_type))
0.436.8 by Jelmer Vernooij
Couple more minor fixes.
267
            except ConflictsInTree:
268
                raise BzrCommandError("A conflict occurred replaying a commit. Resolve the conflict and run 'bzr rebase-continue' or run 'bzr rebase-abort'.")
0.436.3 by Jelmer Vernooij
Fill in commands.
269
            # Remove plan file  
270
            remove_rebase_plan(wt)
271
        finally:
272
            wt.unlock()
0.436.2 by Jelmer Vernooij
Add stubs for testsuite, rebase-continue and rebase-abort commands.
273
274
0.436.9 by Jelmer Vernooij
Add rebase-todo command, fix rebase-continue.
275
class cmd_rebase_todo(Command):
0.436.16 by Jelmer Vernooij
Some more work on maptree.
276
    """Print list of revisions that still need to be replayed as part of the 
277
    current rebase operation.
0.436.9 by Jelmer Vernooij
Add rebase-todo command, fix rebase-continue.
278
279
    """
280
    
281
    def run(self):
0.436.16 by Jelmer Vernooij
Some more work on maptree.
282
        from rebase import (rebase_todo, read_rebase_plan, 
283
                            read_active_rebase_revid)
0.436.9 by Jelmer Vernooij
Add rebase-todo command, fix rebase-continue.
284
        from bzrlib.workingtree import WorkingTree
0.439.1 by Jelmer Vernooij
Allow use in non-root directories for rebase-continue, rebase-todo and rebase-abort.
285
        wt = WorkingTree.open_containing('.')[0]
0.436.9 by Jelmer Vernooij
Add rebase-todo command, fix rebase-continue.
286
        wt.lock_read()
287
        try:
288
            try:
289
                replace_map = read_rebase_plan(wt)[1]
290
            except NoSuchFile:
0.436.16 by Jelmer Vernooij
Some more work on maptree.
291
                raise BzrCommandError("No rebase in progress")
0.436.9 by Jelmer Vernooij
Add rebase-todo command, fix rebase-continue.
292
            currentrevid = read_active_rebase_revid(wt)
293
            if currentrevid is not None:
294
                info("Currently replaying: %s" % currentrevid)
295
            for revid in rebase_todo(wt.branch.repository, replace_map):
296
                info("%s -> %s" % (revid, replace_map[revid][0]))
297
        finally:
298
            wt.unlock()
299
0.439.1 by Jelmer Vernooij
Allow use in non-root directories for rebase-continue, rebase-todo and rebase-abort.
300
0.436.48 by Jelmer Vernooij
Add replay command.
301
class cmd_replay(Command):
0.436.65 by Jelmer Vernooij
Don't require running in the branch root.
302
    """Replay commits from another branch on top of this one.
0.436.48 by Jelmer Vernooij
Add replay command.
303
304
    """
305
    
306
    takes_options = ['revision', 'merge-type']
307
    takes_args = ['location']
308
309
    def run(self, location, revision=None, merge_type=None):
310
        from bzrlib.branch import Branch
311
        from bzrlib.workingtree import WorkingTree
0.436.64 by Jelmer Vernooij
Support revision ranges to replay.
312
        from bzrlib import ui
0.436.63 by Jelmer Vernooij
Fix replay command, add test.
313
        from rebase import regenerate_default_revid, replay_delta_workingtree
0.436.48 by Jelmer Vernooij
Add replay command.
314
0.436.65 by Jelmer Vernooij
Don't require running in the branch root.
315
        from_branch = Branch.open_containing(location)[0]
0.436.48 by Jelmer Vernooij
Add replay command.
316
317
        if revision is not None:
318
            if len(revision) == 1:
319
                if revision[0] is not None:
0.436.64 by Jelmer Vernooij
Support revision ranges to replay.
320
                    todo = [revision[0].in_history(from_branch).rev_id]
321
            elif len(revision) == 2:
322
                from_revno, from_revid = revision[0].in_history(from_branch)
323
                to_revno, to_revid = revision[1].in_history(from_branch)
324
                if to_revid is None:
325
                    to_revno = from_branch.revno()
326
                todo = []
327
                for revno in range(from_revno, to_revno + 1):
328
                    todo.append(from_branch.get_rev_id(revno))
329
            else:
330
                raise BzrCommandError(
331
                    "--revision takes only one or two arguments")
0.436.48 by Jelmer Vernooij
Add replay command.
332
        else:
333
            raise BzrCommandError("--revision is mandatory")
334
335
        wt = WorkingTree.open(".")
336
        wt.lock_write()
0.436.64 by Jelmer Vernooij
Support revision ranges to replay.
337
        pb = ui.ui_factory.nested_progress_bar()
0.436.48 by Jelmer Vernooij
Add replay command.
338
        try:
0.436.64 by Jelmer Vernooij
Support revision ranges to replay.
339
            for revid in todo:
340
                pb.update("replaying commits", todo.index(revid), len(todo))
341
                wt.branch.repository.fetch(from_branch.repository, revid)
342
                newrevid = regenerate_default_revid(wt.branch.repository, revid)
343
                replay_delta_workingtree(wt, revid, newrevid, 
344
                                         [wt.last_revision()], 
345
                                         merge_type=merge_type)
0.436.48 by Jelmer Vernooij
Add replay command.
346
        finally:
0.436.64 by Jelmer Vernooij
Support revision ranges to replay.
347
            pb.finished()
0.436.48 by Jelmer Vernooij
Add replay command.
348
            wt.unlock()
349
350
351
for cmd in [cmd_replay, cmd_rebase, cmd_rebase_abort, cmd_rebase_continue, 
352
            cmd_rebase_todo]:
353
    register_command(cmd)
354
0.436.4 by Jelmer Vernooij
Add some tests.
355
0.436.2 by Jelmer Vernooij
Add stubs for testsuite, rebase-continue and rebase-abort commands.
356
def test_suite():
357
    from unittest import TestSuite
358
    from bzrlib.tests import TestUtil
359
360
    loader = TestUtil.TestLoader()
361
    suite = TestSuite()
0.436.19 by Jelmer Vernooij
- Add blackbox tests
362
    testmod_names = ['test_blackbox', 'test_rebase', 'test_maptree']
0.436.16 by Jelmer Vernooij
Some more work on maptree.
363
    suite.addTest(loader.loadTestsFromModuleNames(
364
                              ["%s.%s" % (__name__, i) for i in testmod_names]))
0.436.2 by Jelmer Vernooij
Add stubs for testsuite, rebase-continue and rebase-abort commands.
365
366
    return suite
0.436.1 by Jelmer Vernooij
Add framework for git-rebase plugin.
367