~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

Late bind to PatienceSequenceMatcher to allow plugin to override.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Copyright (C) 2004, 2005, 2006 by 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
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
7
 
#
 
7
 
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
17
"""builtin bzr commands"""
18
18
 
19
19
 
20
 
import codecs
21
20
import errno
22
21
import os
23
 
import os.path
24
22
import sys
25
23
 
26
24
import bzrlib
27
 
from bzrlib import (
28
 
    branch,
29
 
    bundle,
30
 
    bzrdir,
31
 
    config,
32
 
    errors,
33
 
    ignores,
34
 
    log,
35
 
    osutils,
36
 
    repository,
37
 
    transport,
38
 
    ui,
39
 
    urlutils,
40
 
    )
41
 
from bzrlib.branch import Branch, BranchReferenceFormat
42
 
from bzrlib.bundle import read_bundle_from_url
43
 
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
44
 
from bzrlib.conflicts import ConflictList
 
25
import bzrlib.branch
 
26
from bzrlib.branch import Branch
 
27
import bzrlib.bzrdir as bzrdir
45
28
from bzrlib.commands import Command, display_command
 
29
import bzrlib.errors as errors
46
30
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError, 
47
31
                           NotBranchError, DivergedBranches, NotConflicted,
48
32
                           NoSuchFile, NoWorkingTree, FileInWrongBranch,
49
 
                           NotVersionedError, NotABundle)
 
33
                           NotVersionedError)
 
34
from bzrlib.log import show_one_log
50
35
from bzrlib.merge import Merge3Merger
51
36
from bzrlib.option import Option
52
37
from bzrlib.progress import DummyProgress, ProgressPhase
53
38
from bzrlib.revision import common_ancestor
54
39
from bzrlib.revisionspec import RevisionSpec
55
 
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
 
40
import bzrlib.trace
 
41
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
56
42
from bzrlib.transport.local import LocalTransport
 
43
import bzrlib.ui
57
44
from bzrlib.workingtree import WorkingTree
58
45
 
59
46
 
101
88
        return bzrdir.BzrDirMetaFormat1()
102
89
    if typestring == "metaweave":
103
90
        format = bzrdir.BzrDirMetaFormat1()
104
 
        format.repository_format = repository.RepositoryFormat7()
 
91
        format.repository_format = bzrlib.repository.RepositoryFormat7()
105
92
        return format
106
93
    if typestring == "knit":
107
94
        format = bzrdir.BzrDirMetaFormat1()
108
 
        format.repository_format = repository.RepositoryFormatKnit1()
 
95
        format.repository_format = bzrlib.repository.RepositoryFormatKnit1()
109
96
        return format
110
97
    msg = "Unknown bzr format %s. Current formats are: default, knit,\n" \
111
98
          "metaweave and weave" % typestring
139
126
    modified
140
127
        Text has changed since the previous revision.
141
128
 
 
129
    unchanged
 
130
        Nothing about this file has changed since the previous revision.
 
131
        Only shown with --all.
 
132
 
142
133
    unknown
143
134
        Not versioned and not matching an ignore pattern.
144
135
 
157
148
    # TODO: --no-recurse, --recurse options
158
149
    
159
150
    takes_args = ['file*']
160
 
    takes_options = ['show-ids', 'revision']
 
151
    takes_options = ['all', 'show-ids', 'revision']
161
152
    aliases = ['st', 'stat']
162
 
 
163
 
    encoding_type = 'replace'
164
153
    
165
154
    @display_command
166
 
    def run(self, show_ids=False, file_list=None, revision=None):
 
155
    def run(self, all=False, show_ids=False, file_list=None, revision=None):
 
156
        tree, file_list = tree_files(file_list)
 
157
            
167
158
        from bzrlib.status import show_tree_status
168
 
 
169
 
        tree, file_list = tree_files(file_list)
170
 
            
171
 
        show_tree_status(tree, show_ids=show_ids,
172
 
                         specific_files=file_list, revision=revision,
173
 
                         to_file=self.outf)
 
159
        show_tree_status(tree, show_unchanged=all, show_ids=show_ids,
 
160
                         specific_files=file_list, revision=revision)
174
161
 
175
162
 
176
163
class cmd_cat_revision(Command):
183
170
    hidden = True
184
171
    takes_args = ['revision_id?']
185
172
    takes_options = ['revision']
186
 
    # cat-revision is more for frontends so should be exact
187
 
    encoding = 'strict'
188
173
    
189
174
    @display_command
190
175
    def run(self, revision_id=None, revision=None):
194
179
        if revision_id is None and revision is None:
195
180
            raise BzrCommandError('You must supply either --revision or a revision_id')
196
181
        b = WorkingTree.open_containing(u'.')[0].branch
197
 
 
198
 
        # TODO: jam 20060112 should cat-revision always output utf-8?
199
182
        if revision_id is not None:
200
 
            self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
 
183
            sys.stdout.write(b.repository.get_revision_xml(revision_id))
201
184
        elif revision is not None:
202
185
            for rev in revision:
203
186
                if rev is None:
204
187
                    raise BzrCommandError('You cannot specify a NULL revision.')
205
188
                revno, rev_id = rev.in_history(b)
206
 
                self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
 
189
                sys.stdout.write(b.repository.get_revision_xml(rev_id))
207
190
    
208
191
 
209
192
class cmd_revno(Command):
210
193
    """Show current revision number.
211
194
 
212
 
    This is equal to the number of revisions on this branch.
213
 
    """
214
 
 
 
195
    This is equal to the number of revisions on this branch."""
215
196
    takes_args = ['location?']
216
 
 
217
197
    @display_command
218
198
    def run(self, location=u'.'):
219
 
        self.outf.write(str(Branch.open_containing(location)[0].revno()))
220
 
        self.outf.write('\n')
 
199
        print Branch.open_containing(location)[0].revno()
221
200
 
222
201
 
223
202
class cmd_revision_info(Command):
226
205
    hidden = True
227
206
    takes_args = ['revision_info*']
228
207
    takes_options = ['revision']
229
 
 
230
208
    @display_command
231
209
    def run(self, revision=None, revision_info_list=[]):
232
210
 
269
247
 
270
248
    Adding a file whose parent directory is not versioned will
271
249
    implicitly add the parent, and so on up to the root. This means
272
 
    you should never need to explicitly add a directory, they'll just
 
250
    you should never need to explictly add a directory, they'll just
273
251
    get added when you add a file in the directory.
274
252
 
275
253
    --dry-run will show which files would be added, but not actually 
277
255
    """
278
256
    takes_args = ['file*']
279
257
    takes_options = ['no-recurse', 'dry-run', 'verbose']
280
 
    encoding_type = 'replace'
281
258
 
282
259
    def run(self, file_list, no_recurse=False, dry_run=False, verbose=False):
283
260
        import bzrlib.add
284
261
 
285
 
        action = bzrlib.add.AddAction(to_file=self.outf,
286
 
            should_print=(not is_quiet()))
 
262
        if dry_run:
 
263
            if is_quiet():
 
264
                # This is pointless, but I'd rather not raise an error
 
265
                action = bzrlib.add.add_action_null
 
266
            else:
 
267
                action = bzrlib.add.add_action_print
 
268
        elif is_quiet():
 
269
            action = bzrlib.add.add_action_add
 
270
        else:
 
271
            action = bzrlib.add.add_action_add_and_print
287
272
 
288
273
        added, ignored = bzrlib.add.smart_add(file_list, not no_recurse, 
289
 
                                              action=action, save=not dry_run)
 
274
                                              action)
290
275
        if len(ignored) > 0:
291
276
            if verbose:
292
277
                for glob in sorted(ignored.keys()):
293
278
                    for path in ignored[glob]:
294
 
                        self.outf.write("ignored %s matching \"%s\"\n" 
295
 
                                        % (path, glob))
 
279
                        print "ignored %s matching \"%s\"" % (path, glob)
296
280
            else:
297
281
                match_len = 0
298
282
                for glob, paths in ignored.items():
299
283
                    match_len += len(paths)
300
 
                self.outf.write("ignored %d file(s).\n" % match_len)
301
 
            self.outf.write("If you wish to add some of these files,"
302
 
                            " please add them by name.\n")
 
284
                print "ignored %d file(s)." % match_len
 
285
            print "If you wish to add some of these files, please add them"\
 
286
                " by name."
303
287
 
304
288
 
305
289
class cmd_mkdir(Command):
307
291
 
308
292
    This is equivalent to creating the directory and then adding it.
309
293
    """
310
 
 
311
294
    takes_args = ['dir+']
312
 
    encoding_type = 'replace'
313
295
 
314
296
    def run(self, dir_list):
315
297
        for d in dir_list:
316
298
            os.mkdir(d)
317
299
            wt, dd = WorkingTree.open_containing(d)
318
300
            wt.add([dd])
319
 
            self.outf.write('added %s\n' % d)
 
301
            print 'added', d
320
302
 
321
303
 
322
304
class cmd_relpath(Command):
323
305
    """Show path of a file relative to root"""
324
 
 
325
306
    takes_args = ['filename']
326
307
    hidden = True
327
308
    
328
309
    @display_command
329
310
    def run(self, filename):
330
 
        # TODO: jam 20050106 Can relpath return a munged path if
331
 
        #       sys.stdout encoding cannot represent it?
332
311
        tree, relpath = WorkingTree.open_containing(filename)
333
 
        self.outf.write(relpath)
334
 
        self.outf.write('\n')
 
312
        print relpath
335
313
 
336
314
 
337
315
class cmd_inventory(Command):
340
318
    It is possible to limit the output to a particular entry
341
319
    type using the --kind option.  For example; --kind file.
342
320
    """
