~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Robert Collins
  • Date: 2006-04-18 22:41:16 UTC
  • mto: (1711.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 1671.
  • Revision ID: robertc@robertcollins.net-20060418224116-9b723440fa56e404
 * 'Metadir' is now the default disk format. This improves behaviour in
   SFTP using circumstances and allows binding and rebinding and easier
   use of repositories. (Robert Collins, Aaron Bentley).

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
"""builtin bzr commands"""
18
18
 
19
19
 
20
 
import codecs
21
20
import errno
22
21
import os
23
 
import os.path
 
22
from shutil import rmtree
24
23
import sys
25
24
 
26
25
import bzrlib
27
 
from bzrlib.branch import Branch, BranchReferenceFormat
28
 
from bzrlib import (bundle, branch, bzrdir, errors, osutils, ui, config,
29
 
    repository, log)
30
 
from bzrlib.bundle import read_bundle_from_url
31
 
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
32
 
from bzrlib.conflicts import ConflictList
 
26
import bzrlib.branch
 
27
from bzrlib.branch import Branch
 
28
import bzrlib.bzrdir as bzrdir
33
29
from bzrlib.commands import Command, display_command
 
30
from bzrlib.revision import common_ancestor
 
31
import bzrlib.errors as errors
34
32
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError, 
35
33
                           NotBranchError, DivergedBranches, NotConflicted,
36
34
                           NoSuchFile, NoWorkingTree, FileInWrongBranch,
37
 
                           NotVersionedError, NotABundle)
 
35
                           NotVersionedError)
 
36
from bzrlib.log import show_one_log
38
37
from bzrlib.merge import Merge3Merger
39
38
from bzrlib.option import Option
40
39
from bzrlib.progress import DummyProgress, ProgressPhase
41
 
from bzrlib.revision import common_ancestor
42
40
from bzrlib.revisionspec import RevisionSpec
43
 
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
 
41
import bzrlib.trace
 
42
from bzrlib.trace import mutter, note, log_error, warning, is_quiet
44
43
from bzrlib.transport.local import LocalTransport
45
 
import bzrlib.urlutils as urlutils
 
44
import bzrlib.ui
46
45
from bzrlib.workingtree import WorkingTree
47
46
 
48
47
 
86
85
    """Parse and return a format specifier."""
87
86
    if typestring == "weave":
88
87
        return bzrdir.BzrDirFormat6()
89
 
    if typestring == "default":
 
88
    if typestring == "metadir":
90
89
        return bzrdir.BzrDirMetaFormat1()
91
 
    if typestring == "metaweave":
92
 
        format = bzrdir.BzrDirMetaFormat1()
93
 
        format.repository_format = repository.RepositoryFormat7()
94
 
        return format
95
90
    if typestring == "knit":
96
91
        format = bzrdir.BzrDirMetaFormat1()
97
 
        format.repository_format = repository.RepositoryFormatKnit1()
 
92
        format.repository_format = bzrlib.repository.RepositoryFormatKnit1()
98
93
        return format
99
 
    msg = "Unknown bzr format %s. Current formats are: default, knit,\n" \
100
 
          "metaweave and weave" % typestring
 
94
    msg = "No known bzr-dir format %s. Supported types are: weave, metadir\n" %\
 
95
        (typestring)
101
96
    raise BzrCommandError(msg)
102
97
 
103
98
 
128
123
    modified
129
124
        Text has changed since the previous revision.
130
125
 
 
126
    unchanged
 
127
        Nothing about this file has changed since the previous revision.
 
128
        Only shown with --all.
 
129
 
131
130
    unknown
132
131
        Not versioned and not matching an ignore pattern.
133
132
 
146
145
    # TODO: --no-recurse, --recurse options
147
146
    
148
147
    takes_args = ['file*']
149
 
    takes_options = ['show-ids', 'revision']
 
148
    takes_options = ['all', 'show-ids', 'revision']
150
149
    aliases = ['st', 'stat']
151
 
 
152
 
    encoding_type = 'replace'
153
150
    
154
151
    @display_command
155
 
    def run(self, show_ids=False, file_list=None, revision=None):
 
152
    def run(self, all=False, show_ids=False, file_list=None, revision=None):
 
153
        tree, file_list = tree_files(file_list)
 
154
            
156
155
        from bzrlib.status import show_tree_status
157
 
 
158
 
        tree, file_list = tree_files(file_list)
159
 
            
160
 
        show_tree_status(tree, show_ids=show_ids,
161
 
                         specific_files=file_list, revision=revision,
162
 
                         to_file=self.outf)
 
156
        show_tree_status(tree, show_unchanged=all, show_ids=show_ids,
 
157
                         specific_files=file_list, revision=revision)
163
158
 
164
159
 
165
160
class cmd_cat_revision(Command):
172
167
    hidden = True
173
168
    takes_args = ['revision_id?']
174
169
    takes_options = ['revision']
175
 
    # cat-revision is more for frontends so should be exact
176
 
    encoding = 'strict'
177
170
    
178
171
    @display_command
179
172
    def run(self, revision_id=None, revision=None):
183
176
        if revision_id is None and revision is None:
184
177
            raise BzrCommandError('You must supply either --revision or a revision_id')
185
178
        b = WorkingTree.open_containing(u'.')[0].branch
186
 
 
187
 
        # TODO: jam 20060112 should cat-revision always output utf-8?
188
179
        if revision_id is not None:
189
 
            self.outf.write(b.repository.get_revision_xml(revision_id).decode('utf-8'))
 
180
            sys.stdout.write(b.repository.get_revision_xml(revision_id))
190
181
        elif revision is not None:
191
182
            for rev in revision:
192
183
                if rev is None:
193
184
                    raise BzrCommandError('You cannot specify a NULL revision.')
194
185
                revno, rev_id = rev.in_history(b)
195
 
                self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
 
186
                sys.stdout.write(b.repository.get_revision_xml(rev_id))
196
187
    
197
188
 
198
189
class cmd_revno(Command):
199
190
    """Show current revision number.
200
191
 
201
 
    This is equal to the number of revisions on this branch.
202
 
    """
203
 
 
 
192
    This is equal to the number of revisions on this branch."""
204
193
    takes_args = ['location?']
205
 
 
206
194
    @display_command
207
195
    def run(self, location=u'.'):
208
 
        self.outf.write(str(Branch.open_containing(location)[0].revno()))
209
 
        self.outf.write('\n')
 
196
        print Branch.open_containing(location)[0].revno()
210
197
 
211
198
 
212
199
class cmd_revision_info(Command):
215
202
    hidden = True
216
203
    takes_args = ['revision_info*']
217
204
    takes_options = ['revision']
218
 
 
219
205
    @display_command
220
206
    def run(self, revision=None, revision_info_list=[]):
221
207
 
258
244
 
259
245
    Adding a file whose parent directory is not versioned will
260
246
    implicitly add the parent, and so on up to the root. This means
261
 
    you should never need to explicitly add a directory, they'll just
 
247
    you should never need to explictly add a directory, they'll just
262
248
    get added when you add a file in the directory.
263
249
 
264
250
    --dry-run will show which files would be added, but not actually 
266
252
    """
267
253
    takes_args = ['file*']
268
254
    takes_options = ['no-recurse', 'dry-run', 'verbose']
269
 
    encoding_type = 'replace'
270
255
 
271
256
    def run(self, file_list, no_recurse=False, dry_run=False, verbose=False):
272
257
        import bzrlib.add
273
258
 
274
 
        action = bzrlib.add.AddAction(to_file=self.outf,
275
 
            should_print=(not is_quiet()))
 
259
        if dry_run:
 
260
            if is_quiet():
 
261
                # This is pointless, but I'd rather not raise an error
 
262
                action = bzrlib.add.add_action_null
 
263
            else:
 
264
                action = bzrlib.add.add_action_print
 
265
        elif is_quiet():
 
266
            action = bzrlib.add.add_action_add
 
267
        else:
 
268
            action = bzrlib.add.add_action_add_and_print
276
269
 
277
270
        added, ignored = bzrlib.add.smart_add(file_list, not no_recurse, 
278
 
                                              action=action, save=not dry_run)
 
271
                                              action)
279
272
        if len(ignored) > 0:
280
 
            if verbose:
281
 
                for glob in sorted(ignored.keys()):
 
273
            for glob in sorted(ignored.keys()):
 
274
                match_len = len(ignored[glob])
 
275
                if verbose:
282
276
                    for path in ignored[glob]:
283
 
                        self.outf.write("ignored %s matching \"%s\"\n" 
284
 
                                        % (path, glob))
285
 
            else:
286
 
                match_len = 0
287
 
                for glob, paths in ignored.items():
288
 
                    match_len += len(paths)
289
 
                self.outf.write("ignored %d file(s).\n" % match_len)
290
 
            self.outf.write("If you wish to add some of these files,"
291
 
                            " please add them by name.\n")
 
277
                        print "ignored %s matching \"%s\"" % (path, glob)
 
278
                else:
 
279
                    print "ignored %d file(s) matching \"%s\"" % (match_len,
 
280
                                                              glob)
 
281
            print "If you wish to add some of these files, please add them"\
 
282
                " by name."
292
283
 
293
284
 
294
285
class cmd_mkdir(Command):
296
287
 
297
288
    This is equivalent to creating the directory and then adding it.
298
289
    """
299
 
 
300
290
    takes_args = ['dir+']
301
 
    encoding_type = 'replace'
302
291
 
303
292
    def run(self, dir_list):
304
293
        for d in dir_list:
305
294
            os.mkdir(d)
306
295
            wt, dd = WorkingTree.open_containing(d)
307
296
            wt.add([dd])
308
 
            self.outf.write('added %s\n' % d)
 
297
            print 'added', d
309
298
 
310
299
 
311
300
class cmd_relpath(Command):
312
301
    """Show path of a file relative to root"""
313
 
 
314
302
    takes_args = ['filename']
315
303
    hidden = True
316
304
    
317
305
    @display_command
318
306
    def run(self, filename):
319
 
        # TODO: jam 20050106 Can relpath return a munged path if
320
 
        #       sys.stdout encoding cannot represent it?
321
307
        tree, relpath = WorkingTree.open_containing(filename)
322
 
        self.outf.write(relpath)
323
 
        self.outf.write('\n')
 
308
        print relpath
324
309
 
325
310
 
326
311
class cmd_inventory(Command):
329
314
    It is possible to limit the output to a particular entry
330
315
    type using the --kind option.  For example; --kind file.
331
316
    """
332
 
 
333
317
    takes_options = ['revision', 'show-ids', 'kind']