343
 
 
344
321
    takes_options = ['revision', 'show-ids', 'kind']
345
322
    
346
323
    @display_command
361
338
            if kind and kind != entry.kind:
362
339
                continue
363
340
            if show_ids:
364
 
                self.outf.write('%-50s %s\n' % (path, entry.file_id))
 
341
                print '%-50s %s' % (path, entry.file_id)
365
342
            else:
366
 
                self.outf.write(path)
367
 
                self.outf.write('\n')
 
343
                print path
368
344
 
369
345
 
370
346
class cmd_mv(Command):
380
356
 
381
357
    Files cannot be moved between branches.
382
358
    """
383
 
 
384
359
    takes_args = ['names*']
385
360
    aliases = ['move', 'rename']
386
 
    encoding_type = 'replace'
387
361
 
388
362
    def run(self, names_list):
389
 
        if names_list is None:
390
 
            names_list = []
391
 
 
392
363
        if len(names_list) < 2:
393
364
            raise BzrCommandError("missing file argument")
394
365
        tree, rel_names = tree_files(names_list)
396
367
        if os.path.isdir(names_list[-1]):
397
368
            # move into existing directory
398
369
            for pair in tree.move(rel_names[:-1], rel_names[-1]):
399
 
                self.outf.write("%s => %s\n" % pair)
 
370
                print "%s => %s" % pair
400
371
        else:
401
372
            if len(names_list) != 2:
402
373
                raise BzrCommandError('to mv multiple files the destination '
403
374
                                      'must be a versioned directory')
404
375
            tree.rename_one(rel_names[0], rel_names[1])
405
 
            self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
 
376
            print "%s => %s" % (rel_names[0], rel_names[1])
406
377
            
407
378
    
408
379
class cmd_pull(Command):
416
387
    from one into the other.  Once one branch has merged, the other should
417
388
    be able to pull it again.
418
389
 
 
390
    If branches have diverged, you can use 'bzr merge' to pull the text changes
 
391
    from one into the other.  Once one branch has merged, the other should
 
392
    be able to pull it again.
 
393
 
419
394
    If you want to forget your local changes and just update your branch to
420
395
    match the remote one, use pull --overwrite.
421
396
 
422
397
    If there is no default location set, the first pull will set it.  After
423
398
    that, you can omit the location to use the default.  To change the
424
 
    default, use --remember. The value will only be saved if the remote
425
 
    location can be accessed.
 
399
    default, use --remember.
426
400
    """
427
 
 
428
401
    takes_options = ['remember', 'overwrite', 'revision', 'verbose']
429
402
    takes_args = ['location?']
430
 
    encoding_type = 'replace'
431
403
 
432
404
    def run(self, location=None, remember=False, overwrite=False, revision=None, verbose=False):
433
405
        # FIXME: too much stuff is in the command class
436
408
            branch_to = tree_to.branch
437
409
        except NoWorkingTree:
438
410
            tree_to = None
439
 
            branch_to = Branch.open_containing(u'.')[0]
440
 
 
441
 
        reader = None
442
 
        if location is not None:
443
 
            try:
444
 
                reader = bundle.read_bundle_from_url(location)
445
 
            except NotABundle:
446
 
                pass # Continue on considering this url a Branch
447
 
 
 
411
            branch_to = Branch.open_containing(u'.')[0] 
448
412
        stored_loc = branch_to.get_parent()
449
413
        if location is None:
450
414
            if stored_loc is None:
451
415
                raise BzrCommandError("No pull location known or specified.")
452
416
            else:
453
 
                display_url = urlutils.unescape_for_display(stored_loc,
454
 
                        self.outf.encoding)
455
 
                self.outf.write("Using saved location: %s\n" % display_url)
 
417
                print "Using saved location: %s" % stored_loc
456
418
                location = stored_loc
457
419
 
458
 
 
459
 
        if reader is not None:
460
 
            install_bundle(branch_to.repository, reader)
461
 
            branch_from = branch_to
462
 
        else:
463
 
            branch_from = Branch.open(location)
464
 
 
465
 
            if branch_to.get_parent() is None or remember:
466
 
                branch_to.set_parent(branch_from.base)
467
 
 
468
 
        rev_id = None
 
420
        if branch_to.get_parent() is None or remember:
 
421
            branch_to.set_parent(location)
 
422
 
 
423
        branch_from = Branch.open(location)
 
424
 
469
425
        if revision is None:
470
 
            if reader is not None:
471
 
                rev_id = reader.target
 
426
            rev_id = None
472
427
        elif len(revision) == 1:
473
428
            rev_id = revision[0].in_history(branch_from).rev_id
474
429
        else:
486
441
            if old_rh != new_rh:
487
442
                # Something changed
488
443
                from bzrlib.log import show_changed_revisions
489
 
                show_changed_revisions(branch_to, old_rh, new_rh,
490
 
                                       to_file=self.outf)
 
444
                show_changed_revisions(branch_to, old_rh, new_rh)
491
445
 
492
446
 
493
447
class cmd_push(Command):
512
466
 
513
467
    If there is no default push location set, the first push will set it.
514
468
    After that, you can omit the location to use the default.  To change the
515
 
    default, use --remember. The value will only be saved if the remote
516
 
    location can be accessed.
 
469
    default, use --remember.
517
470
    """
518
 
 
519
 
    takes_options = ['remember', 'overwrite', 'verbose',
 
471
    takes_options = ['remember', 'overwrite', 
520
472
                     Option('create-prefix', 
521
473
                            help='Create the path leading up to the branch '
522
474
                                 'if it does not already exist')]
523
475
    takes_args = ['location?']
524
 
    encoding_type = 'replace'
525
476
 
526
477
    def run(self, location=None, remember=False, overwrite=False,
527
478
            create_prefix=False, verbose=False):
528
479
        # FIXME: Way too big!  Put this into a function called from the
529
480
        # command.
 
481
        from bzrlib.transport import get_transport
530
482
        
531
483
        br_from = Branch.open_containing('.')[0]
532
484
        stored_loc = br_from.get_push_location()
534
486
            if stored_loc is None:
535
487
                raise BzrCommandError("No push location known or specified.")
536
488
            else:
537
 
                display_url = urlutils.unescape_for_display(stored_loc,
538
 
                        self.outf.encoding)
539
 
                self.outf.write("Using saved location: %s\n" % display_url)
 
489
                print "Using saved location: %s" % stored_loc
540
490
                location = stored_loc
541
 
 
542
 
        to_transport = transport.get_transport(location)
543
 
        location_url = to_transport.base
544
 
 
545
 
        old_rh = []
 
491
        if br_from.get_push_location() is None or remember:
 
492
            br_from.set_push_location(location)
546
493
        try:
547
 
            dir_to = bzrdir.BzrDir.open(location_url)
 
494
            dir_to = bzrlib.bzrdir.BzrDir.open(location)
548
495
            br_to = dir_to.open_branch()
549
496
        except NotBranchError:
550
497
            # create a branch.
551
 
            to_transport = to_transport.clone('..')
 
498
            transport = get_transport(location).clone('..')
552
499
            if not create_prefix:
553
500
                try:
554
 
                    relurl = to_transport.relpath(location_url)
555
 
                    mutter('creating directory %s => %s', location_url, relurl)
556
 
                    to_transport.mkdir(relurl)
 
501
                    transport.mkdir(transport.relpath(location))
557
502
                except NoSuchFile:
558
503
                    raise BzrCommandError("Parent directory of %s "
559
504
                                          "does not exist." % location)
560
505
            else:
561
 
                current = to_transport.base
562
 
                needed = [(to_transport, to_transport.relpath(location_url))]
 
506
                current = transport.base
 
507
                needed = [(transport, transport.relpath(location))]
563
508
                while needed:
564
509
                    try:
565
 
                        to_transport, relpath = needed[-1]
566
 
                        to_transport.mkdir(relpath)
 
510
                        transport, relpath = needed[-1]
 
511
                        transport.mkdir(relpath)
567
512
                        needed.pop()
568
513
                    except NoSuchFile:
569
 
                        new_transport = to_transport.clone('..')
 
514
                        new_transport = transport.clone('..')
570
515
                        needed.append((new_transport,
571
 
                                       new_transport.relpath(to_transport.base)))
572
 
                        if new_transport.base == to_transport.base:
 
516
                                       new_transport.relpath(transport.base)))
 
517
                        if new_transport.base == transport.base:
573
518
                            raise BzrCommandError("Could not create "
574
519
                                                  "path prefix.")
575
 
            dir_to = br_from.bzrdir.clone(location_url,
 
520
            dir_to = br_from.bzrdir.clone(location,
576
521
                revision_id=br_from.last_revision())
577
522
            br_to = dir_to.open_branch()
578
523
            count = len(br_to.revision_history())
579
 
            # We successfully created the target, remember it
580
 
            if br_from.get_push_location() is None or remember:
581
 
                br_from.set_push_location(br_to.base)
582
524
        else:
583
 
            # We were able to connect to the remote location, so remember it
584
 
            # we don't need to successfully push because of possible divergence.
585
 
            if br_from.get_push_location() is None or remember:
586
 
                br_from.set_push_location(br_to.base)
587
525
            old_rh = br_to.revision_history()
588
526
            try:
589
527
                try:
606
544
            if old_rh != new_rh:
607
545
                # Something changed
608
546
                from bzrlib.log import show_changed_revisions
609
 
                show_changed_revisions(br_to, old_rh, new_rh,
610
 
                                       to_file=self.outf)
 
547
                show_changed_revisions(br_to, old_rh, new_rh)
611
548
 
612
549
 
613
550
class cmd_branch(Command):
628
565
    aliases = ['get', 'clone']
629
566
 
630
567
    def run(self, from_location, to_location=None, revision=None, basis=None):
 
568
        from bzrlib.osutils import rmtree
631
569
        if revision is None:
632
570
            revision = [None]
633
571
        elif len(revision) > 1:
659
597
                name = None
660
598
            else:
661
599
                name = os.path.basename(to_location) + '\n'
662
 
 
663
 
            to_transport = transport.get_transport(to_location)
664
600
            try:
665
 
                to_transport.mkdir('.')
666
 
            except errors.FileExists:
667
 
                raise BzrCommandError('Target directory "%s" already'
668
 
                                      ' exists.' % to_location)
669
 
            except errors.NoSuchFile:
670
 
                raise BzrCommandError('Parent of "%s" does not exist.' %
671
 
                                      to_location)
 
601
                os.mkdir(to_location)
 
602
            except OSError, e:
 
603
                if e.errno == errno.EEXIST:
 
604
                    raise BzrCommandError('Target directory "%s" already'
 
605
                                          ' exists.' % to_location)
 
606
                if e.errno == errno.ENOENT:
 
607
                    raise BzrCommandError('Parent of "%s" does not exist.' %
 
608
                                          to_location)
 
609
                else:
 
610
                    raise
672
611
            try:
673
612
                # preserve whatever source format we have.
674
 
                dir = br_from.bzrdir.sprout(to_transport.base,
675
 
                        revision_id, basis_dir)
 
613
                dir = br_from.bzrdir.sprout(to_location, revision_id, basis_dir)
676
614
                branch = dir.open_branch()
677
 
            except errors.NoSuchRevision:
678
 
                to_transport.delete_tree('.')
 
615
            except bzrlib.errors.NoSuchRevision:
 
616
                rmtree(to_location)
679
617
                msg = "The branch %s has no revision %s." % (from_location, revision[0])
680
618
                raise BzrCommandError(msg)
681
 
            except errors.UnlistableBranch:
682
 
                osutils.rmtree(to_location)
 
619
            except bzrlib.errors.UnlistableBranch:
 
620
                rmtree(to_location)
683
621
                msg = "The branch %s cannot be used as a --basis" % (basis,)
684
622
                raise BzrCommandError(msg)
685
623
            if name:
686
624
                branch.control_files.put_utf8('branch-name', name)
 
625
 
687
626
            note('Branched %d revision(s).' % branch.revno())
688
627
        finally:
689
628
            br_from.unlock()
719
658
                                 "such access, and also support local commits."
720
659
                            ),
721
660
                     ]
722
 
    aliases = ['co']
723
661
 
724
662
    def run(self, branch_location=None, to_location=None, revision=None, basis=None,
725
663
            lightweight=False):
729
667
            raise BzrCommandError(
730
668
                'bzr checkout --revision takes exactly 1 revision value')
731
669
        if branch_location is None:
732
 
            branch_location = osutils.getcwd()
 
670
            branch_location = bzrlib.osutils.getcwd()
733
671
            to_location = branch_location
734
672
        source = Branch.open(branch_location)
735
673
        if len(revision) == 1 and revision[0] is not None:
741
679
        # if the source and to_location are the same, 
742
680
        # and there is no working tree,
743
681
        # then reconstitute a branch
744
 
        if (osutils.abspath(to_location) == 
745
 
            osutils.abspath(branch_location)):
 
682
        if (bzrlib.osutils.abspath(to_location) == 
 
683
            bzrlib.osutils.abspath(branch_location)):
746
684
            try:
747
685
                source.bzrdir.open_workingtree()
748
686
            except errors.NoWorkingTree:
759
697
                                      to_location)
760
698
            else:
761
699
                raise
762
 
        old_format = bzrdir.BzrDirFormat.get_default_format()
763
 
        bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
 
700
        old_format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
 
701
        bzrlib.bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
764
702
        try:
765
703
            if lightweight:
766
704
                checkout = bzrdir.BzrDirMetaFormat1().initialize(to_location)
767
 
                branch.BranchReferenceFormat().initialize(checkout, source)
 
705
                bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
768
706
            else:
769
 
                checkout_branch =  bzrdir.BzrDir.create_branch_convenience(
 
707
                checkout_branch =  bzrlib.bzrdir.BzrDir.create_branch_convenience(
770
708
                    to_location, force_new_tree=False)
771
709
                checkout = checkout_branch.bzrdir
772
710
                checkout_branch.bind(source)
775
713
                    checkout_branch.set_revision_history(rh[:rh.index(revision_id) + 1])
776
714
            checkout.create_workingtree(revision_id)
777
715
        finally:
778
 
            bzrdir.BzrDirFormat.set_default_format(old_format)
 
716
            bzrlib.bzrdir.BzrDirFormat.set_default_format(old_format)
779
717
 
780
718
 
781
719
class cmd_renames(Command):
788
726
 
789
727
    @display_command
790
728
    def run(self, dir=u'.'):
791
 
        from bzrlib.tree import find_renames
792
729
        tree = WorkingTree.open_containing(dir)[0]
793
730
        old_inv = tree.basis_tree().inventory
794
731
        new_inv = tree.read_working_inventory()
795
 
        renames = list(find_renames(old_inv, new_inv))
 
732
 
 
733
        renames = list(bzrlib.tree.find_renames(old_inv, new_inv))
796
734
        renames.sort()
797
735
        for old_name, new_name in renames:
798
 
            self.outf.write("%s => %s\n" % (old_name, new_name))
 
736
            print "%s => %s" % (old_name, new_name)        
799
737
 
800
738
 
801
739
class cmd_update(Command):
809
747
    'bzr revert' instead of 'bzr commit' after the update.
810
748
    """
811
749
    takes_args = ['dir?']
812
 
    aliases = ['up']
813
750
 
814
751
    def run(self, dir='.'):
815
752
        tree = WorkingTree.open_containing(dir)[0]
816
753
        tree.lock_write()
817
 
        existing_pending_merges = tree.pending_merges()
818
754
        try:
819
 
            last_rev = tree.last_revision() 
820
 
            if last_rev == tree.branch.last_revision():
 
755
            if tree.last_revision() == tree.branch.last_revision():
821
756
                # may be up to date, check master too.
822
757
                master = tree.branch.get_master_branch()
823
 
                if master is None or last_rev == master.last_revision():
824
 
                    revno = tree.branch.revision_id_to_revno(last_rev)
825
 
                    note("Tree is up to date at revision %d." % (revno,))
826
 
                    return 0
 
758
                if master is None or master.last_revision == tree.last_revision():
 
759
                    note("Tree is up to date.")
 
760
                    return
827
761
            conflicts = tree.update()
828
 
            revno = tree.branch.revision_id_to_revno(tree.last_revision())
829
 
            note('Updated to revision %d.' % (revno,))
830
 
            if tree.pending_merges() != existing_pending_merges:
831
 
                note('Your local commits will now show as pending merges with '
832
 
                     "'bzr status', and can be committed with 'bzr commit'.")
 
762
            note('Updated to revision %d.' %
 
763
                 (tree.branch.revision_id_to_revno(tree.last_revision()),))
833
764
            if conflicts != 0:
834
765
                return 1
835
766
            else:
862
793
 
863
794
    This makes bzr stop tracking changes to a versioned file.  It does
864
795
    not delete the working copy.
865
 
 
866
 
    You can specify one or more files, and/or --new.  If you specify --new,
867
 
    only 'added' files will be removed.  If you specify both, then new files
868
 
    in the specified directories will be removed.  If the directories are
869
 
    also new, they will also be removed.
870
796
    """
871
 
    takes_args = ['file*']
872
 
    takes_options = ['verbose', Option('new', help='remove newly-added files')]
 
797
    takes_args = ['file+']
 
798
    takes_options = ['verbose']
873
799
    aliases = ['rm']
874
 
    encoding_type = 'replace'
875
800
    
876
 
    def run(self, file_list, verbose=False, new=False):
 
801
    def run(self, file_list, verbose=False):
877
802
        tree, file_list = tree_files(file_list)
878
 
        if new is False:
879
 
            if file_list is None:
880
 
                raise BzrCommandError('Specify one or more files to remove, or'
881
 
                                      ' use --new.')
882
 
        else:
883
 
            added = tree.changes_from(tree.basis_tree(),
884
 
                specific_files=file_list).added
885
 
            file_list = sorted([f[0] for f in added], reverse=True)
886
 
            if len(file_list) == 0:
887
 
                raise BzrCommandError('No matching files.')
888
 
        tree.remove(file_list, verbose=verbose, to_file=self.outf)
 
803
        tree.remove(file_list, verbose=verbose)
889
804
 
890
805
 
891
806
class cmd_file_id(Command):
895
810
    same through all revisions where the file exists, even when it is
896
811
    moved or renamed.
897
812
    """