334
318
    
335
319
    @display_command
350
334
            if kind and kind != entry.kind:
351
335
                continue
352
336
            if show_ids:
353
 
                self.outf.write('%-50s %s\n' % (path, entry.file_id))
 
337
                print '%-50s %s' % (path, entry.file_id)
354
338
            else:
355
 
                self.outf.write(path)
356
 
                self.outf.write('\n')
 
339
                print path
357
340
 
358
341
 
359
342
class cmd_mv(Command):
369
352
 
370
353
    Files cannot be moved between branches.
371
354
    """
372
 
 
373
355
    takes_args = ['names*']
374
356
    aliases = ['move', 'rename']
375
 
    encoding_type = 'replace'
376
357
 
377
358
    def run(self, names_list):
378
359
        if len(names_list) < 2:
382
363
        if os.path.isdir(names_list[-1]):
383
364
            # move into existing directory
384
365
            for pair in tree.move(rel_names[:-1], rel_names[-1]):
385
 
                self.outf.write("%s => %s\n" % pair)
 
366
                print "%s => %s" % pair
386
367
        else:
387
368
            if len(names_list) != 2:
388
369
                raise BzrCommandError('to mv multiple files the destination '
389
370
                                      'must be a versioned directory')
390
371
            tree.rename_one(rel_names[0], rel_names[1])
391
 
            self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
 
372
            print "%s => %s" % (rel_names[0], rel_names[1])
392
373
            
393
374
    
394
375
class cmd_pull(Command):
402
383
    from one into the other.  Once one branch has merged, the other should
403
384
    be able to pull it again.
404
385
 
 
386
    If branches have diverged, you can use 'bzr merge' to pull the text changes
 
387
    from one into the other.  Once one branch has merged, the other should
 
388
    be able to pull it again.
 
389
 
405
390
    If you want to forget your local changes and just update your branch to
406
391
    match the remote one, use pull --overwrite.
407
392
 
408
393
    If there is no default location set, the first pull will set it.  After
409
394
    that, you can omit the location to use the default.  To change the
410
 
    default, use --remember. The value will only be saved if the remote
411
 
    location can be accessed.
 
395
    default, use --remember.
412
396
    """
413
 
 
414
397
    takes_options = ['remember', 'overwrite', 'revision', 'verbose']
415
398
    takes_args = ['location?']
416
 
    encoding_type = 'replace'
417
399
 
418
400
    def run(self, location=None, remember=False, overwrite=False, revision=None, verbose=False):
419
401
        # FIXME: too much stuff is in the command class
422
404
            branch_to = tree_to.branch
423
405
        except NoWorkingTree:
424
406
            tree_to = None
425
 
            branch_to = Branch.open_containing(u'.')[0]
426
 
 
427
 
        reader = None
428
 
        if location is not None:
429
 
            try:
430
 
                reader = bundle.read_bundle_from_url(location)
431
 
            except NotABundle:
432
 
                pass # Continue on considering this url a Branch
433
 
 
 
407
            branch_to = Branch.open_containing(u'.')[0] 
434
408
        stored_loc = branch_to.get_parent()
435
409
        if location is None:
436
410
            if stored_loc is None:
437
411
                raise BzrCommandError("No pull location known or specified.")
438
412
            else:
439
 
                display_url = urlutils.unescape_for_display(stored_loc,
440
 
                        self.outf.encoding)
441
 
                self.outf.write("Using saved location: %s\n" % display_url)
 
413
                print "Using saved location: %s" % stored_loc
442
414
                location = stored_loc
443
415
 
444
 
 
445
 
        if reader is not None:
446
 
            install_bundle(branch_to.repository, reader)
447
 
            branch_from = branch_to
448
 
        else:
449
 
            branch_from = Branch.open(location)
450
 
 
451
 
            if branch_to.get_parent() is None or remember:
452
 
                branch_to.set_parent(branch_from.base)
453
 
 
454
 
        rev_id = None
 
416
        if branch_to.get_parent() is None or remember:
 
417
            branch_to.set_parent(location)
 
418
 
 
419
        branch_from = Branch.open(location)
 
420
 
455
421
        if revision is None:
456
 
            if reader is not None:
457
 
                rev_id = reader.target
 
422
            rev_id = None
458
423
        elif len(revision) == 1:
459
424
            rev_id = revision[0].in_history(branch_from).rev_id
460
425
        else:
472
437
            if old_rh != new_rh:
473
438
                # Something changed
474
439
                from bzrlib.log import show_changed_revisions
475
 
                show_changed_revisions(branch_to, old_rh, new_rh,
476
 
                                       to_file=self.outf)
 
440
                show_changed_revisions(branch_to, old_rh, new_rh)
477
441
 
478
442
 
479
443
class cmd_push(Command):
498
462
 
499
463
    If there is no default push location set, the first push will set it.
500
464
    After that, you can omit the location to use the default.  To change the
501
 
    default, use --remember. The value will only be saved if the remote
502
 
    location can be accessed.
 
465
    default, use --remember.
503
466
    """
504
 
 
505
 
    takes_options = ['remember', 'overwrite', 'verbose',
 
467
    takes_options = ['remember', 'overwrite', 
506
468
                     Option('create-prefix', 
507
469
                            help='Create the path leading up to the branch '
508
470
                                 'if it does not already exist')]
509
471
    takes_args = ['location?']
510
 
    encoding_type = 'replace'
511
472
 
512
473
    def run(self, location=None, remember=False, overwrite=False,
513
474
            create_prefix=False, verbose=False):
515
476
        # command.
516
477
        from bzrlib.transport import get_transport
517
478
        
518
 
        br_from = Branch.open_containing('.')[0]
519
 
        stored_loc = br_from.get_push_location()
 
479
        tree_from = WorkingTree.open_containing(u'.')[0]
 
480
        br_from = tree_from.branch
 
481
        stored_loc = tree_from.branch.get_push_location()
520
482
        if location is None:
521
483
            if stored_loc is None:
522
484
                raise BzrCommandError("No push location known or specified.")
523
485
            else:
524
 
                display_url = urlutils.unescape_for_display(stored_loc,
525
 
                        self.outf.encoding)
526
 
                self.outf.write("Using saved location: %s\n" % display_url)
 
486
                print "Using saved location: %s" % stored_loc
527
487
                location = stored_loc
528
 
 
529
 
        transport = get_transport(location)
530
 
        location_url = transport.base
531
 
 
532
 
        old_rh = []
 
488
        if br_from.get_push_location() is None or remember:
 
489
            br_from.set_push_location(location)
533
490
        try:
534
 
            dir_to = bzrdir.BzrDir.open(location_url)
 
491
            dir_to = bzrlib.bzrdir.BzrDir.open(location)
535
492
            br_to = dir_to.open_branch()
536
493
        except NotBranchError:
537
494
            # create a branch.
538
 
            transport = transport.clone('..')
 
495
            transport = get_transport(location).clone('..')
539
496
            if not create_prefix:
540
497
                try:
541
 
                    relurl = transport.relpath(location_url)
542
 
                    mutter('creating directory %s => %s', location_url, relurl)
543
 
                    transport.mkdir(relurl)
 
498
                    transport.mkdir(transport.relpath(location))
544
499
                except NoSuchFile:
545
500
                    raise BzrCommandError("Parent directory of %s "
546
501
                                          "does not exist." % location)
547
502
            else:
548
503
                current = transport.base
549
 
                needed = [(transport, transport.relpath(location_url))]
 
504
                needed = [(transport, transport.relpath(location))]
550
505
                while needed:
551
506
                    try:
552
507
                        transport, relpath = needed[-1]
559
514
                        if new_transport.base == transport.base:
560
515
                            raise BzrCommandError("Could not create "
561
516
                                                  "path prefix.")
562
 
            dir_to = br_from.bzrdir.clone(location_url,
563
 
                revision_id=br_from.last_revision())
 
517
            dir_to = br_from.bzrdir.clone(location)
564
518
            br_to = dir_to.open_branch()
565
 
            count = len(br_to.revision_history())
566
 
            # We successfully created the target, remember it
567
 
            if br_from.get_push_location() is None or remember:
568
 
                br_from.set_push_location(br_to.base)
569
 
        else:
570
 
            # We were able to connect to the remote location, so remember it
571
 
            # we don't need to successfully push because of possible divergence.
572
 
            if br_from.get_push_location() is None or remember:
573
 
                br_from.set_push_location(br_to.base)
574
 
            old_rh = br_to.revision_history()
 
519
        old_rh = br_to.revision_history()
 
520
        try:
575
521
            try:
576
 
                try:
577
 
                    tree_to = dir_to.open_workingtree()
578
 
                except errors.NotLocalUrl:
579
 
                    warning('This transport does not update the working '
580
 
                            'tree of: %s' % (br_to.base,))
581
 
                    count = br_to.pull(br_from, overwrite)
582
 
                except NoWorkingTree:
583
 
                    count = br_to.pull(br_from, overwrite)
584
 
                else:
585
 
                    count = tree_to.pull(br_from, overwrite)
586
 
            except DivergedBranches:
587
 
                raise BzrCommandError("These branches have diverged."
588
 
                                      "  Try a merge then push with overwrite.")
 
522
                tree_to = dir_to.open_workingtree()
 
523
            except errors.NotLocalUrl:
 
524
                # TODO: This should be updated for branches which don't have a
 
525
                # working tree, as opposed to ones where we just couldn't 
 
526
                # update the tree.
 
527
                warning('This transport does not update the working '
 
528
                        'tree of: %s' % (br_to.base,))
 
529
                count = br_to.pull(br_from, overwrite)
 
530
            except NoWorkingTree:
 
531
                count = br_to.pull(br_from, overwrite)
 
532
            else:
 
533
                count = tree_to.pull(br_from, overwrite)
 
534
        except DivergedBranches:
 
535
            raise BzrCommandError("These branches have diverged."
 
536
                                  "  Try a merge then push with overwrite.")
589
537
        note('%d revision(s) pushed.' % (count,))
590
538
 
591
539
        if verbose:
593
541
            if old_rh != new_rh:
594
542
                # Something changed
595
543
                from bzrlib.log import show_changed_revisions
596
 
                show_changed_revisions(br_to, old_rh, new_rh,
597
 
                                       to_file=self.outf)
 
544
                show_changed_revisions(br_to, old_rh, new_rh)
598
545
 
599
546
 
600
547
class cmd_branch(Command):
615
562
    aliases = ['get', 'clone']
616
563
 
617
564
    def run(self, from_location, to_location=None, revision=None, basis=None):
618
 
        from bzrlib.transport import get_transport
619
565
        if revision is None:
620
566
            revision = [None]
621
567
        elif len(revision) > 1:
647
593
                name = None
648
594
            else:
649
595
                name = os.path.basename(to_location) + '\n'
650
 
 
651
 
            to_transport = get_transport(to_location)
652
596
            try:
653
 
                to_transport.mkdir('.')
654
 
            except errors.FileExists:
655
 
                raise BzrCommandError('Target directory "%s" already'
656
 
                                      ' exists.' % to_location)
657
 
            except errors.NoSuchFile:
658
 
                raise BzrCommandError('Parent of "%s" does not exist.' %
659
 
                                      to_location)
 
597
                os.mkdir(to_location)
 
598
            except OSError, e:
 
599
                if e.errno == errno.EEXIST:
 
600
                    raise BzrCommandError('Target directory "%s" already'
 
601
                                          ' exists.' % to_location)
 
602
                if e.errno == errno.ENOENT:
 
603
                    raise BzrCommandError('Parent of "%s" does not exist.' %
 
604
                                          to_location)
 
605
                else:
 
606
                    raise
660
607
            try:
661
608
                # preserve whatever source format we have.
662
 
                dir = br_from.bzrdir.sprout(to_transport.base,
663
 
                        revision_id, basis_dir)
 
609
                dir = br_from.bzrdir.sprout(to_location, revision_id, basis_dir)
664
610
                branch = dir.open_branch()
665
 
            except errors.NoSuchRevision:
666
 
                to_transport.delete_tree('.')
 
611
            except bzrlib.errors.NoSuchRevision:
 
612
                rmtree(to_location)
667
613
                msg = "The branch %s has no revision %s." % (from_location, revision[0])
668
614
                raise BzrCommandError(msg)
669
 
            except errors.UnlistableBranch:
670
 
                osutils.rmtree(to_location)
 
615
            except bzrlib.errors.UnlistableBranch:
 
616
                rmtree(to_location)
671
617
                msg = "The branch %s cannot be used as a --basis" % (basis,)
672
618
                raise BzrCommandError(msg)
673
619
            if name:
674
620
                branch.control_files.put_utf8('branch-name', name)
 
621
 
675
622
            note('Branched %d revision(s).' % branch.revno())
676
623
        finally:
677
624
            br_from.unlock()
695
642
 
696
643
    --basis is to speed up checking out from remote branches.  When specified, it
697
644
    uses the inventory and file contents from the basis branch in preference to the
698
 
    branch being checked out.
 
645
    branch being checked out. [Not implemented yet.]
699
646
    """