898
 
 
899
813
    hidden = True
900
814
    takes_args = ['filename']
901
 
 
902
815
    @display_command
903
816
    def run(self, filename):
904
817
        tree, relpath = WorkingTree.open_containing(filename)
906
819
        if i == None:
907
820
            raise BzrError("%r is not a versioned file" % filename)
908
821
        else:
909
 
            self.outf.write(i + '\n')
 
822
            print i
910
823
 
911
824
 
912
825
class cmd_file_path(Command):
913
826
    """Print path of file_ids to a file or directory.
914
827
 
915
828
    This prints one line for each directory down to the target,
916
 
    starting at the branch root.
917
 
    """
918
 
 
 
829
    starting at the branch root."""
919
830
    hidden = True
920
831
    takes_args = ['filename']
921
 
 
922
832
    @display_command
923
833
    def run(self, filename):
924
834
        tree, relpath = WorkingTree.open_containing(filename)
927
837
        if fid == None:
928
838
            raise BzrError("%r is not a versioned file" % filename)
929
839
        for fip in inv.get_idpath(fid):
930
 
            self.outf.write(fip + '\n')
 
840
            print fip
931
841
 
932
842
 
933
843
class cmd_reconcile(Command):
952
862
 
953
863
    def run(self, branch="."):
954
864
        from bzrlib.reconcile import reconcile
955
 
        dir = bzrdir.BzrDir.open(branch)
 
865
        dir = bzrlib.bzrdir.BzrDir.open(branch)
956
866
        reconcile(dir)
957
867
 
958
868
 
959
869
class cmd_revision_history(Command):
960
 
    """Display the list of revision ids on a branch."""
961
 
    takes_args = ['location?']
962
 
 
 
870
    """Display list of revision ids on this branch."""
963
871
    hidden = True
964
 
 
965
872
    @display_command
966
 
    def run(self, location="."):
967
 
        branch = Branch.open_containing(location)[0]
968
 
        for revid in branch.revision_history():
969
 
            self.outf.write(revid)
970
 
            self.outf.write('\n')
 
873
    def run(self):
 
874
        branch = WorkingTree.open_containing(u'.')[0].branch
 
875
        for patchid in branch.revision_history():
 
876
            print patchid
971
877
 
972
878
 
973
879
class cmd_ancestry(Command):
974
880
    """List all revisions merged into this branch."""
975
 
    takes_args = ['location?']
976
 
 
977
881
    hidden = True
978
 
 
979
882
    @display_command
980
 
    def run(self, location="."):
981
 
        try:
982
 
            wt = WorkingTree.open_containing(location)[0]
983
 
        except errors.NoWorkingTree:
984
 
            b = Branch.open(location)
985
 
            last_revision = b.last_revision()
986
 
        else:
987
 
            b = wt.branch
988
 
            last_revision = wt.last_revision()
989
 
 
990
 
        revision_ids = b.repository.get_ancestry(last_revision)
 
883
    def run(self):
 
884
        tree = WorkingTree.open_containing(u'.')[0]
 
885
        b = tree.branch
 
886
        # FIXME. should be tree.last_revision
 
887
        revision_ids = b.repository.get_ancestry(b.last_revision())
991
888
        assert revision_ids[0] == None
992
889
        revision_ids.pop(0)
993
890
        for revision_id in revision_ids:
994
 
            self.outf.write(revision_id + '\n')
 
891
            print revision_id
995
892
 
996
893
 
997
894
class cmd_init(Command):
1025
922
                            type=get_format_type),
1026
923
                     ]
1027
924
    def run(self, location=None, format=None):
 
925
        from bzrlib.branch import Branch
1028
926
        if format is None:
1029
927
            format = get_format_type('default')
1030
928
        if location is None:
1031
929
            location = u'.'
1032
 
 
1033
 
        to_transport = transport.get_transport(location)
1034
 
 
1035
 
        # The path has to exist to initialize a
1036
 
        # branch inside of it.
1037
 
        # Just using os.mkdir, since I don't
1038
 
        # believe that we want to create a bunch of
1039
 
        # locations if the user supplies an extended path
1040
 
        # TODO: create-prefix
1041
 
        try:
1042
 
            to_transport.mkdir('.')
1043
 
        except errors.FileExists:
1044
 
            pass
1045
 
                    
 
930
        else:
 
931
            # The path has to exist to initialize a
 
932
            # branch inside of it.
 
933
            # Just using os.mkdir, since I don't
 
934
            # believe that we want to create a bunch of
 
935
            # locations if the user supplies an extended path
 
936
            if not os.path.exists(location):
 
937
                os.mkdir(location)
1046
938
        try:
1047
939
            existing_bzrdir = bzrdir.BzrDir.open(location)
1048
940
        except NotBranchError:
1050
942
            bzrdir.BzrDir.create_branch_convenience(location, format=format)
1051
943
        else:
1052
944
            if existing_bzrdir.has_branch():
1053
 
                if (isinstance(to_transport, LocalTransport)
1054
 
                    and not existing_bzrdir.has_workingtree()):
1055
 
                        raise errors.BranchExistsWithoutWorkingTree(location)
1056
 
                raise errors.AlreadyBranchError(location)
 
945
                if existing_bzrdir.has_workingtree():
 
946
                    raise errors.AlreadyBranchError(location)
 
947
                else:
 
948
                    raise errors.BranchExistsWithoutWorkingTree(location)
1057
949
            else:
1058
950
                existing_bzrdir.create_branch()
1059
951
                existing_bzrdir.create_workingtree()
1085
977
                             ' a working tree')]
1086
978
    aliases = ["init-repo"]
1087
979
    def run(self, location, format=None, trees=False):
 
980
        from bzrlib.transport import get_transport
1088
981
        if format is None:
1089
982
            format = get_format_type('default')
1090
 
 
1091
 
        if location is None:
1092
 
            location = '.'
1093
 
 
1094
 
        to_transport = transport.get_transport(location)
1095
 
        try:
1096
 
            to_transport.mkdir('.')
1097
 
        except errors.FileExists:
1098
 
            pass
1099
 
 
1100
 
        newdir = format.initialize_on_transport(to_transport)
 
983
        transport = get_transport(location)
 
984
        if not transport.has('.'):
 
985
            transport.mkdir('')
 
986
        newdir = format.initialize_on_transport(transport)
1101
987
        repo = newdir.create_repository(shared=True)
1102
988
        repo.set_make_working_trees(trees)
1103
989
 
1104
990
 
1105
991
class cmd_diff(Command):
1106
 
    """Show differences in the working tree or between revisions.
 
992
    """Show differences in working tree.
1107
993
    
1108
994
    If files are listed, only the changes in those files are listed.
1109
995
    Otherwise, all changes for the tree are listed.
1113
999
 
1114
1000
    examples:
1115
1001
        bzr diff
1116
 
            Shows the difference in the working tree versus the last commit
1117
1002
        bzr diff -r1
1118
 
            Difference between the working tree and revision 1
1119
1003
        bzr diff -r1..2
1120
 
            Difference between revision 2 and revision 1
1121
1004
        bzr diff --diff-prefix old/:new/
1122
 
            Same as 'bzr diff' but prefix paths with old/ and new/
1123
1005
        bzr diff bzr.mine bzr.dev
1124
 
            Show the differences between the two working trees
1125
1006
        bzr diff foo.c
1126
 
            Show just the differences for 'foo.c'
1127
1007
    """
1128
1008
    # TODO: Option to use external diff command; could be GNU diff, wdiff,
1129
1009
    #       or a graphical diff.
1139
1019
    takes_args = ['file*']
1140
1020
    takes_options = ['revision', 'diff-options', 'prefix']
1141
1021
    aliases = ['di', 'dif']
1142
 
    encoding_type = 'exact'
1143
1022
 
1144
1023
    @display_command