700
647
    takes_args = ['branch_location?', 'to_location?']
701
648
    takes_options = ['revision', # , 'basis']
707
654
                                 "such access, and also support local commits."
708
655
                            ),
709
656
                     ]
710
 
    aliases = ['co']
711
657
 
712
658
    def run(self, branch_location=None, to_location=None, revision=None, basis=None,
713
659
            lightweight=False):
717
663
            raise BzrCommandError(
718
664
                'bzr checkout --revision takes exactly 1 revision value')
719
665
        if branch_location is None:
720
 
            branch_location = osutils.getcwd()
 
666
            branch_location = bzrlib.osutils.getcwd()
721
667
            to_location = branch_location
722
668
        source = Branch.open(branch_location)
723
669
        if len(revision) == 1 and revision[0] is not None:
729
675
        # if the source and to_location are the same, 
730
676
        # and there is no working tree,
731
677
        # then reconstitute a branch
732
 
        if (osutils.abspath(to_location) == 
733
 
            osutils.abspath(branch_location)):
 
678
        if (bzrlib.osutils.abspath(to_location) == 
 
679
            bzrlib.osutils.abspath(branch_location)):
734
680
            try:
735
681
                source.bzrdir.open_workingtree()
736
682
            except errors.NoWorkingTree:
747
693
                                      to_location)
748
694
            else:
749
695
                raise
750
 
        old_format = bzrdir.BzrDirFormat.get_default_format()
751
 
        bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
 
696
        old_format = bzrlib.bzrdir.BzrDirFormat.get_default_format()
 
697
        bzrlib.bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
752
698
        try:
753
699
            if lightweight:
754
700
                checkout = bzrdir.BzrDirMetaFormat1().initialize(to_location)
755
 
                branch.BranchReferenceFormat().initialize(checkout, source)
 
701
                bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
756
702
            else:
757
 
                checkout_branch =  bzrdir.BzrDir.create_branch_convenience(
 
703
                checkout_branch =  bzrlib.bzrdir.BzrDir.create_branch_convenience(
758
704
                    to_location, force_new_tree=False)
759
705
                checkout = checkout_branch.bzrdir
760
706
                checkout_branch.bind(source)
763
709
                    checkout_branch.set_revision_history(rh[:rh.index(revision_id) + 1])
764
710
            checkout.create_workingtree(revision_id)
765
711
        finally:
766
 
            bzrdir.BzrDirFormat.set_default_format(old_format)
 
712
            bzrlib.bzrdir.BzrDirFormat.set_default_format(old_format)
767
713
 
768
714
 
769
715
class cmd_renames(Command):
776
722
 
777
723
    @display_command
778
724
    def run(self, dir=u'.'):
779
 
        from bzrlib.tree import find_renames
780
725
        tree = WorkingTree.open_containing(dir)[0]
781
726
        old_inv = tree.basis_tree().inventory
782
727
        new_inv = tree.read_working_inventory()
783
 
        renames = list(find_renames(old_inv, new_inv))
 
728
 
 
729
        renames = list(bzrlib.tree.find_renames(old_inv, new_inv))
784
730
        renames.sort()
785
731
        for old_name, new_name in renames:
786
 
            self.outf.write("%s => %s\n" % (old_name, new_name))
 
732
            print "%s => %s" % (old_name, new_name)        
787
733
 
788
734
 
789
735
class cmd_update(Command):
802
748
        tree = WorkingTree.open_containing(dir)[0]
803
749
        tree.lock_write()
804
750
        try:
805
 
            last_rev = tree.last_revision() 
806
 
            if last_rev == tree.branch.last_revision():
 
751
            if tree.last_revision() == tree.branch.last_revision():
807
752
                # may be up to date, check master too.
808
753
                master = tree.branch.get_master_branch()
809
 
                if master is None or last_rev == master.last_revision():
810
 
                    revno = tree.branch.revision_id_to_revno(last_rev)
811
 
                    note("Tree is up to date at revision %d." % (revno,))
812
 
                    return 0
 
754
                if master is None or master.last_revision == tree.last_revision():
 
755
                    note("Tree is up to date.")
 
756
                    return
813
757
            conflicts = tree.update()
814
 
            revno = tree.branch.revision_id_to_revno(tree.last_revision())
815
 
            note('Updated to revision %d.' % (revno,))
 
758
            note('Updated to revision %d.' %
 
759
                 (tree.branch.revision_id_to_revno(tree.last_revision()),))
816
760
            if conflicts != 0:
817
761
                return 1
818
762
            else:
822
766
 
823
767
 
824
768
class cmd_info(Command):
825
 
    """Show information about a working tree, branch or repository.
826
 
 
827
 
    This command will show all known locations and formats associated to the
828
 
    tree, branch or repository.  Statistical information is included with
829
 
    each report.
830
 
 
831
 
    Branches and working trees will also report any missing revisions.
832
 
    """
833
 
    takes_args = ['location?']
 
769
    """Show statistical information about a branch."""
 
770
    takes_args = ['branch?']
834
771
    takes_options = ['verbose']
835
 
 
 
772
    
836
773
    @display_command
837
 
    def run(self, location=None, verbose=False):
838
 
        from bzrlib.info import show_bzrdir_info
839
 
        show_bzrdir_info(bzrdir.BzrDir.open_containing(location)[0],
840
 
                         verbose=verbose)
 
774
    def run(self, branch=None, verbose=False):
 
775
        import bzrlib.info
 
776
        bzrlib.info.show_bzrdir_info(bzrdir.BzrDir.open_containing(branch)[0],
 
777
                                     verbose=verbose)
841
778
 
842
779
 
843
780
class cmd_remove(Command):
845
782
 
846
783
    This makes bzr stop tracking changes to a versioned file.  It does
847
784
    not delete the working copy.
848
 
 
849
 
    You can specify one or more files, and/or --new.  If you specify --new,
850
 
    only 'added' files will be removed.  If you specify both, then new files
851
 
    in the specified directories will be removed.  If the directories are
852
 
    also new, they will also be removed.
853
785
    """
854
 
    takes_args = ['file*']
855
 
    takes_options = ['verbose', Option('new', help='remove newly-added files')]
 
786
    takes_args = ['file+']
 
787
    takes_options = ['verbose']
856
788
    aliases = ['rm']
857
 
    encoding_type = 'replace'
858
789
    
859
 
    def run(self, file_list, verbose=False, new=False):
 
790
    def run(self, file_list, verbose=False):
860
791
        tree, file_list = tree_files(file_list)
861
 
        if new is False:
862
 
            if file_list is None:
863
 
                raise BzrCommandError('Specify one or more files to remove, or'
864
 
                                      ' use --new.')
865
 
        else:
866
 
            from bzrlib.delta import compare_trees
867
 
            added = [compare_trees(tree.basis_tree(), tree,
868
 
                                   specific_files=file_list).added]
869
 
            file_list = sorted([f[0] for f in added[0]], reverse=True)
870
 
            if len(file_list) == 0:
871
 
                raise BzrCommandError('No matching files.')
872
 
        tree.remove(file_list, verbose=verbose, to_file=self.outf)
 
792
        tree.remove(file_list, verbose=verbose)
873
793
 
874
794
 
875
795
class cmd_file_id(Command):
879
799
    same through all revisions where the file exists, even when it is
880
800
    moved or renamed.
881
801
    """
882
 
 
883
802
    hidden = True
884
803
    takes_args = ['filename']
885
 
 
886
804
    @display_command
887
805
    def run(self, filename):
888
806
        tree, relpath = WorkingTree.open_containing(filename)
890
808
        if i == None:
891
809
            raise BzrError("%r is not a versioned file" % filename)
892
810
        else:
893
 
            self.outf.write(i + '\n')
 
811
            print i
894
812
 
895
813
 
896
814
class cmd_file_path(Command):
897
815
    """Print path of file_ids to a file or directory.
898
816
 
899
817
    This prints one line for each directory down to the target,
900
 
    starting at the branch root.
901
 
    """
902
 
 
 
818
    starting at the branch root."""
903
819
    hidden = True
904
820
    takes_args = ['filename']
905
 
 
906
821
    @display_command
907
822
    def run(self, filename):
908
823
        tree, relpath = WorkingTree.open_containing(filename)
911
826
        if fid == None:
912
827
            raise BzrError("%r is not a versioned file" % filename)
913
828
        for fip in inv.get_idpath(fid):
914
 
            self.outf.write(fip + '\n')
 
829
            print fip
915
830
 
916
831
 
917
832
class cmd_reconcile(Command):
936
851
 
937
852
    def run(self, branch="."):
938
853
        from bzrlib.reconcile import reconcile
939
 
        dir = bzrdir.BzrDir.open(branch)
 
854
        dir = bzrlib.bzrdir.BzrDir.open(branch)
940
855
        reconcile(dir)
941
856
 
942
857
 
943
858
class cmd_revision_history(Command):
944
 
    """Display the list of revision ids on a branch."""
945
 
    takes_args = ['location?']
946
 
 
 
859
    """Display list of revision ids on this branch."""
947
860
    hidden = True
948
 
 
949
861
    @display_command
950
 
    def run(self, location="."):
951
 
        branch = Branch.open_containing(location)[0]
952
 
        for revid in branch.revision_history():
953
 
            self.outf.write(revid)
954
 
            self.outf.write('\n')
 
862
    def run(self):
 
863
        branch = WorkingTree.open_containing(u'.')[0].branch
 
864
        for patchid in branch.revision_history():
 
865
            print patchid
955
866
 
956
867
 
957
868
class cmd_ancestry(Command):
958
869
    """List all revisions merged into this branch."""
959
 
    takes_args = ['location?']
960
 
 
961
870
    hidden = True
962
 
 
963
871
    @display_command
964
 
    def run(self, location="."):
965
 
        try:
966
 
            wt = WorkingTree.open_containing(location)[0]
967
 
        except errors.NoWorkingTree:
968
 
            b = Branch.open(location)
969
 
            last_revision = b.last_revision()
970
 
        else:
971
 
            b = wt.branch
972
 
            last_revision = wt.last_revision()
973
 
 
974
 
        revision_ids = b.repository.get_ancestry(last_revision)
975
 
        assert revision_ids[0] == None
976
 
        revision_ids.pop(0)
977
 
        for revision_id in revision_ids:
978
 
            self.outf.write(revision_id + '\n')
 
872
    def run(self):
 
873
        tree = WorkingTree.open_containing(u'.')[0]
 
874
        b = tree.branch
 
875
        # FIXME. should be tree.last_revision
 
876
        for revision_id in b.repository.get_ancestry(b.last_revision()):
 
877
            print revision_id
979
878
 
980
879
 
981
880
class cmd_init(Command):
984
883
    Use this to create an empty branch, or before importing an
985
884
    existing project.
986
885
 
987
 
    If there is a repository in a parent directory of the location, then 
988
 
    the history of the branch will be stored in the repository.  Otherwise
989
 
    init creates a standalone branch which carries its own history in 
990
 
    .bzr.
991
 
 
992
 
    If there is already a branch at the location but it has no working tree,
993
 
    the tree can be populated with 'bzr checkout'.
994
 
 
995
886
    Recipe for importing a tree of files:
996
887
        cd ~/project
997
888
        bzr init
1002
893
    takes_args = ['location?']
1003
894
    takes_options = [
1004
895
                     Option('format', 
1005
 
                            help='Specify a format for this branch. Current'
1006
 
                                 ' formats are: default, knit, metaweave and'
1007
 
                                 ' weave. Default is knit; metaweave and'
1008
 
                                 ' weave are deprecated',
 
896
                            help='Create a specific format rather than the'
 
897
                                 ' current default format. Currently this '
 
898
                                 ' option only accepts "metadir"',
1009
899
                            type=get_format_type),
1010
900
                     ]
1011
901
    def run(self, location=None, format=None):
1012
 
        if format is None:
1013
 
            format = get_format_type('default')
 
902
        from bzrlib.branch import Branch
1014
903
        if location is None:
1015
904
            location = u'.'
1016
905
        else:
1022
911
            if not os.path.exists(location):
1023
912
                os.mkdir(location)
1024
913
        try:
1025
 
            existing_bzrdir = bzrdir.BzrDir.open(location)
 
914
            existing = bzrdir.BzrDir.open(location)
1026
915
        except NotBranchError:
1027
 
            # really a NotBzrDir error...
1028
916
            bzrdir.BzrDir.create_branch_convenience(location, format=format)
1029
917
        else:
1030
 
            if existing_bzrdir.has_branch():
1031
 
                if existing_bzrdir.has_workingtree():
1032
 
                    raise errors.AlreadyBranchError(location)
1033
 
                else:
1034
 
                    raise errors.BranchExistsWithoutWorkingTree(location)
 
918
            try:
 
919
                existing.open_branch()
 
920
            except NotBranchError:
 
921
                existing.create_branch()
 
922
                existing.create_workingtree()
1035
923
            else:
1036
 
                existing_bzrdir.create_branch()
1037
 
                existing_bzrdir.create_workingtree()
 
924
                raise errors.AlreadyBranchError(location)
1038
925
 
1039
926
 
1040
927
class cmd_init_repository(Command):
1044
931
    in the repository, not in the branch directory, if the branch format supports
1045
932
    shared storage.
1046
933
 
1047
 
    example:
 
934
    example:    
1048
935
        bzr init-repo repo
1049
 
        bzr init repo/trunk
1050
 
        bzr checkout --lightweight repo/trunk trunk-checkout
1051
 
        cd trunk-checkout
 
936
        bzr init --format=metadir repo/trunk
 
937
        cd repo/trunk
1052
938
        (add files here)
1053
939
    """
1054
940
    takes_args = ["location"] 
1055
941
    takes_options = [Option('format', 
1056
 
                            help='Specify a format for this repository.'
1057
 
                                 ' Current formats are: default, knit,'
1058
 
                                 ' metaweave and weave. Default is knit;'
1059
 
                                 ' metaweave and weave are deprecated',
 
942
                            help='Use a specific format rather than the'
 
943
                            ' current default format. Currently this'
 
944
                            ' option only accepts "metadir" and "knit"'
 
945
                            ' WARNING: the knit format is currently unstable'
 
946
                            ' and only for experimental use.',
1060
947
                            type=get_format_type),
1061
948
                     Option('trees',
1062
949
                             help='Allows branches in repository to have'
1063
950
                             ' a working tree')]
1064
951
    aliases = ["init-repo"]
1065
952
    def run(self, location, format=None, trees=False):
 
953
        from bzrlib.bzrdir import BzrDirMetaFormat1
1066
954
        from bzrlib.transport import get_transport
1067
955
        if format is None:
1068
 
            format = get_format_type('default')
 
956
            format = BzrDirMetaFormat1()
1069
957
        transport = get_transport(location)
1070
958
        if not transport.has('.'):
1071
959
            transport.mkdir('')
1080
968
    If files are listed, only the changes in those files are listed.
1081
969
    Otherwise, all changes for the tree are listed.
1082
970
 
1083
 
    "bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
1084
 
    produces patches suitable for "patch -p1".
1085
 
 
1086
971
    examples:
1087
972
        bzr diff
1088
973
        bzr diff -r1
1089
974
        bzr diff -r1..2
1090
 
        bzr diff --diff-prefix old/:new/
1091
 
        bzr diff bzr.mine bzr.dev
1092
 
        bzr diff foo.c
1093
975
    """
 
976
    # TODO: Allow diff across branches.
1094
977
    # TODO: Option to use external diff command; could be GNU diff, wdiff,
1095
978
    #       or a graphical diff.
1096
979
 
1097
980
    # TODO: Python difflib is not exactly the same as unidiff; should
1098
981
    #       either fix it up or prefer to use an external diff.
1099
982
 
 
983
    # TODO: If a directory is given, diff everything under that.
 
984
 
1100
985
    # TODO: Selected-file diff is inefficient and doesn't show you
1101
986
    #       deleted files.
1102
987
 
1103
988
    # TODO: This probably handles non-Unix newlines poorly.
1104
989
    
1105
990
    takes_args = ['file*']
1106
 
    takes_options = ['revision', 'diff-options', 'prefix']
 
991
    takes_options = ['revision', 'diff-options']
1107
992
    aliases = ['di', 'dif']
1108
 
    encoding_type = 'exact'
1109
993
 
1110
994
    @display_command
1111
 
    def run(self, revision=None, file_list=None, diff_options=None,
1112
 
            prefix=None):
 
995
    def run(self, revision=None, file_list=None, diff_options=None):
1113
996
        from bzrlib.diff import diff_cmd_helper, show_diff_trees
1114
 
 
1115
 
        if (prefix is None) or (prefix == '0'):
1116
 
            # diff -p0 format
1117
 
            old_label = ''
1118
 
            new_label = ''
1119
 
        elif prefix == '1':
1120
 
            old_label = 'old/'
1121
 
            new_label = 'new/'
1122
 
        else:
1123
 
            if not ':' in prefix:
1124
 
                 raise BzrError("--diff-prefix expects two values separated by a colon")
1125
 
            old_label, new_label = prefix.split(":")
1126
 
        
1127
997
        try:
1128
998
            tree1, file_list = internal_tree_files(file_list)
1129
999
            tree2 = None
1144
1014
                raise BzrCommandError("Can't specify -r with two branches")
1145
1015
            if (len(revision) == 1) or (revision[1].spec is None):
1146
1016
                return diff_cmd_helper(tree1, file_list, diff_options,
1147
 
                                       revision[0], 
1148
 
                                       old_label=old_label, new_label=new_label)
 
1017
                                       revision[0])
1149
1018
            elif len(revision) == 2:
1150
1019
                return diff_cmd_helper(tree1, file_list, diff_options,
1151
 
                                       revision[0], revision[1],
1152
 
                                       old_label=old_label, new_label=new_label)
 
1020
                                       revision[0], revision[1])
1153
1021
            else:
1154
1022
                raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
1155
1023
        else:
1156
1024
            if tree2 is not None:
1157
1025
                return show_diff_trees(tree1, tree2, sys.stdout, 
1158
1026
                                       specific_files=file_list,
1159
 
                                       external_diff_options=diff_options,
1160
 
                                       old_label=old_label, new_label=new_label)
 
1027
                                       external_diff_options=diff_options)
1161
1028
            else:
1162
 
                return diff_cmd_helper(tree1, file_list, diff_options,
1163
 
                                       old_label=old_label, new_label=new_label)
 
1029
                return diff_cmd_helper(tree1, file_list, diff_options)
1164
1030
 
1165
1031
 
1166
1032
class cmd_deleted(Command):
1172
1038
    # directories with readdir, rather than stating each one.  Same
1173
1039
    # level of effort but possibly much less IO.  (Or possibly not,
1174
1040
    # if the directories are very large...)
1175
 
    takes_options = ['show-ids']
1176
 
 
1177
1041
    @display_command
1178
1042
    def run(self, show_ids=False):
1179
1043
        tree = WorkingTree.open_containing(u'.')[0]
1180
1044
        old = tree.basis_tree()
1181
1045
        for path, ie in old.inventory.iter_entries():
1182
1046
            if not tree.has_id(ie.file_id):
1183
 
                self.outf.write(path)
1184
1047
                if show_ids:
1185
 
                    self.outf.write(' ')
1186
 
                    self.outf.write(ie.file_id)
1187
 
                self.outf.write('\n')
 
1048
                    print '%-50s %s' % (path, ie.file_id)
 
1049
                else:
 
1050
                    print path
1188
1051
 
1189
1052
 
1190
1053
class cmd_modified(Command):
1198
1061
        td = compare_trees(tree.basis_tree(), tree)
1199
1062
 
1200
1063
        for path, id, kind, text_modified, meta_modified in td.modified:
1201
 
            self.outf.write(path + '\n')
 
1064
            print path
 
1065
 
1202
1066
 
1203
1067
 
1204
1068
class cmd_added(Command):
1213
1077
            if file_id in basis_inv:
1214
1078
                continue
1215
1079
            path = inv.id2path(file_id)
1216
 
            if not os.access(osutils.abspath(path), os.F_OK):
 
1080
            if not os.access(bzrlib.osutils.abspath(path), os.F_OK):
1217
1081
                continue
1218
 
            self.outf.write(path + '\n')
1219
 
 
 
1082
            print path
 
1083
                
 
1084
        
1220
1085
 
1221
1086
class cmd_root(Command):
1222
1087
    """Show the tree root directory.
1228
1093
    def run(self, filename=None):
1229
1094
        """Print the branch root."""
1230
1095
        tree = WorkingTree.open_containing(filename)[0]
1231
 
        self.outf.write(tree.basedir + '\n')
 
1096
        print tree.basedir
1232
1097
 
1233
1098
 
1234
1099
class cmd_log(Command):
1262
1127
                            type=str),