1145
1024
    def run(self, revision=None, file_list=None, diff_options=None,
1173
1052
                # FIXME diff those two files. rbc 20051123
1174
1053
                raise BzrCommandError("Files are in different branches")
1175
1054
            file_list = None
1176
 
        except NotBranchError:
1177
 
            if (revision is not None and len(revision) == 2
1178
 
                and not revision[0].needs_branch()
1179
 
                and not revision[1].needs_branch()):
1180
 
                # If both revision specs include a branch, we can
1181
 
                # diff them without needing a local working tree
1182
 
                tree1, tree2 = None, None
1183
 
            else:
1184
 
                raise
1185
1055
        if revision is not None:
1186
1056
            if tree2 is not None:
1187
1057
                raise BzrCommandError("Can't specify -r with two branches")
1215
1085
    # directories with readdir, rather than stating each one.  Same
1216
1086
    # level of effort but possibly much less IO.  (Or possibly not,
1217
1087
    # if the directories are very large...)
1218
 
    takes_options = ['show-ids']
1219
 
 
1220
1088
    @display_command
1221
1089
    def run(self, show_ids=False):
1222
1090
        tree = WorkingTree.open_containing(u'.')[0]
1223
1091
        old = tree.basis_tree()
1224
1092
        for path, ie in old.inventory.iter_entries():
1225
1093
            if not tree.has_id(ie.file_id):
1226
 
                self.outf.write(path)
1227
1094
                if show_ids:
1228
 
                    self.outf.write(' ')
1229
 
                    self.outf.write(ie.file_id)
1230
 
                self.outf.write('\n')
 
1095
                    print '%-50s %s' % (path, ie.file_id)
 
1096
                else:
 
1097
                    print path
1231
1098
 
1232
1099
 
1233
1100
class cmd_modified(Command):
1235
1102
    hidden = True
1236
1103
    @display_command
1237
1104
    def run(self):
 
1105
        from bzrlib.delta import compare_trees
 
1106
 
1238
1107
        tree = WorkingTree.open_containing(u'.')[0]
1239
 
        td = tree.changes_from(tree.basis_tree())
 
1108
        td = compare_trees(tree.basis_tree(), tree)
 
1109
 
1240
1110
        for path, id, kind, text_modified, meta_modified in td.modified:
1241
 
            self.outf.write(path + '\n')
 
1111
            print path
 
1112
 
1242
1113
 
1243
1114
 
1244
1115
class cmd_added(Command):
1253
1124
            if file_id in basis_inv:
1254
1125
                continue
1255
1126
            path = inv.id2path(file_id)
1256
 
            if not os.access(osutils.abspath(path), os.F_OK):
 
1127
            if not os.access(bzrlib.osutils.abspath(path), os.F_OK):
1257
1128
                continue
1258
 
            self.outf.write(path + '\n')
1259
 
 
 
1129
            print path
 
1130
                
 
1131
        
1260
1132
 
1261
1133
class cmd_root(Command):
1262
1134
    """Show the tree root directory.
1268
1140
    def run(self, filename=None):
1269
1141
        """Print the branch root."""
1270
1142
        tree = WorkingTree.open_containing(filename)[0]
1271
 
        self.outf.write(tree.basedir + '\n')
 
1143
        print tree.basedir
1272
1144
 
1273
1145
 
1274
1146
class cmd_log(Command):
1302
1174
                            type=str),
1303
1175
                     'short',
1304
1176
                     ]
1305
 
    encoding_type = 'replace'
1306
 
 
1307
1177
    @display_command
1308
1178
    def run(self, location=None, timezone='original',
1309
1179
            verbose=False,
1316
1186
            short=False,
1317
1187
            line=False):
1318
1188
        from bzrlib.log import log_formatter, show_log
 
1189
        import codecs
1319
1190
        assert message is None or isinstance(message, basestring), \
1320
1191
            "invalid message argument %r" % message
1321
1192
        direction = (forward and 'forward') or 'reverse'
1367
1238
        if rev1 > rev2:
1368
1239
            (rev2, rev1) = (rev1, rev2)
1369
1240
 
 
1241
        mutter('encoding log as %r', bzrlib.user_encoding)
 
1242
 
 
1243
        # use 'replace' so that we don't abort if trying to write out
 
1244
        # in e.g. the default C locale.
 
1245
        outf = codecs.getwriter(bzrlib.user_encoding)(sys.stdout, errors='replace')
 
1246
 
1370
1247
        if (log_format == None):
1371
 
            default = b.get_config().log_format()
1372
 
            log_format = get_log_format(long=long, short=short, line=line, 
1373
 
                                        default=default)
 
1248
            default = bzrlib.config.BranchConfig(b).log_format()
 
1249
            log_format = get_log_format(long=long, short=short, line=line, default=default)
 
1250
 
1374
1251
        lf = log_formatter(log_format,
1375
1252
                           show_ids=show_ids,
1376
 
                           to_file=self.outf,
 
1253
                           to_file=outf,
1377
1254
                           show_timezone=timezone)
1378
1255
 
1379
1256
        show_log(b,
1400
1277
class cmd_touching_revisions(Command):
1401
1278
    """Return revision-ids which affected a particular file.
1402
1279
 
1403
 
    A more user-friendly interface is "bzr log FILE".
1404
 
    """
1405
 
 
 
1280
    A more user-friendly interface is "bzr log FILE"."""
1406
1281
    hidden = True
1407
1282
    takes_args = ["filename"]
1408
 
 
1409
1283
    @display_command
1410
1284
    def run(self, filename):
1411
1285
        tree, relpath = WorkingTree.open_containing(filename)
1412
1286
        b = tree.branch
1413
1287
        inv = tree.read_working_inventory()
1414
1288
        file_id = inv.path2id(relpath)
1415
 
        for revno, revision_id, what in log.find_touching_revisions(b, file_id):
1416
 
            self.outf.write("%6d %s\n" % (revno, what))
 
1289
        for revno, revision_id, what in bzrlib.log.find_touching_revisions(b, file_id):
 
1290
            print "%6d %s" % (revno, what)
1417
1291
 
1418
1292
 
1419
1293
class cmd_ls(Command):
1452
1326
        if revision is not None:
1453
1327
            tree = tree.branch.repository.revision_tree(
1454
1328
                revision[0].in_history(tree.branch).rev_id)
1455
 
 
1456
1329
        for fp, fc, kind, fid, entry in tree.list_files():
1457
1330
            if fp.startswith(relpath):
1458
1331
                fp = fp[len(relpath):]
1462
1335
                    continue
1463
1336
                if verbose:
1464
1337
                    kindch = entry.kind_character()
1465
 
                    self.outf.write('%-8s %s%s\n' % (fc, fp, kindch))
 
1338
                    print '%-8s %s%s' % (fc, fp, kindch)
1466
1339
                elif null:
1467
 
                    self.outf.write(fp + '\0')
1468
 
                    self.outf.flush()
 
1340
                    sys.stdout.write(fp)
 
1341
                    sys.stdout.write('\0')
 
1342
                    sys.stdout.flush()
1469
1343
                else:
1470
 
                    self.outf.write(fp + '\n')
 
1344
                    print fp
1471
1345
 
1472
1346
 
1473
1347
class cmd_unknowns(Command):
1474
1348
    """List unknown files."""
1475
1349
    @display_command
1476
1350
    def run(self):
 
1351
        from bzrlib.osutils import quotefn
1477
1352
        for f in WorkingTree.open_containing(u'.')[0].unknowns():
1478
 
            self.outf.write(osutils.quotefn(f) + '\n')
 
1353
            print quotefn(f)
1479
1354
 
1480
1355
 
1481
1356
class cmd_ignore(Command):
1497
1372
        bzr ignore '*.class'
1498
1373
    """
1499
1374
    # TODO: Complain if the filename is absolute
1500
 
    takes_args = ['name_pattern?']
1501
 
    takes_options = [
1502
 
                     Option('old-default-rules',
1503
 
                            help='Out the ignore rules bzr < 0.9 always used.')
1504
 
                     ]
 
1375
    takes_args = ['name_pattern']
1505
1376
    
1506
 
    def run(self, name_pattern=None, old_default_rules=None):
 
1377
    def run(self, name_pattern):
1507
1378
        from bzrlib.atomicfile import AtomicFile
1508
 
        if old_default_rules is not None:
1509
 
            # dump the rules and exit
1510
 
            for pattern in ignores.OLD_DEFAULTS:
1511
 
                print pattern
1512
 
            return
1513
 
        if name_pattern is None:
1514
 
            raise BzrCommandError("ignore requires a NAME_PATTERN")
 
1379
        import os.path
 
1380
 
1515
1381
        tree, relpath = WorkingTree.open_containing(u'.')
1516
1382
        ifn = tree.abspath('.bzrignore')
 
1383
 
1517
1384
        if os.path.exists(ifn):
1518
1385
            f = open(ifn, 'rt')
1519
1386
            try:
1604
1471
    takes_args = ['dest']
1605
1472
    takes_options = ['revision', 'format', 'root']
1606
1473
    def run(self, dest, revision=None, format=None, root=None):
 
1474
        import os.path
1607
1475
        from bzrlib.export import export
1608
1476
        tree = WorkingTree.open_containing(u'.')[0]
1609
1477
        b = tree.branch
1652
1520
    hidden = True    
1653
1521
    @display_command
1654
1522
    def run(self):
1655
 
        print osutils.local_time_offset()
 
1523
        print bzrlib.osutils.local_time_offset()
1656
1524
 
1657
1525
 
1658
1526
 
1705
1573
        from bzrlib.msgeditor import edit_commit_message, \
1706
1574
                make_commit_message_template
1707
1575
        from tempfile import TemporaryFile
 
1576
        import codecs
1708
1577
 
1709
1578
        # TODO: Need a blackbox test for invoking the external editor; may be
1710
1579
        # slightly problematic to run this cross-platform.
1733
1602
            raise BzrCommandError("please specify either --message or --file")
1734
1603
        
1735
1604
        if file:
 
1605
            import codecs
1736
1606
            message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1737
1607
 
1738
1608
        if message == "":
1739
 
            raise BzrCommandError("empty commit message specified")
 
1609
                raise BzrCommandError("empty commit message specified")
1740
1610
        
1741
1611
        if verbose:
1742
1612
            reporter = ReportCommitToLog()
1750
1620
        except PointlessCommit:
1751
1621
            # FIXME: This should really happen before the file is read in;
1752
1622
            # perhaps prepare the commit; get the message; then actually commit
1753
 
            raise BzrCommandError("no changes to commit."
1754
 
                                  " use --unchanged to commit anyhow")
 
1623
            raise BzrCommandError("no changes to commit",
 
1624
                                  ["use --unchanged to commit anyhow"])
1755
1625
        except ConflictsInTree:
1756
1626
            raise BzrCommandError("Conflicts detected in working tree.  "
1757
1627
                'Use "bzr conflicts" to list, "bzr resolve FILE" to resolve.')
1759
1629
            raise BzrCommandError("Commit refused because there are unknown "
1760
1630
                                  "files in the working tree.")
1761
1631
        except errors.BoundBranchOutOfDate, e:
1762
 
            raise BzrCommandError(str(e) + "\n"
1763
 
                'To commit to master branch, run update and then commit.\n'
1764
 
                'You can also pass --local to commit to continue working '
1765
 
                'disconnected.')
 
1632
            raise BzrCommandError(str(e)
 
1633
                                  + ' Either unbind, update, or'
 
1634
                                    ' pass --local to commit.')
 
1635
 
1766
1636
 
1767
1637
class cmd_check(Command):
1768
1638
    """Validate consistency of branch history.
1828
1698
 
1829
1699
 
1830
1700
class cmd_whoami(Command):
1831
 
    """Show or set bzr user id.
1832
 
    
1833
 
    examples:
1834
 
        bzr whoami --email
1835
 
        bzr whoami 'Frank Chu <fchu@example.com>'
1836
 
    """
1837
 
    takes_options = [ Option('email',
1838
 
                             help='display email address only'),
1839
 
                      Option('branch',
1840
 
                             help='set identity for the current branch instead of '
1841
 
                                  'globally'),
1842
 
                    ]
1843
 
    takes_args = ['name?']
1844
 
    encoding_type = 'replace'
 
1701
    """Show bzr user id."""
 
1702
    takes_options = ['email']
1845
1703
    
1846
1704
    @display_command
1847
 
    def run(self, email=False, branch=False, name=None):
1848
 
        if name is None:
1849
 
            # use branch if we're inside one; otherwise global config
1850
 
            try:
1851
 
                c = Branch.open_containing('.')[0].get_config()
1852
 
            except NotBranchError:
1853
 
                c = config.GlobalConfig()
1854
 
            if email:
1855
 
                self.outf.write(c.user_email() + '\n')
1856
 
            else:
1857
 
                self.outf.write(c.username() + '\n')
1858
 
            return
1859
 
 
1860
 
        # display a warning if an email address isn't included in the given name.
 
1705
    def run(self, email=False):
1861
1706
        try:
1862
 
            config.extract_email_address(name)
1863
 
        except BzrError, e:
1864
 
            warning('"%s" does not seem to contain an email address.  '
1865
 
                    'This is allowed, but not recommended.', name)
 
1707
            b = WorkingTree.open_containing(u'.')[0].branch
 
1708
            config = bzrlib.config.BranchConfig(b)
 
1709
        except NotBranchError:
 
1710
            config = bzrlib.config.GlobalConfig()
1866
1711
        
1867
 
        # use global config unless --branch given
1868
 
        if branch:
1869
 
            c = Branch.open_containing('.')[0].get_config()
 
1712
        if email:
 
1713
            print config.user_email()
1870
1714
        else:
1871
 
            c = config.GlobalConfig()
1872
 
        c.set_user_option('email', name)
 
1715
            print config.username()
1873
1716
 
1874
1717
 
1875
1718
class cmd_nick(Command):
1955
1798
        # we don't want progress meters from the tests to go to the
1956
1799
        # real output; and we don't want log messages cluttering up
1957
1800
        # the real logs.
1958
 
        save_ui = ui.ui_factory
1959
 
        print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
 
1801
        save_ui = bzrlib.ui.ui_factory
 
1802
        print '%10s: %s' % ('bzr', bzrlib.osutils.realpath(sys.argv[0]))
1960
1803
        print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
1961
1804
        print
1962
 
        info('running tests...')
 
1805
        bzrlib.trace.info('running tests...')
1963
1806
        try:
1964
 
            ui.ui_factory = ui.SilentUIFactory()
 
1807
            bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
1965
1808
            if testspecs_list is not None:
1966
1809
                pattern = '|'.join(testspecs_list)
1967
1810
            else:
1982
1825
                              test_suite_factory=test_suite_factory,
1983
1826
                              lsprof_timed=lsprof_timed)