1263
1128
                     'short',
1264
1129
                     ]
1265
 
    encoding_type = 'replace'
1266
 
 
1267
1130
    @display_command
1268
1131
    def run(self, location=None, timezone='original',
1269
1132
            verbose=False,
1276
1139
            short=False,
1277
1140
            line=False):
1278
1141
        from bzrlib.log import log_formatter, show_log
 
1142
        import codecs
1279
1143
        assert message is None or isinstance(message, basestring), \
1280
1144
            "invalid message argument %r" % message
1281
1145
        direction = (forward and 'forward') or 'reverse'
1327
1191
        if rev1 > rev2:
1328
1192
            (rev2, rev1) = (rev1, rev2)
1329
1193
 
 
1194
        mutter('encoding log as %r', bzrlib.user_encoding)
 
1195
 
 
1196
        # use 'replace' so that we don't abort if trying to write out
 
1197
        # in e.g. the default C locale.
 
1198
        outf = codecs.getwriter(bzrlib.user_encoding)(sys.stdout, errors='replace')
 
1199
 
1330
1200
        if (log_format == None):
1331
 
            default = b.get_config().log_format()
1332
 
            log_format = get_log_format(long=long, short=short, line=line, 
1333
 
                                        default=default)
 
1201
            default = bzrlib.config.BranchConfig(b).log_format()
 
1202
            log_format = get_log_format(long=long, short=short, line=line, default=default)
 
1203
 
1334
1204
        lf = log_formatter(log_format,
1335
1205
                           show_ids=show_ids,
1336
 
                           to_file=self.outf,
 
1206
                           to_file=outf,
1337
1207
                           show_timezone=timezone)
1338
1208
 
1339
1209
        show_log(b,
1360
1230
class cmd_touching_revisions(Command):
1361
1231
    """Return revision-ids which affected a particular file.
1362
1232
 
1363
 
    A more user-friendly interface is "bzr log FILE".
1364
 
    """
1365
 
 
 
1233
    A more user-friendly interface is "bzr log FILE"."""
1366
1234
    hidden = True
1367
1235
    takes_args = ["filename"]
1368
 
 
1369
1236
    @display_command
1370
1237
    def run(self, filename):
1371
1238
        tree, relpath = WorkingTree.open_containing(filename)
1372
1239
        b = tree.branch
1373
1240
        inv = tree.read_working_inventory()
1374
1241
        file_id = inv.path2id(relpath)
1375
 
        for revno, revision_id, what in log.find_touching_revisions(b, file_id):
1376
 
            self.outf.write("%6d %s\n" % (revno, what))
 
1242
        for revno, revision_id, what in bzrlib.log.find_touching_revisions(b, file_id):
 
1243
            print "%6d %s" % (revno, what)
1377
1244
 
1378
1245
 
1379
1246
class cmd_ls(Command):
1412
1279
        if revision is not None:
1413
1280
            tree = tree.branch.repository.revision_tree(
1414
1281
                revision[0].in_history(tree.branch).rev_id)
1415
 
 
1416
1282
        for fp, fc, kind, fid, entry in tree.list_files():
1417
1283
            if fp.startswith(relpath):
1418
1284
                fp = fp[len(relpath):]
1422
1288
                    continue
1423
1289
                if verbose:
1424
1290
                    kindch = entry.kind_character()
1425
 
                    self.outf.write('%-8s %s%s\n' % (fc, fp, kindch))
 
1291
                    print '%-8s %s%s' % (fc, fp, kindch)
1426
1292
                elif null:
1427
 
                    self.outf.write(fp + '\0')
1428
 
                    self.outf.flush()
 
1293
                    sys.stdout.write(fp)
 
1294
                    sys.stdout.write('\0')
 
1295
                    sys.stdout.flush()
1429
1296
                else:
1430
 
                    self.outf.write(fp + '\n')
 
1297
                    print fp
1431
1298
 
1432
1299
 
1433
1300
class cmd_unknowns(Command):
1434
1301
    """List unknown files."""
1435
1302
    @display_command
1436
1303
    def run(self):
 
1304
        from bzrlib.osutils import quotefn
1437
1305
        for f in WorkingTree.open_containing(u'.')[0].unknowns():
1438
 
            self.outf.write(osutils.quotefn(f) + '\n')
 
1306
            print quotefn(f)
1439
1307
 
1440
1308
 
1441
1309
class cmd_ignore(Command):
1457
1325
        bzr ignore '*.class'
1458
1326
    """
1459
1327
    # TODO: Complain if the filename is absolute
1460
 
    takes_args = ['name_pattern?']
1461
 
    takes_options = [
1462
 
                     Option('old-default-rules',
1463
 
                            help='Out the ignore rules bzr < 0.9 always used.')
1464
 
                     ]
 
1328
    takes_args = ['name_pattern']
1465
1329
    
1466
 
    def run(self, name_pattern=None, old_default_rules=None):
 
1330
    def run(self, name_pattern):
1467
1331
        from bzrlib.atomicfile import AtomicFile
1468
 
        if old_default_rules is not None:
1469
 
            # dump the rules and exit
1470
 
            for pattern in bzrlib.DEFAULT_IGNORE:
1471
 
                print pattern
1472
 
            return
1473
 
        if name_pattern is None:
1474
 
            raise BzrCommandError("ignore requires a NAME_PATTERN")
 
1332
        import os.path
 
1333
 
1475
1334
        tree, relpath = WorkingTree.open_containing(u'.')
1476
1335
        ifn = tree.abspath('.bzrignore')
 
1336
 
1477
1337
        if os.path.exists(ifn):
1478
1338
            f = open(ifn, 'rt')
1479
1339
            try:
1490
1350
            igns += '\n'
1491
1351
        igns += name_pattern + '\n'
1492
1352
 
1493
 
        f = AtomicFile(ifn, 'wt')
1494
1353
        try:
 
1354
            f = AtomicFile(ifn, 'wt')
1495
1355
            f.write(igns.encode('utf-8'))
1496
1356
            f.commit()
1497
1357
        finally:
1564
1424
    takes_args = ['dest']
1565
1425
    takes_options = ['revision', 'format', 'root']
1566
1426
    def run(self, dest, revision=None, format=None, root=None):
 
1427
        import os.path
1567
1428
        from bzrlib.export import export
1568
1429
        tree = WorkingTree.open_containing(u'.')[0]
1569
1430
        b = tree.branch
1612
1473
    hidden = True    
1613
1474
    @display_command
1614
1475
    def run(self):
1615
 
        print osutils.local_time_offset()
 
1476
        print bzrlib.osutils.local_time_offset()
1616
1477
 
1617
1478
 
1618
1479
 
1665
1526
        from bzrlib.msgeditor import edit_commit_message, \
1666
1527
                make_commit_message_template
1667
1528
        from tempfile import TemporaryFile
 
1529
        import codecs
1668
1530
 
1669
1531
        # TODO: Need a blackbox test for invoking the external editor; may be
1670
1532
        # slightly problematic to run this cross-platform.
1675
1537
        # TODO: if the commit *does* happen to fail, then save the commit 
1676
1538
        # message to a temporary file where it can be recovered
1677
1539
        tree, selected_list = tree_files(selected_list)
1678
 
        if selected_list == ['']:
1679
 
            # workaround - commit of root of tree should be exactly the same
1680
 
            # as just default commit in that tree, and succeed even though
1681
 
            # selected-file merge commit is not done yet
1682
 
            selected_list = []
1683
 
 
1684
1540
        if local and not tree.branch.get_bound_location():
1685
1541
            raise errors.LocalRequiresBoundBranch()
1686
1542
        if message is None and not file:
1693
1549
            raise BzrCommandError("please specify either --message or --file")
1694
1550
        
1695
1551
        if file:
 
1552
            import codecs
1696
1553
            message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1697
1554
 
1698
1555
        if message == "":
1699
 
            raise BzrCommandError("empty commit message specified")
 
1556
                raise BzrCommandError("empty commit message specified")
1700
1557
        
1701
1558
        if verbose:
1702
1559
            reporter = ReportCommitToLog()
1710
1567
        except PointlessCommit:
1711
1568
            # FIXME: This should really happen before the file is read in;
1712
1569
            # perhaps prepare the commit; get the message; then actually commit
1713
 
            raise BzrCommandError("no changes to commit."
1714
 
                                  " use --unchanged to commit anyhow")
 
1570
            raise BzrCommandError("no changes to commit",
 
1571
                                  ["use --unchanged to commit anyhow"])
1715
1572
        except ConflictsInTree:
1716
1573
            raise BzrCommandError("Conflicts detected in working tree.  "
1717
1574
                'Use "bzr conflicts" to list, "bzr resolve FILE" to resolve.')
1772
1629
    takes_args = ['url?']
1773
1630
    takes_options = [
1774
1631
                     Option('format', 
1775
 
                            help='Upgrade to a specific format. Current formats'
1776
 
                                 ' are: default, knit, metaweave and weave.'
1777
 
                                 ' Default is knit; metaweave and weave are'
1778
 
                                 ' deprecated',
 
1632
                            help='Upgrade to a specific format rather than the'
 
1633
                                 ' current default format. Currently this'
 
1634
                                 ' option only accepts "metadir" and "knit".'
 
1635
                                 ' WARNING: the knit format is currently'
 
1636
                                 ' unstable and only for experimental use.',
1779
1637
                            type=get_format_type),
1780
1638
                    ]
1781
1639
 
1782
1640
 
1783
1641
    def run(self, url='.', format=None):
1784
1642
        from bzrlib.upgrade import upgrade
1785
 
        if format is None:
1786
 
            format = get_format_type('default')
1787
1643
        upgrade(url, format)
1788
1644
 
1789
1645
 
1790
1646
class cmd_whoami(Command):
1791
 
    """Show or set bzr user id.
1792
 
    
1793
 
    examples:
1794
 
        bzr whoami --email
1795
 
        bzr whoami 'Frank Chu <fchu@example.com>'
1796
 
    """
1797
 
    takes_options = [ Option('email',
1798
 
                             help='display email address only'),
1799
 
                      Option('branch',
1800
 
                             help='set identity for the current branch instead of '
1801
 
                                  'globally'),
1802
 
                    ]
1803
 
    takes_args = ['name?']
1804
 
    encoding_type = 'replace'
 
1647
    """Show bzr user id."""
 
1648
    takes_options = ['email']
1805
1649
    
1806
1650
    @display_command
1807
 
    def run(self, email=False, branch=False, name=None):
1808
 
        if name is None:
1809
 
            # use branch if we're inside one; otherwise global config
1810
 
            try:
1811
 
                c = Branch.open_containing('.')[0].get_config()
1812
 
            except NotBranchError:
1813
 
                c = config.GlobalConfig()
1814
 
            if email:
1815
 
                self.outf.write(c.user_email() + '\n')
1816
 
            else:
1817
 
                self.outf.write(c.username() + '\n')
1818
 
            return
1819
 
 
1820
 
        # use global config unless --branch given
1821
 
        if branch:
1822
 
            c = Branch.open_containing('.')[0].get_config()
 
1651
    def run(self, email=False):
 
1652
        try:
 
1653
            b = WorkingTree.open_containing(u'.')[0].branch
 
1654
            config = bzrlib.config.BranchConfig(b)
 
1655
        except NotBranchError:
 
1656
            config = bzrlib.config.GlobalConfig()
 
1657
        
 
1658
        if email:
 
1659
            print config.user_email()
1823
1660
        else:
1824
 
            c = config.GlobalConfig()
1825
 
        c.set_user_option('email', name)
 
1661
            print config.username()
1826
1662
 
1827
1663
 
1828
1664
class cmd_nick(Command):
1893
1729
                            help='Use a different transport by default '
1894
1730
                                 'throughout the test suite.',
1895
1731
                            type=get_transport_type),