1984
1827
            if result:
1985
 
                info('tests passed')
 
1828
                bzrlib.trace.info('tests passed')
1986
1829
            else:
1987
 
                info('tests failed')
 
1830
                bzrlib.trace.info('tests failed')
1988
1831
            return int(not result)
1989
1832
        finally:
1990
 
            ui.ui_factory = save_ui
 
1833
            bzrlib.ui.ui_factory = save_ui
1991
1834
 
1992
1835
 
1993
1836
def _get_bzr_branch():
1994
1837
    """If bzr is run from a branch, return Branch or None"""
 
1838
    import bzrlib.errors
 
1839
    from bzrlib.branch import Branch
 
1840
    from bzrlib.osutils import abspath
1995
1841
    from os.path import dirname
1996
1842
    
1997
1843
    try:
1998
 
        branch = Branch.open(dirname(osutils.abspath(dirname(__file__))))
 
1844
        branch = Branch.open(dirname(abspath(dirname(__file__))))
1999
1845
        return branch
2000
 
    except errors.BzrError:
 
1846
    except bzrlib.errors.BzrError:
2001
1847
        return None
2002
1848
    
2003
1849
 
2004
1850
def show_version():
2005
 
    import bzrlib
2006
 
    print "Bazaar (bzr) %s" % bzrlib.__version__
 
1851
    print "bzr (bazaar-ng) %s" % bzrlib.__version__
2007
1852
    # is bzrlib itself in a branch?
2008
1853
    branch = _get_bzr_branch()
2009
1854
    if branch:
2013
1858
        print "  nick: %s" % (branch.nick,)
2014
1859
        if rh:
2015
1860
            print "  revid: %s" % (rh[-1],)
2016
 
    print "Using python interpreter:", sys.executable
2017
 
    import site
2018
 
    print "Using python standard library:", os.path.dirname(site.__file__)
2019
 
    print "Using bzrlib:",
2020
 
    if len(bzrlib.__path__) > 1:
2021
 
        # print repr, which is a good enough way of making it clear it's
2022
 
        # more than one element (eg ['/foo/bar', '/foo/bzr'])
2023
 
        print repr(bzrlib.__path__)
2024
 
    else:
2025
 
        print bzrlib.__path__[0]
2026
 
 
2027
 
    print
2028
1861
    print bzrlib.__copyright__
2029
1862
    print "http://bazaar-vcs.org/"
2030
1863
    print
2035
1868
 
2036
1869
class cmd_version(Command):
2037
1870
    """Show version of bzr."""
2038
 
 
2039
1871
    @display_command
2040
1872
    def run(self):
2041
1873
        show_version()
2042
1874
 
2043
 
 
2044
1875
class cmd_rocks(Command):
2045
1876
    """Statement of optimism."""
2046
 
 
2047
1877
    hidden = True
2048
 
 
2049
1878
    @display_command
2050
1879
    def run(self):
2051
1880
        print "it sure does!"
2052
1881
 
2053
1882
 
2054
1883
class cmd_find_merge_base(Command):
2055
 
    """Find and print a base revision for merging two branches."""
 
1884
    """Find and print a base revision for merging two branches.
 
1885
    """
2056
1886
    # TODO: Options to specify revisions on either side, as if
2057
1887
    #       merging only part of the history.
2058
1888
    takes_args = ['branch', 'other']
2077
1907
        base_rev_id = common_ancestor(last1, last2, source)
2078
1908
 
2079
1909
        print 'merge base is revision %s' % base_rev_id
 
1910
        
 
1911
        return
 
1912
 
 
1913
        if base_revno is None:
 
1914
            raise bzrlib.errors.UnrelatedBranches()
 
1915
 
 
1916
        print ' r%-6d in %s' % (base_revno, branch)
 
1917
 
 
1918
        other_revno = branch2.revision_id_to_revno(base_revid)
 
1919
        
 
1920
        print ' r%-6d in %s' % (other_revno, other)
 
1921
 
2080
1922
 
2081
1923
 
2082
1924
class cmd_merge(Command):
2083
1925
    """Perform a three-way merge.
2084
1926
    
2085
 
    The branch is the branch you will merge from.  By default, it will merge
2086
 
    the latest revision.  If you specify a revision, that revision will be
2087
 
    merged.  If you specify two revisions, the first will be used as a BASE,
2088
 
    and the second one as OTHER.  Revision numbers are always relative to the
2089
 
    specified branch.
 
1927
    The branch is the branch you will merge from.  By default, it will
 
1928
    merge the latest revision.  If you specify a revision, that
 
1929
    revision will be merged.  If you specify two revisions, the first
 
1930
    will be used as a BASE, and the second one as OTHER.  Revision
 
1931
    numbers are always relative to the specified branch.
2090
1932
 
2091
1933
    By default, bzr will try to merge in all new work from the other
2092
1934
    branch, automatically determining an appropriate base.  If this
2101
1943
 
2102
1944
    If there is no default branch set, the first merge will set it. After
2103
1945
    that, you can omit the branch to use the default.  To change the
2104
 
    default, use --remember. The value will only be saved if the remote
2105
 
    location can be accessed.
 
1946
    default, use --remember.
2106
1947
 
2107
1948
    Examples:
2108
1949
 
2123
1964
    takes_args = ['branch?']
2124
1965
    takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
2125
1966
                     Option('show-base', help="Show base revision text in "
2126
 
                            "conflicts"), 
2127
 
                     Option('uncommitted', help='Apply uncommitted changes'
2128
 
                            ' from a working copy, instead of branch changes')]
 
1967
                            "conflicts")]
2129
1968
 
2130
1969
    def help(self):
2131
1970
        from merge import merge_type_help
2133
1972
        return getdoc(self) + '\n' + merge_type_help() 
2134
1973
 
2135
1974
    def run(self, branch=None, revision=None, force=False, merge_type=None,
2136
 
            show_base=False, reprocess=False, remember=False, 
2137
 
            uncommitted=False):
 
1975
            show_base=False, reprocess=False, remember=False):
2138
1976
        if merge_type is None:
2139
1977
            merge_type = Merge3Merger
2140
1978
 
2141
1979
        tree = WorkingTree.open_containing(u'.')[0]
2142
 
 
2143
 
        if branch is not None:
2144
 
            try:
2145
 
                reader = bundle.read_bundle_from_url(branch)
2146
 
            except NotABundle:
2147
 
                pass # Continue on considering this url a Branch
 
1980
        stored_loc = tree.branch.get_parent()
 
1981
        if branch is None:
 
1982
            if stored_loc is None:
 
1983
                raise BzrCommandError("No merge branch known or specified.")
2148
1984
            else:
2149
 
                conflicts = merge_bundle(reader, tree, not force, merge_type,
2150
 
                                            reprocess, show_base)
2151
 
                if conflicts == 0:
2152
 
                    return 0
2153
 
                else:
2154
 
                    return 1
 
1985
                print "Using saved branch: %s" % stored_loc
 
1986
                branch = stored_loc
2155
1987
 
2156
 
        branch = self._get_remembered_parent(tree, branch, 'Merging from')
 
1988
        if tree.branch.get_parent() is None or remember:
 
1989
            tree.branch.set_parent(branch)
2157
1990
 
2158
1991
        if revision is None or len(revision) < 1:
2159
 
            if uncommitted:
2160
 
                base = [branch, -1]
2161
 
                other = [branch, None]
2162
 
            else:
2163
 
                base = [None, None]
2164
 
                other = [branch, -1]
 
1992
            base = [None, None]
 
1993
            other = [branch, -1]
2165
1994
            other_branch, path = Branch.open_containing(branch)
2166
1995
        else:
2167
 
            if uncommitted:
2168
 
                raise BzrCommandError('Cannot use --uncommitted and --revision'
2169
 
                                      ' at the same time.')
2170
1996
            if len(revision) == 1:
2171
1997
                base = [None, None]
2172
1998
                other_branch, path = Branch.open_containing(branch)
2177
2003
                if None in revision:
2178
2004
                    raise BzrCommandError(
2179
2005
                        "Merge doesn't permit that revision specifier.")
2180
 
                other_branch, path = Branch.open_containing(branch)
2181
 
 
2182
 
                base = [branch, revision[0].in_history(other_branch).revno]
2183
 
                other = [branch, revision[1].in_history(other_branch).revno]
2184
 
 
2185
 
        if tree.branch.get_parent() is None or remember:
2186
 
            tree.branch.set_parent(other_branch.base)
2187
 
 
 
2006
                b, path = Branch.open_containing(branch)
 
2007
 
 
2008
                base = [branch, revision[0].in_history(b).revno]
 
2009
                other = [branch, revision[1].in_history(b).revno]
2188
2010
        if path != "":
2189
2011
            interesting_files = [path]
2190
2012
        else:
2191
2013
            interesting_files = None
2192
 
        pb = ui.ui_factory.nested_progress_bar()
 
2014
        pb = bzrlib.ui.ui_factory.nested_progress_bar()
2193
2015
        try:
2194
2016
            try:
2195
2017
                conflict_count = merge(other, base, check_clean=(not force),
2196
 
                                       merge_type=merge_type,
 
2018
                                       merge_type=merge_type, 
2197
2019
                                       reprocess=reprocess,
2198
 
                                       show_base=show_base,
 
2020
                                       show_base=show_base, 
2199
2021
                                       pb=pb, file_list=interesting_files)
2200
2022
            finally:
2201
2023
                pb.finished()
2203
2025
                return 1
2204
2026
            else:
2205
2027
                return 0
2206
 
        except errors.AmbiguousBase, e:
 
2028
        except bzrlib.errors.AmbiguousBase, e:
2207
2029
            m = ("sorry, bzr can't determine the right merge base yet\n"
2208
2030
                 "candidates are:\n  "
2209
2031
                 + "\n  ".join(e.bases)
2212
2034
                 "and (if you want) report this to the bzr developers\n")
2213
2035
            log_error(m)
2214
2036
 
2215
 
    # TODO: move up to common parent; this isn't merge-specific anymore. 
2216
 
    def _get_remembered_parent(self, tree, supplied_location, verb_string):
2217
 
        """Use tree.branch's parent if none was supplied.
2218
 
 
2219
 
        Report if the remembered location was used.
2220
 
        """
2221
 
        if supplied_location is not None:
2222
 
            return supplied_location
2223
 
        stored_location = tree.branch.get_parent()
2224
 
        mutter("%s", stored_location)
2225
 
        if stored_location is None:
2226
 
            raise BzrCommandError("No location specified or remembered")
2227
 
        display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
2228
 
        self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
2229
 
        return stored_location
2230
 
 
2231
2037
 
2232
2038
class cmd_remerge(Command):
2233
2039
    """Redo a merge.
2271
2077
            pending_merges = tree.pending_merges() 
2272
2078
            if len(pending_merges) != 1:
2273
2079
                raise BzrCommandError("Sorry, remerge only works after normal"
2274
 
                                      " merges.  Not cherrypicking or"
2275
 
                                      " multi-merges.")
 
2080
                                      + " merges.  Not cherrypicking or"
 
2081
                                      + "multi-merges.")
2276
2082
            repository = tree.branch.repository
2277
2083
            base_revision = common_ancestor(tree.branch.last_revision(), 
2278
2084
                                            pending_merges[0], repository)
2279
2085
            base_tree = repository.revision_tree(base_revision)
2280
2086
            other_tree = repository.revision_tree(pending_merges[0])
2281
2087
            interesting_ids = None
2282
 
            new_conflicts = []
2283
 
            conflicts = tree.conflicts()
2284
2088
            if file_list is not None:
2285
2089
                interesting_ids = set()
2286
2090
                for filename in file_list:
2293
2097
                    
2294
2098
                    for name, ie in tree.inventory.iter_entries(file_id):
2295
2099
                        interesting_ids.add(ie.file_id)
2296
 
                new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
2297
2100
            transform_tree(tree, tree.basis_tree(), interesting_ids)
2298
 
            tree.set_conflicts(ConflictList(new_conflicts))
2299
2101
            if file_list is None:
2300
2102
                restore_files = list(tree.iter_conflicts())
2301
2103
            else:
2305
2107
                    restore(tree.abspath(filename))
2306
2108
                except NotConflicted:
2307
2109
                    pass
2308
 
            conflicts = merge_inner(tree.branch, other_tree, base_tree,
2309
 
                                    this_tree=tree,
2310
 
                                    interesting_ids=interesting_ids, 
2311
 
                                    other_rev_id=pending_merges[0], 
2312
 
                                    merge_type=merge_type, 
2313
 
                                    show_base=show_base,
2314
 
                                    reprocess=reprocess)
 
2110
            conflicts =  merge_inner(tree.branch, other_tree, base_tree,
 
2111
                                     this_tree=tree,
 
2112
                                     interesting_ids = interesting_ids, 
 
2113
                                     other_rev_id=pending_merges[0], 
 
2114
                                     merge_type=merge_type, 
 
2115
                                     show_base=show_base,
 
2116
                                     reprocess=reprocess)
2315
2117
        finally:
2316
2118
            tree.unlock()
2317
2119
        if conflicts > 0:
2346
2148
            raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
2347
2149
        else:
2348
2150
            rev_id = revision[0].in_history(tree.branch).rev_id
2349
 
        pb = ui.ui_factory.nested_progress_bar()
 
2151
        pb = bzrlib.ui.ui_factory.nested_progress_bar()
2350
2152
        try:
2351
2153
            tree.revert(file_list, 
2352
2154
                        tree.branch.repository.revision_tree(rev_id),
2400
2202
    takes_args = ['from_branch', 'to_branch']
2401
2203
    def run(self, from_branch, to_branch):
2402
2204
        from bzrlib.fetch import Fetcher
 
2205
        from bzrlib.branch import Branch
2403
2206
        from_b = Branch.open(from_branch)
2404
2207
        to_b = Branch.open(to_branch)
2405
2208
        Fetcher(to_b, from_b)
2422
2225
                     'show-ids',
2423
2226
                     'verbose'
2424
2227
                     ]