1896
 
                     Option('benchmark', help='run the bzr bencharks.'),
1897
 
                     Option('lsprof-timed',
1898
 
                            help='generate lsprof output for benchmarked'
1899
 
                                 ' sections of code.'),
1900
 
                     ]
 
1732
                    ]
1901
1733
 
1902
 
    def run(self, testspecs_list=None, verbose=None, one=False,
1903
 
            keep_output=False, transport=None, benchmark=None,
1904
 
            lsprof_timed=None):
 
1734
    def run(self, testspecs_list=None, verbose=False, one=False,
 
1735
            keep_output=False, transport=None):
1905
1736
        import bzrlib.ui
1906
1737
        from bzrlib.tests import selftest
1907
 
        import bzrlib.benchmarks as benchmarks
1908
1738
        # we don't want progress meters from the tests to go to the
1909
1739
        # real output; and we don't want log messages cluttering up
1910
1740
        # the real logs.
1911
 
        save_ui = ui.ui_factory
1912
 
        print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
1913
 
        print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
1914
 
        print
1915
 
        info('running tests...')
 
1741
        save_ui = bzrlib.ui.ui_factory
 
1742
        bzrlib.trace.info('running tests...')
1916
1743
        try:
1917
 
            ui.ui_factory = ui.SilentUIFactory()
 
1744
            bzrlib.ui.ui_factory = bzrlib.ui.SilentUIFactory()
1918
1745
            if testspecs_list is not None:
1919
1746
                pattern = '|'.join(testspecs_list)
1920
1747
            else:
1921
1748
                pattern = ".*"
1922
 
            if benchmark:
1923
 
                test_suite_factory = benchmarks.test_suite
1924
 
                if verbose is None:
1925
 
                    verbose = True
1926
 
            else:
1927
 
                test_suite_factory = None
1928
 
                if verbose is None:
1929
 
                    verbose = False
1930
1749
            result = selftest(verbose=verbose, 
1931
1750
                              pattern=pattern,
1932
1751
                              stop_on_failure=one, 
1933
1752
                              keep_output=keep_output,
1934
 
                              transport=transport,
1935
 
                              test_suite_factory=test_suite_factory,
1936
 
                              lsprof_timed=lsprof_timed)
 
1753
                              transport=transport)
1937
1754
            if result:
1938
 
                info('tests passed')
 
1755
                bzrlib.trace.info('tests passed')
1939
1756
            else:
1940
 
                info('tests failed')
 
1757
                bzrlib.trace.info('tests failed')
1941
1758
            return int(not result)
1942
1759
        finally:
1943
 
            ui.ui_factory = save_ui
 
1760
            bzrlib.ui.ui_factory = save_ui
1944
1761
 
1945
1762
 
1946
1763
def _get_bzr_branch():
1947
1764
    """If bzr is run from a branch, return Branch or None"""
 
1765
    import bzrlib.errors
 
1766
    from bzrlib.branch import Branch
 
1767
    from bzrlib.osutils import abspath
1948
1768
    from os.path import dirname
1949
1769
    
1950
1770
    try:
1951
 
        branch = Branch.open(dirname(osutils.abspath(dirname(__file__))))
 
1771
        branch = Branch.open(dirname(abspath(dirname(__file__))))
1952
1772
        return branch
1953
 
    except errors.BzrError:
 
1773
    except bzrlib.errors.BzrError:
1954
1774
        return None
1955
1775
    
1956
1776
 
1957
1777
def show_version():
1958
 
    import bzrlib
1959
1778
    print "bzr (bazaar-ng) %s" % bzrlib.__version__
1960
1779
    # is bzrlib itself in a branch?
1961
1780
    branch = _get_bzr_branch()
1966
1785
        print "  nick: %s" % (branch.nick,)
1967
1786
        if rh:
1968
1787
            print "  revid: %s" % (rh[-1],)
1969
 
    print "Using python interpreter:", sys.executable
1970
 
    import site
1971
 
    print "Using python standard library:", os.path.dirname(site.__file__)
1972
 
    print "Using bzrlib:",
1973
 
    if len(bzrlib.__path__) > 1:
1974
 
        # print repr, which is a good enough way of making it clear it's
1975
 
        # more than one element (eg ['/foo/bar', '/foo/bzr'])
1976
 
        print repr(bzrlib.__path__)
1977
 
    else:
1978
 
        print bzrlib.__path__[0]
1979
 
 
1980
 
    print
1981
1788
    print bzrlib.__copyright__
1982
 
    print "http://bazaar-vcs.org/"
 
1789
    print "http://bazaar-ng.org/"
1983
1790
    print
1984
1791
    print "bzr comes with ABSOLUTELY NO WARRANTY.  bzr is free software, and"
1985
1792
    print "you may use, modify and redistribute it under the terms of the GNU"
2027
1834
        base_rev_id = common_ancestor(last1, last2, source)
2028
1835
 
2029
1836
        print 'merge base is revision %s' % base_rev_id
 
1837
        
 
1838
        return
 
1839
 
 
1840
        if base_revno is None:
 
1841
            raise bzrlib.errors.UnrelatedBranches()
 
1842
 
 
1843
        print ' r%-6d in %s' % (base_revno, branch)
 
1844
 
 
1845
        other_revno = branch2.revision_id_to_revno(base_revid)
 
1846
        
 
1847
        print ' r%-6d in %s' % (other_revno, other)
 
1848
 
2030
1849
 
2031
1850
 
2032
1851
class cmd_merge(Command):
2033
1852
    """Perform a three-way merge.
2034
1853
    
2035
 
    The branch is the branch you will merge from.  By default, it will merge
2036
 
    the latest revision.  If you specify a revision, that revision will be
2037
 
    merged.  If you specify two revisions, the first will be used as a BASE,
2038
 
    and the second one as OTHER.  Revision numbers are always relative to the
2039
 
    specified branch.
 
1854
    The branch is the branch you will merge from.  By default, it will
 
1855
    merge the latest revision.  If you specify a revision, that
 
1856
    revision will be merged.  If you specify two revisions, the first
 
1857
    will be used as a BASE, and the second one as OTHER.  Revision
 
1858
    numbers are always relative to the specified branch.
2040
1859
 
2041
1860
    By default, bzr will try to merge in all new work from the other
2042
1861
    branch, automatically determining an appropriate base.  If this
2051
1870
 
2052
1871
    If there is no default branch set, the first merge will set it. After
2053
1872
    that, you can omit the branch to use the default.  To change the
2054
 
    default, use --remember. The value will only be saved if the remote
2055
 
    location can be accessed.
 
1873
    default, use --remember.
2056
1874
 
2057
1875
    Examples:
2058
1876
 
2067
1885
    
2068
1886
    merge refuses to run if there are any uncommitted changes, unless
2069
1887
    --force is given.
2070
 
 
2071
 
    The following merge types are available:
2072
1888
    """
2073
1889
    takes_args = ['branch?']
2074
1890
    takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
2075
1891
                     Option('show-base', help="Show base revision text in "
2076
1892
                            "conflicts")]