2425
 
    encoding_type = 'replace'
2426
2228
 
2427
 
    @display_command
2428
2229
    def run(self, other_branch=None, reverse=False, mine_only=False,
2429
2230
            theirs_only=False, log_format=None, long=False, short=False, line=False, 
2430
2231
            show_ids=False, verbose=False):
2431
2232
        from bzrlib.missing import find_unmerged, iter_log_data
2432
2233
        from bzrlib.log import log_formatter
2433
 
        local_branch = Branch.open_containing(u".")[0]
 
2234
        local_branch = bzrlib.branch.Branch.open_containing(u".")[0]
2434
2235
        parent = local_branch.get_parent()
2435
2236
        if other_branch is None:
2436
2237
            other_branch = parent
2437
2238
            if other_branch is None:
2438
 
                raise BzrCommandError("No peer location known or specified.")
 
2239
                raise BzrCommandError("No missing location known or specified.")
2439
2240
            print "Using last location: " + local_branch.get_parent()
2440
 
        remote_branch = Branch.open(other_branch)
 
2241
        remote_branch = bzrlib.branch.Branch.open(other_branch)
2441
2242
        if remote_branch.base == local_branch.base:
2442
2243
            remote_branch = local_branch
2443
2244
        local_branch.lock_read()
2446
2247
            try:
2447
2248
                local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
2448
2249
                if (log_format == None):
2449
 
                    default = local_branch.get_config().log_format()
2450
 
                    log_format = get_log_format(long=long, short=short, 
2451
 
                                                line=line, default=default)
2452
 
                lf = log_formatter(log_format,
2453
 
                                   to_file=self.outf,
 
2250
                    default = bzrlib.config.BranchConfig(local_branch).log_format()
 
2251
                    log_format = get_log_format(long=long, short=short, line=line, default=default)
 
2252
                lf = log_formatter(log_format, sys.stdout,
2454
2253
                                   show_ids=show_ids,
2455
2254
                                   show_timezone='original')
2456
2255
                if reverse is False:
2485
2284
            try:
2486
2285
                # handle race conditions - a parent might be set while we run.
2487
2286
                if local_branch.get_parent() is None:
2488
 
                    local_branch.set_parent(remote_branch.base)
 
2287
                    local_branch.set_parent(other_branch)
2489
2288
            finally:
2490
2289
                local_branch.unlock()
2491
2290
        return status_code
2513
2312
 
2514
2313
class cmd_testament(Command):
2515
2314
    """Show testament (signing-form) of a revision."""
2516
 
    takes_options = ['revision', 'long', 
2517
 
                     Option('strict', help='Produce a strict-format'
2518
 
                            ' testament')]
 
2315
    takes_options = ['revision', 'long']
2519
2316
    takes_args = ['branch?']
2520
2317
    @display_command
2521
 
    def run(self, branch=u'.', revision=None, long=False, strict=False):
2522
 
        from bzrlib.testament import Testament, StrictTestament
2523
 
        if strict is True:
2524
 
            testament_class = StrictTestament
2525
 
        else:
2526
 
            testament_class = Testament
 
2318
    def run(self, branch=u'.', revision=None, long=False):
 
2319
        from bzrlib.testament import Testament
2527
2320
        b = WorkingTree.open_containing(branch)[0].branch
2528
2321
        b.lock_read()
2529
2322
        try:
2531
2324
                rev_id = b.last_revision()
2532
2325
            else:
2533
2326
                rev_id = revision[0].in_history(b).rev_id
2534
 
            t = testament_class.from_revision(b.repository, rev_id)
 
2327
            t = Testament.from_revision(b.repository, rev_id)
2535
2328
            if long:
2536
2329
                sys.stdout.writelines(t.as_text_lines())
2537
2330
            else:
2552
2345
    # TODO: annotate directories; showing when each file was last changed
2553
2346
    # TODO: if the working copy is modified, show annotations on that 
2554
2347
    #       with new uncommitted lines marked
2555
 
    aliases = ['ann', 'blame', 'praise']
 
2348
    aliases = ['blame', 'praise']
2556
2349
    takes_args = ['filename']
2557
2350
    takes_options = [Option('all', help='show annotations on all lines'),
2558
2351
                     Option('long', help='show date in annotations'),
2589
2382
    takes_options = ['revision']
2590
2383
    
2591
2384
    def run(self, revision_id_list=None, revision=None):
 
2385
        import bzrlib.config as config
2592
2386
        import bzrlib.gpg as gpg
2593
2387
        if revision_id_list is not None and revision is not None:
2594
2388
            raise BzrCommandError('You can only supply one of revision_id or --revision')
2595
2389
        if revision_id_list is None and revision is None:
2596
2390
            raise BzrCommandError('You must supply either --revision or a revision_id')
2597
2391
        b = WorkingTree.open_containing(u'.')[0].branch
2598
 
        gpg_strategy = gpg.GPGStrategy(b.get_config())
 
2392
        gpg_strategy = gpg.GPGStrategy(config.BranchConfig(b))
2599
2393
        if revision_id_list is not None:
2600
2394
            for revision_id in revision_id_list:
2601
2395
                b.repository.sign_revision(revision_id, gpg_strategy)
2656
2450
            raise BzrCommandError('Local branch is not bound')
2657
2451
 
2658
2452
 
2659
 
class cmd_uncommit(Command):
 
2453
class cmd_uncommit(bzrlib.commands.Command):
2660
2454
    """Remove the last committed revision.
2661
2455
 
2662
2456
    --verbose will print out what is being removed.
2663
2457
    --dry-run will go through all the motions, but not actually
2664
2458
    remove anything.
2665
2459
    
2666
 
    In the future, uncommit will create a revision bundle, which can then
 
2460
    In the future, uncommit will create a changeset, which can then
2667
2461
    be re-applied.
2668
2462
    """
2669
2463
 
2670
2464
    # TODO: jam 20060108 Add an option to allow uncommit to remove
2671
 
    # unreferenced information in 'branch-as-repository' branches.
 
2465
    # unreferenced information in 'branch-as-repostory' branches.
2672
2466
    # TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
2673
2467
    # information in shared branches as well.
2674
2468
    takes_options = ['verbose', 'revision',
2677
2471
    takes_args = ['location?']
2678
2472
    aliases = []
2679
2473
 
2680
 
    def run(self, location=None,
 
2474
    def run(self, location=None, 
2681
2475
            dry_run=False, verbose=False,
2682
2476
            revision=None, force=False):
2683
 
        from bzrlib.log import log_formatter, show_log
 
2477
        from bzrlib.branch import Branch
 
2478
        from bzrlib.log import log_formatter
2684
2479
        import sys
2685
2480
        from bzrlib.uncommit import uncommit
2686
2481
 
2694
2489
            tree = None
2695
2490
            b = control.open_branch()
2696
2491
 
2697
 
        rev_id = None
2698
2492
        if revision is None:
2699
2493
            revno = b.revno()
 
2494
            rev_id = b.last_revision()
2700
2495
        else:
2701
 
            # 'bzr uncommit -r 10' actually means uncommit
2702
 
            # so that the final tree is at revno 10.
2703
 
            # but bzrlib.uncommit.uncommit() actually uncommits
2704
 
            # the revisions that are supplied.
2705
 
            # So we need to offset it by one
2706
 
            revno = revision[0].in_history(b).revno+1
2707
 
 
2708
 
        if revno <= b.revno():
2709
 
            rev_id = b.get_rev_id(revno)
 
2496
            revno, rev_id = revision[0].in_history(b)
2710
2497
        if rev_id is None:
2711
 
            self.outf.write('No revisions to uncommit.\n')
2712
 
            return 1
2713
 
 
2714
 
        lf = log_formatter('short',
2715
 
                           to_file=self.outf,
2716
 
                           show_timezone='original')
2717
 
 
2718
 
        show_log(b,
2719
 
                 lf,
2720
 
                 verbose=False,
2721
 
                 direction='forward',
2722
 
                 start_revision=revno,
2723
 
                 end_revision=b.revno())
 
2498
            print 'No revisions to uncommit.'
 
2499
 
 
2500
        for r in range(revno, b.revno()+1):
 
2501
            rev_id = b.get_rev_id(r)
 
2502
            lf = log_formatter('short', to_file=sys.stdout,show_timezone='original')
 
2503
            lf.show(r, b.repository.get_revision(rev_id), None)
2724
2504
 
2725
2505
        if dry_run:
2726
2506
            print 'Dry-run, pretending to remove the above revisions.'
2837
2617
# aliases.  ideally we would avoid loading the implementation until the
2838
2618
# details were needed.
2839
2619
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
2840
 
from bzrlib.bundle.commands import cmd_bundle_revisions
2841
2620
from bzrlib.sign_my_commits import cmd_sign_my_commits
2842
2621
from bzrlib.weave_commands import cmd_weave_list, cmd_weave_join, \
2843
2622
        cmd_weave_plan_merge, cmd_weave_merge_text