2077
1893
 
2078
 
    def help(self):
2079
 
        from merge import merge_type_help
2080
 
        from inspect import getdoc
2081
 
        return getdoc(self) + '\n' + merge_type_help() 
2082
 
 
2083
1894
    def run(self, branch=None, revision=None, force=False, merge_type=None,
2084
1895
            show_base=False, reprocess=False, remember=False):
2085
1896
        if merge_type is None:
2086
1897
            merge_type = Merge3Merger
2087
1898
 
2088
1899
        tree = WorkingTree.open_containing(u'.')[0]
2089
 
 
2090
 
        if branch is not None:
2091
 
            try:
2092
 
                reader = bundle.read_bundle_from_url(branch)
2093
 
            except NotABundle:
2094
 
                pass # Continue on considering this url a Branch
 
1900
        stored_loc = tree.branch.get_parent()
 
1901
        if branch is None:
 
1902
            if stored_loc is None:
 
1903
                raise BzrCommandError("No merge branch known or specified.")
2095
1904
            else:
2096
 
                conflicts = merge_bundle(reader, tree, not force, merge_type,
2097
 
                                            reprocess, show_base)
2098
 
                if conflicts == 0:
2099
 
                    return 0
2100
 
                else:
2101
 
                    return 1
 
1905
                print "Using saved branch: %s" % stored_loc
 
1906
                branch = stored_loc
2102
1907
 
2103
 
        branch = self._get_remembered_parent(tree, branch, 'Merging from')
 
1908
        if tree.branch.get_parent() is None or remember:
 
1909
            tree.branch.set_parent(branch)
2104
1910
 
2105
1911
        if revision is None or len(revision) < 1:
2106
1912
            base = [None, None]
2117
1923
                if None in revision:
2118
1924
                    raise BzrCommandError(
2119
1925
                        "Merge doesn't permit that revision specifier.")
2120
 
                other_branch, path = Branch.open_containing(branch)
2121
 
 
2122
 
                base = [branch, revision[0].in_history(other_branch).revno]
2123
 
                other = [branch, revision[1].in_history(other_branch).revno]
2124
 
 
2125
 
        if tree.branch.get_parent() is None or remember:
2126
 
            tree.branch.set_parent(other_branch.base)
2127
 
 
 
1926
                b, path = Branch.open_containing(branch)
 
1927
 
 
1928
                base = [branch, revision[0].in_history(b).revno]
 
1929
                other = [branch, revision[1].in_history(b).revno]
2128
1930
        if path != "":
2129
1931
            interesting_files = [path]
2130
1932
        else:
2131
1933
            interesting_files = None
2132
 
        pb = ui.ui_factory.nested_progress_bar()
 
1934
        pb = bzrlib.ui.ui_factory.nested_progress_bar()
2133
1935
        try:
2134
1936
            try:
2135
1937
                conflict_count = merge(other, base, check_clean=(not force),
2136
 
                                       merge_type=merge_type,
 
1938
                                       merge_type=merge_type, 
2137
1939
                                       reprocess=reprocess,
2138
 
                                       show_base=show_base,
 
1940
                                       show_base=show_base, 
2139
1941
                                       pb=pb, file_list=interesting_files)
2140
1942
            finally:
2141
1943
                pb.finished()
2143
1945
                return 1
2144
1946
            else:
2145
1947
                return 0
2146
 
        except errors.AmbiguousBase, e:
 
1948
        except bzrlib.errors.AmbiguousBase, e:
2147
1949
            m = ("sorry, bzr can't determine the right merge base yet\n"
2148
1950
                 "candidates are:\n  "
2149
1951
                 + "\n  ".join(e.bases)
2152
1954
                 "and (if you want) report this to the bzr developers\n")
2153
1955
            log_error(m)
2154
1956
 
2155
 
    # TODO: move up to common parent; this isn't merge-specific anymore. 
2156
 
    def _get_remembered_parent(self, tree, supplied_location, verb_string):
2157
 
        """Use tree.branch's parent if none was supplied.
2158
 
 
2159
 
        Report if the remembered location was used.
2160
 
        """
2161
 
        if supplied_location is not None:
2162
 
            return supplied_location
2163
 
        stored_location = tree.branch.get_parent()
2164
 
        mutter("%s", stored_location)
2165
 
        if stored_location is None:
2166
 
            raise BzrCommandError("No location specified or remembered")
2167
 
        display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
2168
 
        self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
2169
 
        return stored_location
2170
 
 
2171
1957
 
2172
1958
class cmd_remerge(Command):
2173
1959
    """Redo a merge.
2174
 
 
2175
 
    Use this if you want to try a different merge technique while resolving
2176
 
    conflicts.  Some merge techniques are better than others, and remerge 
2177
 
    lets you try different ones on different files.
2178
 
 
2179
 
    The options for remerge have the same meaning and defaults as the ones for
2180
 
    merge.  The difference is that remerge can (only) be run when there is a
2181
 
    pending merge, and it lets you specify particular files.
2182
 
 
2183
 
    Examples:
2184
 
    $ bzr remerge --show-base
2185
 
        Re-do the merge of all conflicted files, and show the base text in
2186
 
        conflict regions, in addition to the usual THIS and OTHER texts.
2187
 
 
2188
 
    $ bzr remerge --merge-type weave --reprocess foobar
2189
 
        Re-do the merge of "foobar", using the weave merge algorithm, with
2190
 
        additional processing to reduce the size of conflict regions.
2191
 
    
2192
 
    The following merge types are available:"""
 
1960
    """
2193
1961
    takes_args = ['file*']
2194
1962
    takes_options = ['merge-type', 'reprocess',
2195
1963
                     Option('show-base', help="Show base revision text in "
2196
1964
                            "conflicts")]
2197
1965
 
2198
 
    def help(self):
2199
 
        from merge import merge_type_help
2200
 
        from inspect import getdoc
2201
 
        return getdoc(self) + '\n' + merge_type_help() 
2202
 
 
2203
1966
    def run(self, file_list=None, merge_type=None, show_base=False,
2204
1967
            reprocess=False):
2205
1968
        from bzrlib.merge import merge_inner, transform_tree
2211
1974
            pending_merges = tree.pending_merges() 
2212
1975
            if len(pending_merges) != 1:
2213
1976
                raise BzrCommandError("Sorry, remerge only works after normal"
2214
 
                                      " merges.  Not cherrypicking or"
2215
 
                                      " multi-merges.")
 
1977
                                      + " merges.  Not cherrypicking or"
 
1978
                                      + "multi-merges.")
2216
1979
            repository = tree.branch.repository
2217
1980
            base_revision = common_ancestor(tree.branch.last_revision(), 
2218
1981
                                            pending_merges[0], repository)
2219
1982
            base_tree = repository.revision_tree(base_revision)
2220
1983
            other_tree = repository.revision_tree(pending_merges[0])
2221
1984
            interesting_ids = None
2222
 
            new_conflicts = []
2223
 
            conflicts = tree.conflicts()
2224
1985
            if file_list is not None:
2225
1986
                interesting_ids = set()
2226
1987
                for filename in file_list:
2233
1994
                    
2234
1995
                    for name, ie in tree.inventory.iter_entries(file_id):
2235
1996
                        interesting_ids.add(ie.file_id)
2236
 
                new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
2237
1997
            transform_tree(tree, tree.basis_tree(), interesting_ids)
2238
 
            tree.set_conflicts(ConflictList(new_conflicts))
2239
1998
            if file_list is None:
2240
1999
                restore_files = list(tree.iter_conflicts())
2241
2000
            else:
2245
2004
                    restore(tree.abspath(filename))
2246
2005
                except NotConflicted:
2247
2006
                    pass
2248
 
            conflicts = merge_inner(tree.branch, other_tree, base_tree,
2249
 
                                    this_tree=tree,
2250
 
                                    interesting_ids=interesting_ids, 
2251
 
                                    other_rev_id=pending_merges[0], 
2252
 
                                    merge_type=merge_type, 
2253
 
                                    show_base=show_base,
2254
 
                                    reprocess=reprocess)
 
2007
            conflicts =  merge_inner(tree.branch, other_tree, base_tree,
 
2008
                                     this_tree=tree,
 
2009
                                     interesting_ids = interesting_ids, 
 
2010
                                     other_rev_id=pending_merges[0], 
 
2011
                                     merge_type=merge_type, 
 
2012
                                     show_base=show_base,
 
2013
                                     reprocess=reprocess)
2255
2014
        finally:
2256
2015
            tree.unlock()
2257
2016
        if conflicts > 0:
2286
2045
            raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
2287
2046
        else:
2288
2047
            rev_id = revision[0].in_history(tree.branch).rev_id
2289
 
        pb = ui.ui_factory.nested_progress_bar()
 
2048
        pb = bzrlib.ui.ui_factory.nested_progress_bar()
2290
2049
        try:
2291
2050
            tree.revert(file_list, 
2292
2051
                        tree.branch.repository.revision_tree(rev_id),
2340
2099
    takes_args = ['from_branch', 'to_branch']
2341
2100
    def run(self, from_branch, to_branch):
2342
2101
        from bzrlib.fetch import Fetcher
 
2102
        from bzrlib.branch import Branch
2343
2103
        from_b = Branch.open(from_branch)
2344
2104
        to_b = Branch.open(to_branch)
2345
2105
        Fetcher(to_b, from_b)
2362
2122
                     'show-ids',
2363
2123
                     'verbose'
2364
2124
                     ]
2365
 
    encoding_type = 'replace'
2366
2125
 
2367
 
    @display_command
2368
2126
    def run(self, other_branch=None, reverse=False, mine_only=False,
2369
2127
            theirs_only=False, log_format=None, long=False, short=False, line=False, 
2370
2128
            show_ids=False, verbose=False):
2371
2129
        from bzrlib.missing import find_unmerged, iter_log_data
2372
2130
        from bzrlib.log import log_formatter
2373
 
        local_branch = Branch.open_containing(u".")[0]
 
2131
        local_branch = bzrlib.branch.Branch.open_containing(u".")[0]
2374
2132
        parent = local_branch.get_parent()
2375
2133
        if other_branch is None:
2376
2134
            other_branch = parent
2377
2135
            if other_branch is None:
2378
2136
                raise BzrCommandError("No missing location known or specified.")
2379
2137
            print "Using last location: " + local_branch.get_parent()
2380
 
        remote_branch = Branch.open(other_branch)
 
2138
        remote_branch = bzrlib.branch.Branch.open(other_branch)
 
2139
        local_branch.lock_write()
2381
2140
        if remote_branch.base == local_branch.base:
2382
2141
            remote_branch = local_branch
2383
 
        local_branch.lock_read()
2384
2142
        try:
2385
2143
            remote_branch.lock_read()
2386
2144
            try:
2387
2145
                local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
2388
2146
                if (log_format == None):
2389
 
                    default = local_branch.get_config().log_format()
2390
 
                    log_format = get_log_format(long=long, short=short, 
2391
 
                                                line=line, default=default)
2392
 
                lf = log_formatter(log_format,
2393
 
                                   to_file=self.outf,
 
2147
                    default = bzrlib.config.BranchConfig(local_branch).log_format()
 
2148
                    log_format = get_log_format(long=long, short=short, line=line, default=default)
 
2149
                lf = log_formatter(log_format, sys.stdout,
2394
2150
                                   show_ids=show_ids,
2395
2151
                                   show_timezone='original')
2396
2152
                if reverse is False:
2416
2172
                    print "Branches are up to date."
2417
2173
                else:
2418
2174
                    status_code = 1
2419
 
            finally:
2420
 
                remote_branch.unlock()
2421
 
        finally:
2422
 
            local_branch.unlock()
2423
 
        if not status_code and parent is None and other_branch is not None:
2424
 
            local_branch.lock_write()
2425
 
            try:
2426
 
                # handle race conditions - a parent might be set while we run.
2427
 
                if local_branch.get_parent() is None:
2428
 
                    local_branch.set_parent(remote_branch.base)
 
2175
                if parent is None and other_branch is not None:
 
2176
                    local_branch.set_parent(other_branch)
 
2177
                return status_code
2429
2178
            finally:
2430
2179
                local_branch.unlock()
2431
 
        return status_code
 
2180
        finally:
 
2181
            remote_branch.unlock()
2432
2182
 
2433
2183
 
2434
2184
class cmd_plugins(Command):
2453
2203
 
2454
2204
class cmd_testament(Command):
2455
2205
    """Show testament (signing-form) of a revision."""
2456
 
    takes_options = ['revision', 'long', 
2457
 
                     Option('strict', help='Produce a strict-format'
2458
 
                            ' testament')]
 
2206
    takes_options = ['revision', 'long']
2459
2207
    takes_args = ['branch?']
2460
2208
    @display_command
2461
 
    def run(self, branch=u'.', revision=None, long=False, strict=False):
2462
 
        from bzrlib.testament import Testament, StrictTestament
2463
 
        if strict is True:
2464
 
            testament_class = StrictTestament
2465
 
        else:
2466
 
            testament_class = Testament
 
2209
    def run(self, branch=u'.', revision=None, long=False):
 
2210
        from bzrlib.testament import Testament
2467
2211
        b = WorkingTree.open_containing(branch)[0].branch
2468
2212
        b.lock_read()
2469
2213
        try:
2471
2215
                rev_id = b.last_revision()
2472
2216
            else:
2473
2217
                rev_id = revision[0].in_history(b).rev_id
2474
 
            t = testament_class.from_revision(b.repository, rev_id)
 
2218
            t = Testament.from_revision(b.repository, rev_id)
2475
2219
            if long:
2476
2220
                sys.stdout.writelines(t.as_text_lines())
2477
2221
            else:
2490
2234
    shown only at the top, unless the --all option is given.
2491
2235
    """
2492
2236
    # TODO: annotate directories; showing when each file was last changed
 
2237
    # TODO: annotate a previous version of a file
2493
2238
    # TODO: if the working copy is modified, show annotations on that 
2494
2239
    #       with new uncommitted lines marked
2495
 
    aliases = ['ann', 'blame', 'praise']
 
2240
    aliases = ['blame', 'praise']
2496
2241
    takes_args = ['filename']
2497
2242
    takes_options = [Option('all', help='show annotations on all lines'),
2498
2243
                     Option('long', help='show date in annotations'),
2499
 
                     'revision'
2500
2244
                     ]
2501
2245
 
2502
2246
    @display_command
2503
 
    def run(self, filename, all=False, long=False, revision=None):
 
2247
    def run(self, filename, all=False, long=False):
2504
2248
        from bzrlib.annotate import annotate_file
2505
2249
        tree, relpath = WorkingTree.open_containing(filename)
2506
2250
        branch = tree.branch
2507
2251
        branch.lock_read()
2508
2252
        try:
2509
 
            if revision is None:
2510
 
                revision_id = branch.last_revision()
2511
 
            elif len(revision) != 1:
2512
 
                raise BzrCommandError('bzr annotate --revision takes exactly 1 argument')
2513
 
            else:
2514
 
                revision_id = revision[0].in_history(branch).rev_id
2515
2253
            file_id = tree.inventory.path2id(relpath)
2516
 
            tree = branch.repository.revision_tree(revision_id)
 
2254
            tree = branch.repository.revision_tree(branch.last_revision())
2517
2255
            file_version = tree.inventory[file_id].revision
2518
2256
            annotate_file(branch, file_version, file_id, long, all, sys.stdout)
2519
2257
        finally:
2529
2267
    takes_options = ['revision']
2530
2268
    
2531
2269
    def run(self, revision_id_list=None, revision=None):
 
2270
        import bzrlib.config as config
2532
2271
        import bzrlib.gpg as gpg
2533
2272
        if revision_id_list is not None and revision is not None:
2534
2273
            raise BzrCommandError('You can only supply one of revision_id or --revision')
2535
2274
        if revision_id_list is None and revision is None:
2536
2275
            raise BzrCommandError('You must supply either --revision or a revision_id')
2537
2276
        b = WorkingTree.open_containing(u'.')[0].branch
2538
 
        gpg_strategy = gpg.GPGStrategy(b.get_config())
 
2277
        gpg_strategy = gpg.GPGStrategy(config.BranchConfig(b))
2539
2278
        if revision_id_list is not None:
2540
2279
            for revision_id in revision_id_list:
2541
2280
                b.repository.sign_revision(revision_id, gpg_strategy)
2581
2320
 
2582
2321
 
2583
2322
class cmd_unbind(Command):
2584
 
    """Unbind the current branch from its master branch.
 
2323
    """Bind the current branch to its parent.
2585
2324
 
2586
2325
    After unbinding, the local branch is considered independent.
2587
 
    All subsequent commits will be local.
2588
2326
    """
2589
2327
 
2590
2328
    takes_args = []
2596
2334
            raise BzrCommandError('Local branch is not bound')
2597
2335
 
2598
2336
 
2599
 
class cmd_uncommit(Command):
 
2337
class cmd_uncommit(bzrlib.commands.Command):
2600
2338
    """Remove the last committed revision.
2601
2339
 
 
2340
    By supplying the --all flag, it will not only remove the entry 
 
2341
    from revision_history, but also remove all of the entries in the
 
2342
    stores.
 
2343
 
2602
2344
    --verbose will print out what is being removed.
2603
2345
    --dry-run will go through all the motions, but not actually
2604
2346
    remove anything.
2605
2347
    
2606
 
    In the future, uncommit will create a revision bundle, which can then
 
2348
    In the future, uncommit will create a changeset, which can then
2607
2349
    be re-applied.
2608
2350
    """
2609
2351
 
2610
2352
    # TODO: jam 20060108 Add an option to allow uncommit to remove
2611
 
    # unreferenced information in 'branch-as-repository' branches.
 
2353
    # unreferenced information in 'branch-as-repostory' branches.
2612
2354
    # TODO: jam 20060108 Add the ability for uncommit to remove unreferenced
2613
2355
    # information in shared branches as well.
2614
2356
    takes_options = ['verbose', 'revision',
2620
2362
    def run(self, location=None, 
2621
2363
            dry_run=False, verbose=False,
2622
2364
            revision=None, force=False):
 
2365
        from bzrlib.branch import Branch
2623
2366
        from bzrlib.log import log_formatter
2624
2367
        import sys
2625
2368
        from bzrlib.uncommit import uncommit
2668
2411
 
2669
2412
    CAUTION: Locks should only be broken when you are sure that the process
2670
2413
    holding the lock has been stopped.
2671
 
 
2672
 
    You can get information on what locks are open via the 'bzr info' command.
2673
2414
    
2674
2415
    example:
2675
 
        bzr break-lock
 
2416
        bzr break-lock .
2676
2417
    """
2677
 
    takes_args = ['location?']
2678
 
 
2679
 
    def run(self, location=None, show=False):
2680
 
        if location is None:
2681
 
            location = u'.'
2682
 
        control, relpath = bzrdir.BzrDir.open_containing(location)
2683
 
        try:
2684
 
            control.break_lock()
2685
 
        except NotImplementedError:
2686
 
            pass
2687
 
        
 
2418
    takes_args = ['location']
 
2419
    takes_options = [Option('show',
 
2420
                            help="just show information on the lock, " \
 
2421
                                 "don't break it"),
 
2422
                    ]
 
2423
    def run(self, location, show=False):
 
2424
        raise NotImplementedError("sorry, break-lock is not complete yet; "
 
2425
                "you can remove the 'held' directory manually to break the lock")
2688
2426
 
2689
2427
 
2690
2428
# command-line interpretation helper for merge-related commands
2727
2465
    if show_base and not merge_type is Merge3Merger:
2728
2466
        raise BzrCommandError("Show-base is not supported for this merge"
2729
2467
                              " type. %s" % merge_type)
2730
 
    if reprocess and not merge_type.supports_reprocess:
2731
 
        raise BzrCommandError("Conflict reduction is not supported for merge"
2732
 
                              " type %s." % merge_type)
 
2468
    if reprocess and not merge_type is Merge3Merger:
 
2469
        raise BzrCommandError("Reprocess is not supported for this merge"
 
2470
                              " type. %s" % merge_type)
2733
2471
    if reprocess and show_base:
2734
 
        raise BzrCommandError("Cannot do conflict reduction and show base.")
 
2472
        raise BzrCommandError("Cannot reprocess and show base.")
2735
2473
    try:
2736
2474
        merger = Merger(this_tree.branch, this_tree=this_tree, pb=pb)
2737
2475
        merger.pp = ProgressPhase("Merge phase", 5, pb)
2762
2500
# aliases.  ideally we would avoid loading the implementation until the
2763
2501
# details were needed.
2764
2502
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
2765
 
from bzrlib.bundle.commands import cmd_bundle_revisions
2766
2503
from bzrlib.sign_my_commits import cmd_sign_my_commits
2767
2504
from bzrlib.weave_commands import cmd_weave_list, cmd_weave_join, \
2768
2505
        cmd_weave_plan_merge, cmd_weave_merge_text