~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

[merge] bzr.dev 2255, resolve conflicts, update copyrights

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2004, 2005, 2006 by Canonical Ltd
 
1
# Copyright (C) 2004, 2005, 2006 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
16
16
 
17
17
"""builtin bzr commands"""
18
18
 
 
19
import os
19
20
 
 
21
from bzrlib.lazy_import import lazy_import
 
22
lazy_import(globals(), """
20
23
import codecs
21
24
import errno
22
 
import os
23
 
import os.path
24
25
import sys
 
26
import tempfile
25
27
 
26
28
import bzrlib
27
29
from bzrlib import (
28
30
    branch,
29
31
    bundle,
30
32
    bzrdir,
 
33
    delta,
31
34
    config,
32
35
    errors,
33
36
    ignores,
34
37
    log,
 
38
    merge as _mod_merge,
35
39
    osutils,
36
40
    repository,
37
41
    transport,
 
42
    tree as _mod_tree,
38
43
    ui,
39
44
    urlutils,
40
45
    )
41
 
from bzrlib.branch import Branch, BranchReferenceFormat
42
 
from bzrlib.bundle import read_bundle_from_url
 
46
from bzrlib.branch import Branch
43
47
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
44
48
from bzrlib.conflicts import ConflictList
 
49
from bzrlib.revision import common_ancestor
 
50
from bzrlib.revisionspec import RevisionSpec
 
51
from bzrlib.workingtree import WorkingTree
 
52
""")
 
53
 
45
54
from bzrlib.commands import Command, display_command
46
 
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError, 
47
 
                           NotBranchError, DivergedBranches, NotConflicted,
48
 
                           NoSuchFile, NoWorkingTree, FileInWrongBranch,
49
 
                           NotVersionedError, NotABundle)
50
 
from bzrlib.merge import Merge3Merger
51
 
from bzrlib.option import Option
 
55
from bzrlib.option import Option, RegistryOption
52
56
from bzrlib.progress import DummyProgress, ProgressPhase
53
 
from bzrlib.revision import common_ancestor
54
 
from bzrlib.revisionspec import RevisionSpec
55
57
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
56
 
from bzrlib.transport.local import LocalTransport
57
 
import bzrlib.tree
58
 
from bzrlib.workingtree import WorkingTree
59
58
 
60
59
 
61
60
def tree_files(file_list, default_branch=u'.'):
62
61
    try:
63
62
        return internal_tree_files(file_list, default_branch)
64
 
    except FileInWrongBranch, e:
65
 
        raise BzrCommandError("%s is not in the same branch as %s" %
66
 
                             (e.path, file_list[0]))
 
63
    except errors.FileInWrongBranch, e:
 
64
        raise errors.BzrCommandError("%s is not in the same branch as %s" %
 
65
                                     (e.path, file_list[0]))
67
66
 
68
67
 
69
68
# XXX: Bad function name; should possibly also be a class method of
78
77
 
79
78
    :param file_list: Filenames to convert.  
80
79
 
81
 
    :param default_branch: Fallback tree path to use if file_list is empty or None.
 
80
    :param default_branch: Fallback tree path to use if file_list is empty or
 
81
        None.
82
82
 
83
83
    :return: workingtree, [relative_paths]
84
84
    """
85
85
    if file_list is None or len(file_list) == 0:
86
86
        return WorkingTree.open_containing(default_branch)[0], file_list
87
 
    tree = WorkingTree.open_containing(file_list[0])[0]
 
87
    tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
88
88
    new_list = []
89
89
    for filename in file_list:
90
90
        try:
91
 
            new_list.append(tree.relpath(filename))
 
91
            new_list.append(tree.relpath(osutils.dereference_path(filename)))
92
92
        except errors.PathNotChild:
93
 
            raise FileInWrongBranch(tree.branch, filename)
 
93
            raise errors.FileInWrongBranch(tree.branch, filename)
94
94
    return tree, new_list
95
95
 
96
96
 
97
97
def get_format_type(typestring):
98
98
    """Parse and return a format specifier."""
99
 
    if typestring == "weave":
100
 
        return bzrdir.BzrDirFormat6()
 
99
    # Have to use BzrDirMetaFormat1 directly, so that
 
100
    # RepositoryFormat.set_default_format works
101
101
    if typestring == "default":
102
102
        return bzrdir.BzrDirMetaFormat1()
103
 
    if typestring == "metaweave":
104
 
        format = bzrdir.BzrDirMetaFormat1()
105
 
        format.repository_format = repository.RepositoryFormat7()
106
 
        return format
107
 
    if typestring == "knit":
108
 
        format = bzrdir.BzrDirMetaFormat1()
109
 
        format.repository_format = repository.RepositoryFormatKnit1()
110
 
        return format
111
 
    if typestring == "experimental-knit2":
112
 
        format = bzrdir.BzrDirMetaFormat1()
113
 
        format.repository_format = repository.RepositoryFormatKnit2()
114
 
        return format
115
 
    msg = "Unknown bzr format %s. Current formats are: default, knit,\n" \
116
 
          "metaweave and weave" % typestring
117
 
    raise BzrCommandError(msg)
 
103
    try:
 
104
        return bzrdir.format_registry.make_bzrdir(typestring)
 
105
    except KeyError:
 
106
        msg = 'Unknown bzr format "%s". See "bzr help formats".' % typestring
 
107
        raise errors.BzrCommandError(msg)
118
108
 
119
109
 
120
110
# TODO: Make sure no commands unconditionally use the working directory as a
129
119
    This reports on versioned and unknown files, reporting them
130
120
    grouped by state.  Possible states are:
131
121
 
132
 
    added
 
122
    added / A
133
123
        Versioned in the working copy but not in the previous revision.
134
124
 
135
 
    removed
 
125
    removed / D
136
126
        Versioned in the previous revision but removed or deleted
137
127
        in the working copy.
138
128
 
139
 
    renamed
 
129
    renamed / R
140
130
        Path of this file changed from the previous revision;
141
131
        the text may also have changed.  This includes files whose
142
132
        parent directory was renamed.
143
133
 
144
 
    modified
 
134
    modified / M
145
135
        Text has changed since the previous revision.
146
136
 
147
 
    unknown
 
137
    unknown / ?
148
138
        Not versioned and not matching an ignore pattern.
149
139
 
150
140
    To see ignored files use 'bzr ignored'.  For details in the
151
141
    changes to file texts, use 'bzr diff'.
 
142
    
 
143
    --short gives a one character status flag for each item, similar
 
144
    to the SVN's status command.
152
145
 
153
146
    If no arguments are specified, the status of the entire working
154
147
    directory is shown.  Otherwise, only the status of the specified
162
155
    # TODO: --no-recurse, --recurse options
163
156
    
164
157
    takes_args = ['file*']
165
 
    takes_options = ['show-ids', 'revision']
 
158
    takes_options = ['show-ids', 'revision', 'short']
166
159
    aliases = ['st', 'stat']
167
160
 
168
161
    encoding_type = 'replace'
169
162
    
170
163
    @display_command
171
 
    def run(self, show_ids=False, file_list=None, revision=None):
 
164
    def run(self, show_ids=False, file_list=None, revision=None, short=False):
172
165
        from bzrlib.status import show_tree_status
173
166
 
174
167
        tree, file_list = tree_files(file_list)
175
168
            
176
169
        show_tree_status(tree, show_ids=show_ids,
177
170
                         specific_files=file_list, revision=revision,
178
 
                         to_file=self.outf)
 
171
                         to_file=self.outf,
 
172
                         short=short)
179
173
 
180
174
 
181
175
class cmd_cat_revision(Command):
195
189
    def run(self, revision_id=None, revision=None):
196
190
 
197
191
        if revision_id is not None and revision is not None:
198
 
            raise BzrCommandError('You can only supply one of revision_id or --revision')
 
192
            raise errors.BzrCommandError('You can only supply one of'
 
193
                                         ' revision_id or --revision')
199
194
        if revision_id is None and revision is None:
200
 
            raise BzrCommandError('You must supply either --revision or a revision_id')
 
195
            raise errors.BzrCommandError('You must supply either'
 
196
                                         ' --revision or a revision_id')
201
197
        b = WorkingTree.open_containing(u'.')[0].branch
202
198
 
203
199
        # TODO: jam 20060112 should cat-revision always output utf-8?
206
202
        elif revision is not None:
207
203
            for rev in revision:
208
204
                if rev is None:
209
 
                    raise BzrCommandError('You cannot specify a NULL revision.')
 
205
                    raise errors.BzrCommandError('You cannot specify a NULL'
 
206
                                                 ' revision.')
210
207
                revno, rev_id = rev.in_history(b)
211
208
                self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
212
209
    
213
210
 
 
211
class cmd_remove_tree(Command):
 
212
    """Remove the working tree from a given branch/checkout.
 
213
 
 
214
    Since a lightweight checkout is little more than a working tree
 
215
    this will refuse to run against one.
 
216
    """
 
217
 
 
218
    hidden = True
 
219
 
 
220
    takes_args = ['location?']
 
221
 
 
222
    def run(self, location='.'):
 
223
        d = bzrdir.BzrDir.open(location)
 
224
        
 
225
        try:
 
226
            working = d.open_workingtree()
 
227
        except errors.NoWorkingTree:
 
228
            raise errors.BzrCommandError("No working tree to remove")
 
229
        except errors.NotLocalUrl:
 
230
            raise errors.BzrCommandError("You cannot remove the working tree of a "
 
231
                                         "remote path")
 
232
        
 
233
        working_path = working.bzrdir.root_transport.base
 
234
        branch_path = working.branch.bzrdir.root_transport.base
 
235
        if working_path != branch_path:
 
236
            raise errors.BzrCommandError("You cannot remove the working tree from "
 
237
                                         "a lightweight checkout")
 
238
        
 
239
        d.destroy_workingtree()
 
240
        
 
241
 
214
242
class cmd_revno(Command):
215
243
    """Show current revision number.
216
244
 
242
270
            for rev in revision_info_list:
243
271
                revs.append(RevisionSpec.from_string(rev))
244
272
        if len(revs) == 0:
245
 
            raise BzrCommandError('You must supply a revision identifier')
 
273
            raise errors.BzrCommandError('You must supply a revision identifier')
246
274
 
247
275
        b = WorkingTree.open_containing(u'.')[0].branch
248
276
 
299
327
                base_tree, base_path = WorkingTree.open_containing(
300
328
                                            file_ids_from)
301
329
            except errors.NoWorkingTree:
302
 
                base_branch, base_path = branch.Branch.open_containing(
 
330
                base_branch, base_path = Branch.open_containing(
303
331
                                            file_ids_from)
304
332
                base_tree = base_branch.basis_tree()
305
333
 
374
402
    @display_command
375
403
    def run(self, revision=None, show_ids=False, kind=None, file_list=None):
376
404
        if kind and kind not in ['file', 'directory', 'symlink']:
377
 
            raise BzrCommandError('invalid kind specified')
 
405
            raise errors.BzrCommandError('invalid kind specified')
378
406
 
379
407
        work_tree, file_list = tree_files(file_list)
380
408
 
381
409
        if revision is not None:
382
410
            if len(revision) > 1:
383
 
                raise BzrCommandError('bzr inventory --revision takes'
384
 
                                      ' exactly one revision identifier')
 
411
                raise errors.BzrCommandError('bzr inventory --revision takes'
 
412
                                             ' exactly one revision identifier')
385
413
            revision_id = revision[0].in_history(work_tree.branch).rev_id
386
414
            tree = work_tree.branch.repository.revision_tree(revision_id)
387
415
                        
395
423
            trees = [tree]
396
424
 
397
425
        if file_list is not None:
398
 
            file_ids = bzrlib.tree.find_ids_across_trees(file_list, trees,
 
426
            file_ids = _mod_tree.find_ids_across_trees(file_list, trees,
399
427
                                                      require_versioned=True)
400
428
            # find_ids_across_trees may include some paths that don't
401
429
            # exist in 'tree'.
423
451
 
424
452
    If the last argument is a versioned directory, all the other names
425
453
    are moved into it.  Otherwise, there must be exactly two arguments
426
 
    and the file is changed to a new name, which must not already exist.
 
454
    and the file is changed to a new name.
 
455
 
 
456
    If OLDNAME does not exist on the filesystem but is versioned and
 
457
    NEWNAME does exist on the filesystem but is not versioned, mv
 
458
    assumes that the file has been manually moved and only updates
 
459
    its internal inventory to reflect that change.
 
460
    The same is valid when moving many SOURCE files to a DESTINATION.
427
461
 
428
462
    Files cannot be moved between branches.
429
463
    """
430
464
 
431
465
    takes_args = ['names*']
 
466
    takes_options = [Option("after", help="move only the bzr identifier"
 
467
        " of the file (file has already been moved). Use this flag if"
 
468
        " bzr is not able to detect this itself.")]
432
469
    aliases = ['move', 'rename']
433
470
    encoding_type = 'replace'
434
471
 
435
 
    def run(self, names_list):
 
472
    def run(self, names_list, after=False):
436
473
        if names_list is None:
437
474
            names_list = []
438
475
 
439
476
        if len(names_list) < 2:
440
 
            raise BzrCommandError("missing file argument")
 
477
            raise errors.BzrCommandError("missing file argument")
441
478
        tree, rel_names = tree_files(names_list)
442
479
        
443
480
        if os.path.isdir(names_list[-1]):
444
481
            # move into existing directory
445
 
            for pair in tree.move(rel_names[:-1], rel_names[-1]):
 
482
            for pair in tree.move(rel_names[:-1], rel_names[-1], after=after):
446
483
                self.outf.write("%s => %s\n" % pair)
447
484
        else:
448
485
            if len(names_list) != 2:
449
 
                raise BzrCommandError('to mv multiple files the destination '
450
 
                                      'must be a versioned directory')
451
 
            tree.rename_one(rel_names[0], rel_names[1])
 
486
                raise errors.BzrCommandError('to mv multiple files the'
 
487
                                             ' destination must be a versioned'
 
488
                                             ' directory')
 
489
            tree.rename_one(rel_names[0], rel_names[1], after=after)
452
490
            self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
453
491
            
454
492
    
481
519
        try:
482
520
            tree_to = WorkingTree.open_containing(u'.')[0]
483
521
            branch_to = tree_to.branch
484
 
        except NoWorkingTree:
 
522
        except errors.NoWorkingTree:
485
523
            tree_to = None
486
524
            branch_to = Branch.open_containing(u'.')[0]
487
525
 
489
527
        if location is not None:
490
528
            try:
491
529
                reader = bundle.read_bundle_from_url(location)
492
 
            except NotABundle:
 
530
            except errors.NotABundle:
493
531
                pass # Continue on considering this url a Branch
494
532
 
495
533
        stored_loc = branch_to.get_parent()
496
534
        if location is None:
497
535
            if stored_loc is None:
498
 
                raise BzrCommandError("No pull location known or specified.")
 
536
                raise errors.BzrCommandError("No pull location known or"
 
537
                                             " specified.")
499
538
            else:
500
539
                display_url = urlutils.unescape_for_display(stored_loc,
501
540
                        self.outf.encoding)
519
558
        elif len(revision) == 1:
520
559
            rev_id = revision[0].in_history(branch_from).rev_id
521
560
        else:
522
 
            raise BzrCommandError('bzr pull --revision takes one value.')
 
561
            raise errors.BzrCommandError('bzr pull --revision takes one value.')
523
562
 
524
563
        old_rh = branch_to.revision_history()
525
564
        if tree_to is not None:
579
618
        stored_loc = br_from.get_push_location()
580
619
        if location is None:
581
620
            if stored_loc is None:
582
 
                raise BzrCommandError("No push location known or specified.")
 
621
                raise errors.BzrCommandError("No push location known or specified.")
583
622
            else:
584
623
                display_url = urlutils.unescape_for_display(stored_loc,
585
624
                        self.outf.encoding)
593
632
        try:
594
633
            dir_to = bzrdir.BzrDir.open(location_url)
595
634
            br_to = dir_to.open_branch()
596
 
        except NotBranchError:
 
635
        except errors.NotBranchError:
597
636
            # create a branch.
598
637
            to_transport = to_transport.clone('..')
599
638
            if not create_prefix:
601
640
                    relurl = to_transport.relpath(location_url)
602
641
                    mutter('creating directory %s => %s', location_url, relurl)
603
642
                    to_transport.mkdir(relurl)
604
 
                except NoSuchFile:
605
 
                    raise BzrCommandError("Parent directory of %s "
606
 
                                          "does not exist." % location)
 
643
                except errors.NoSuchFile:
 
644
                    raise errors.BzrCommandError("Parent directory of %s "
 
645
                                                 "does not exist." % location)
607
646
            else:
608
647
                current = to_transport.base
609
648
                needed = [(to_transport, to_transport.relpath(location_url))]
612
651
                        to_transport, relpath = needed[-1]
613
652
                        to_transport.mkdir(relpath)
614
653
                        needed.pop()
615
 
                    except NoSuchFile:
 
654
                    except errors.NoSuchFile:
616
655
                        new_transport = to_transport.clone('..')
617
656
                        needed.append((new_transport,
618
657
                                       new_transport.relpath(to_transport.base)))
619
658
                        if new_transport.base == to_transport.base:
620
 
                            raise BzrCommandError("Could not create "
621
 
                                                  "path prefix.")
 
659
                            raise errors.BzrCommandError("Could not create "
 
660
                                                         "path prefix.")
622
661
            dir_to = br_from.bzrdir.clone(location_url,
623
662
                revision_id=br_from.last_revision())
624
663
            br_to = dir_to.open_branch()
638
677
                except errors.NotLocalUrl:
639
678
                    warning('This transport does not update the working '
640
679
                            'tree of: %s' % (br_to.base,))
641
 
                    count = br_to.pull(br_from, overwrite)
642
 
                except NoWorkingTree:
643
 
                    count = br_to.pull(br_from, overwrite)
 
680
                    count = br_from.push(br_to, overwrite)
 
681
                except errors.NoWorkingTree:
 
682
                    count = br_from.push(br_to, overwrite)
644
683
                else:
645
 
                    count = tree_to.pull(br_from, overwrite)
646
 
            except DivergedBranches:
647
 
                raise BzrCommandError("These branches have diverged."
648
 
                                      "  Try a merge then push with overwrite.")
 
684
                    tree_to.lock_write()
 
685
                    try:
 
686
                        count = br_from.push(tree_to.branch, overwrite)
 
687
                        tree_to.update()
 
688
                    finally:
 
689
                        tree_to.unlock()
 
690
            except errors.DivergedBranches:
 
691
                raise errors.BzrCommandError('These branches have diverged.'
 
692
                                        '  Try using "merge" and then "push".')
649
693
        note('%d revision(s) pushed.' % (count,))
650
694
 
651
695
        if verbose:
678
722
        if revision is None:
679
723
            revision = [None]
680
724
        elif len(revision) > 1:
681
 
            raise BzrCommandError(
 
725
            raise errors.BzrCommandError(
682
726
                'bzr branch --revision takes exactly 1 revision value')
683
727
        try:
684
728
            br_from = Branch.open(from_location)
685
729
        except OSError, e:
686
730
            if e.errno == errno.ENOENT:
687
 
                raise BzrCommandError('Source location "%s" does not'
688
 
                                      ' exist.' % to_location)
 
731
                raise errors.BzrCommandError('Source location "%s" does not'
 
732
                                             ' exist.' % to_location)
689
733
            else:
690
734
                raise
691
735
        br_from.lock_read()
711
755
            try:
712
756
                to_transport.mkdir('.')
713
757
            except errors.FileExists:
714
 
                raise BzrCommandError('Target directory "%s" already'
715
 
                                      ' exists.' % to_location)
 
758
                raise errors.BzrCommandError('Target directory "%s" already'
 
759
                                             ' exists.' % to_location)
716
760
            except errors.NoSuchFile:
717
 
                raise BzrCommandError('Parent of "%s" does not exist.' %
718
 
                                      to_location)
 
761
                raise errors.BzrCommandError('Parent of "%s" does not exist.'
 
762
                                             % to_location)
719
763
            try:
720
764
                # preserve whatever source format we have.
721
765
                dir = br_from.bzrdir.sprout(to_transport.base,
724
768
            except errors.NoSuchRevision:
725
769
                to_transport.delete_tree('.')
726
770
                msg = "The branch %s has no revision %s." % (from_location, revision[0])
727
 
                raise BzrCommandError(msg)
 
771
                raise errors.BzrCommandError(msg)
728
772
            except errors.UnlistableBranch:
729
773
                osutils.rmtree(to_location)
730
774
                msg = "The branch %s cannot be used as a --basis" % (basis,)
731
 
                raise BzrCommandError(msg)
 
775
                raise errors.BzrCommandError(msg)
732
776
            if name:
733
777
                branch.control_files.put_utf8('branch-name', name)
734
778
            note('Branched %d revision(s).' % branch.revno())
773
817
        if revision is None:
774
818
            revision = [None]
775
819
        elif len(revision) > 1:
776
 
            raise BzrCommandError(
 
820
            raise errors.BzrCommandError(
777
821
                'bzr checkout --revision takes exactly 1 revision value')
778
822
        if branch_location is None:
779
823
            branch_location = osutils.getcwd()
799
843
            os.mkdir(to_location)
800
844
        except OSError, e:
801
845
            if e.errno == errno.EEXIST:
802
 
                raise BzrCommandError('Target directory "%s" already'
803
 
                                      ' exists.' % to_location)
 
846
                raise errors.BzrCommandError('Target directory "%s" already'
 
847
                                             ' exists.' % to_location)
804
848
            if e.errno == errno.ENOENT:
805
 
                raise BzrCommandError('Parent of "%s" does not exist.' %
806
 
                                      to_location)
 
849
                raise errors.BzrCommandError('Parent of "%s" does not exist.'
 
850
                                             % to_location)
807
851
            else:
808
852
                raise
809
 
        old_format = bzrdir.BzrDirFormat.get_default_format()
810
 
        bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
811
 
        try:
812
 
            source.create_checkout(to_location, revision_id, lightweight)
813
 
        finally:
814
 
            bzrdir.BzrDirFormat.set_default_format(old_format)
 
853
        source.create_checkout(to_location, revision_id, lightweight)
815
854
 
816
855
 
817
856
class cmd_renames(Command):
824
863
 
825
864
    @display_command
826
865
    def run(self, dir=u'.'):
827
 
        from bzrlib.tree import find_renames
828
866
        tree = WorkingTree.open_containing(dir)[0]
829
867
        old_inv = tree.basis_tree().inventory
830
868
        new_inv = tree.read_working_inventory()
831
 
        renames = list(find_renames(old_inv, new_inv))
 
869
        renames = list(_mod_tree.find_renames(old_inv, new_inv))
832
870
        renames.sort()
833
871
        for old_name, new_name in renames:
834
872
            self.outf.write("%s => %s\n" % (old_name, new_name))
849
887
 
850
888
    def run(self, dir='.'):
851
889
        tree = WorkingTree.open_containing(dir)[0]
852
 
        tree.lock_write()
 
890
        master = tree.branch.get_master_branch()
 
891
        if master is not None:
 
892
            tree.lock_write()
 
893
        else:
 
894
            tree.lock_tree_write()
853
895
        try:
854
896
            existing_pending_merges = tree.get_parent_ids()[1:]
855
897
            last_rev = tree.last_revision()
913
955
        tree, file_list = tree_files(file_list)
914
956
        if new is False:
915
957
            if file_list is None:
916
 
                raise BzrCommandError('Specify one or more files to remove, or'
917
 
                                      ' use --new.')
 
958
                raise errors.BzrCommandError('Specify one or more files to'
 
959
                                             ' remove, or use --new.')
918
960
        else:
919
961
            added = tree.changes_from(tree.basis_tree(),
920
962
                specific_files=file_list).added
921
963
            file_list = sorted([f[0] for f in added], reverse=True)
922
964
            if len(file_list) == 0:
923
 
                raise BzrCommandError('No matching files.')
 
965
                raise errors.BzrCommandError('No matching files.')
924
966
        tree.remove(file_list, verbose=verbose, to_file=self.outf)
925
967
 
926
968
 
940
982
        tree, relpath = WorkingTree.open_containing(filename)
941
983
        i = tree.inventory.path2id(relpath)
942
984
        if i is None:
943
 
            raise BzrError("%r is not a versioned file" % filename)
 
985
            raise errors.NotVersionedError(filename)
944
986
        else:
945
987
            self.outf.write(i + '\n')
946
988
 
961
1003
        inv = tree.inventory
962
1004
        fid = inv.path2id(relpath)
963
1005
        if fid is None:
964
 
            raise BzrError("%r is not a versioned file" % filename)
 
1006
            raise errors.NotVersionedError(filename)
965
1007
        for fip in inv.get_idpath(fid):
966
1008
            self.outf.write(fip + '\n')
967
1009
 
1053
1095
    """
1054
1096
    takes_args = ['location?']
1055
1097
    takes_options = [
1056
 
                     Option('format', 
 
1098
                     RegistryOption('format',
1057
1099
                            help='Specify a format for this branch. Current'
1058
1100
                                 ' formats are: default, knit, metaweave and'
1059
1101
                                 ' weave. Default is knit; metaweave and'
1060
1102
                                 ' weave are deprecated',
1061
 
                            type=get_format_type),
 
1103
                            registry=bzrdir.format_registry,
 
1104
                            converter=get_format_type,
 
1105
                            value_switches=True),
1062
1106
                     ]
1063
1107
    def run(self, location=None, format=None):
1064
1108
        if format is None:
1081
1125
                    
1082
1126
        try:
1083
1127
            existing_bzrdir = bzrdir.BzrDir.open(location)
1084
 
        except NotBranchError:
 
1128
        except errors.NotBranchError:
1085
1129
            # really a NotBzrDir error...
1086
1130
            bzrdir.BzrDir.create_branch_convenience(location, format=format)
1087
1131
        else:
 
1132
            from bzrlib.transport.local import LocalTransport
1088
1133
            if existing_bzrdir.has_branch():
1089
1134
                if (isinstance(to_transport, LocalTransport)
1090
1135
                    and not existing_bzrdir.has_workingtree()):
1110
1155
        (add files here)
1111
1156
    """
1112
1157
    takes_args = ["location"] 
1113
 
    takes_options = [Option('format', 
 
1158
    takes_options = [RegistryOption('format',
1114
1159
                            help='Specify a format for this repository.'
1115
1160
                                 ' Current formats are: default, knit,'
1116
1161
                                 ' metaweave and weave. Default is knit;'
1117
1162
                                 ' metaweave and weave are deprecated',
1118
 
                            type=get_format_type),
 
1163
                            registry=bzrdir.format_registry,
 
1164
                            converter=get_format_type,
 
1165
                            value_switches=True),
1119
1166
                     Option('trees',
1120
1167
                             help='Allows branches in repository to have'
1121
1168
                             ' a working tree')]
1171
1218
    #       deleted files.
1172
1219
 
1173
1220
    # TODO: This probably handles non-Unix newlines poorly.
1174
 
    
 
1221
 
1175
1222
    takes_args = ['file*']
1176
 
    takes_options = ['revision', 'diff-options', 'prefix']
 
1223
    takes_options = ['revision', 'diff-options',
 
1224
        Option('prefix', type=str,
 
1225
               short_name='p',
 
1226
               help='Set prefixes to added to old and new filenames, as '
 
1227
                    'two values separated by a colon.'),
 
1228
        ]
1177
1229
    aliases = ['di', 'dif']
1178
1230
    encoding_type = 'exact'
1179
1231
 
1189
1241
        elif prefix == '1':
1190
1242
            old_label = 'old/'
1191
1243
            new_label = 'new/'
1192
 
        else:
1193
 
            if not ':' in prefix:
1194
 
                 raise BzrError("--diff-prefix expects two values separated by a colon")
 
1244
        elif ':' in prefix:
1195
1245
            old_label, new_label = prefix.split(":")
 
1246
        else:
 
1247
            raise BzrCommandError(
 
1248
                "--prefix expects two values separated by a colon")
 
1249
 
 
1250
        if revision and len(revision) > 2:
 
1251
            raise errors.BzrCommandError('bzr diff --revision takes exactly'
 
1252
                                         ' one or two revision specifiers')
1196
1253
        
1197
1254
        try:
1198
1255
            tree1, file_list = internal_tree_files(file_list)
1199
1256
            tree2 = None
1200
1257
            b = None
1201
1258
            b2 = None
1202
 
        except FileInWrongBranch:
 
1259
        except errors.FileInWrongBranch:
1203
1260
            if len(file_list) != 2:
1204
 
                raise BzrCommandError("Files are in different branches")
 
1261
                raise errors.BzrCommandError("Files are in different branches")
1205
1262
 
1206
1263
            tree1, file1 = WorkingTree.open_containing(file_list[0])
1207
1264
            tree2, file2 = WorkingTree.open_containing(file_list[1])
1208
1265
            if file1 != "" or file2 != "":
1209
1266
                # FIXME diff those two files. rbc 20051123
1210
 
                raise BzrCommandError("Files are in different branches")
 
1267
                raise errors.BzrCommandError("Files are in different branches")
1211
1268
            file_list = None
1212
 
        except NotBranchError:
 
1269
        except errors.NotBranchError:
1213
1270
            if (revision is not None and len(revision) == 2
1214
1271
                and not revision[0].needs_branch()
1215
1272
                and not revision[1].needs_branch()):
1218
1275
                tree1, tree2 = None, None
1219
1276
            else:
1220
1277
                raise
1221
 
        if revision is not None:
1222
 
            if tree2 is not None:
1223
 
                raise BzrCommandError("Can't specify -r with two branches")
1224
 
            if (len(revision) == 1) or (revision[1].spec is None):
1225
 
                return diff_cmd_helper(tree1, file_list, diff_options,
1226
 
                                       revision[0], 
1227
 
                                       old_label=old_label, new_label=new_label)
1228
 
            elif len(revision) == 2:
1229
 
                return diff_cmd_helper(tree1, file_list, diff_options,
1230
 
                                       revision[0], revision[1],
1231
 
                                       old_label=old_label, new_label=new_label)
1232
 
            else:
1233
 
                raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
1234
 
        else:
1235
 
            if tree2 is not None:
1236
 
                return show_diff_trees(tree1, tree2, sys.stdout, 
1237
 
                                       specific_files=file_list,
1238
 
                                       external_diff_options=diff_options,
1239
 
                                       old_label=old_label, new_label=new_label)
1240
 
            else:
1241
 
                return diff_cmd_helper(tree1, file_list, diff_options,
1242
 
                                       old_label=old_label, new_label=new_label)
 
1278
 
 
1279
        if tree2 is not None:
 
1280
            if revision is not None:
 
1281
                # FIXME: but there should be a clean way to diff between
 
1282
                # non-default versions of two trees, it's not hard to do
 
1283
                # internally...
 
1284
                raise errors.BzrCommandError(
 
1285
                        "Sorry, diffing arbitrary revisions across branches "
 
1286
                        "is not implemented yet")
 
1287
            return show_diff_trees(tree1, tree2, sys.stdout, 
 
1288
                                   specific_files=file_list,
 
1289
                                   external_diff_options=diff_options,
 
1290
                                   old_label=old_label, new_label=new_label)
 
1291
 
 
1292
        return diff_cmd_helper(tree1, file_list, diff_options,
 
1293
                               revision_specs=revision,
 
1294
                               old_label=old_label, new_label=new_label)
1243
1295
 
1244
1296
 
1245
1297
class cmd_deleted(Command):
1288
1340
        for file_id in inv:
1289
1341
            if file_id in basis_inv:
1290
1342
                continue
 
1343
            if inv.is_root(file_id) and len(basis_inv) == 0:
 
1344
                continue
1291
1345
            path = inv.id2path(file_id)
1292
1346
            if not os.access(osutils.abspath(path), os.F_OK):
1293
1347
                continue
1329
1383
                            help='show from oldest to newest'),
1330
1384
                     'timezone', 
1331
1385
                     Option('verbose', 
 
1386
                             short_name='v',
1332
1387
                             help='show files changed in each revision'),
1333
1388
                     'show-ids', 'revision',
1334
1389
                     'log-format',
1335
1390
                     'line', 'long', 
1336
1391
                     Option('message',
 
1392
                            short_name='m',
1337
1393
                            help='show revisions whose message matches this regexp',
1338
1394
                            type=str),
1339
1395
                     'short',
1371
1427
                    # either no tree, or is remote.
1372
1428
                    inv = b.basis_tree().inventory
1373
1429
                file_id = inv.path2id(fp)
 
1430
                if file_id is None:
 
1431
                    raise errors.BzrCommandError(
 
1432
                        "Path does not have any revision history: %s" %
 
1433
                        location)
1374
1434
        else:
1375
1435
            # local dir only
1376
1436
            # FIXME ? log the current subdir only RBC 20060203 
1392
1452
                # b is taken from revision[0].get_branch(), and
1393
1453
                # show_log will use its revision_history. Having
1394
1454
                # different branches will lead to weird behaviors.
1395
 
                raise BzrCommandError(
 
1455
                raise errors.BzrCommandError(
1396
1456
                    "Log doesn't accept two revisions in different branches.")
1397
1457
            if revision[0].spec is None:
1398
1458
                # missing begin-range means first revision
1406
1466
            else:
1407
1467
                rev2 = revision[1].in_history(b).revno
1408
1468
        else:
1409
 
            raise BzrCommandError('bzr log --revision takes one or two values.')
 
1469
            raise errors.BzrCommandError('bzr log --revision takes one or two values.')
1410
1470
 
1411
1471
        # By this point, the revision numbers are converted to the +ve
1412
1472
        # form if they were supplied in the -ve form, so we can do
1466
1526
class cmd_ls(Command):
1467
1527
    """List files in a tree.
1468
1528
    """
 
1529
 
 
1530
    takes_args = ['path?']
1469
1531
    # TODO: Take a revision or remote path and list that tree instead.
1470
 
    hidden = True
1471
1532
    takes_options = ['verbose', 'revision',
1472
1533
                     Option('non-recursive',
1473
1534
                            help='don\'t recurse into sub-directories'),
1478
1539
                     Option('ignored', help='Print ignored files'),
1479
1540
 
1480
1541
                     Option('null', help='Null separate the files'),
 
1542
                     'kind', 'show-ids'
1481
1543
                    ]
1482
1544
    @display_command
1483
1545
    def run(self, revision=None, verbose=False, 
1484
1546
            non_recursive=False, from_root=False,
1485
1547
            unknown=False, versioned=False, ignored=False,
1486
 
            null=False):
 
1548
            null=False, kind=None, show_ids=False, path=None):
 
1549
 
 
1550
        if kind and kind not in ('file', 'directory', 'symlink'):
 
1551
            raise errors.BzrCommandError('invalid kind specified')
1487
1552
 
1488
1553
        if verbose and null:
1489
 
            raise BzrCommandError('Cannot set both --verbose and --null')
 
1554
            raise errors.BzrCommandError('Cannot set both --verbose and --null')
1490
1555
        all = not (unknown or versioned or ignored)
1491
1556
 
1492
1557
        selection = {'I':ignored, '?':unknown, 'V':versioned}
1493
1558
 
1494
 
        tree, relpath = WorkingTree.open_containing(u'.')
 
1559
        if path is None:
 
1560
            fs_path = '.'
 
1561
            prefix = ''
 
1562
        else:
 
1563
            if from_root:
 
1564
                raise errors.BzrCommandError('cannot specify both --from-root'
 
1565
                                             ' and PATH')
 
1566
            fs_path = path
 
1567
            prefix = path
 
1568
        tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
 
1569
            fs_path)
1495
1570
        if from_root:
1496
1571
            relpath = u''
1497
1572
        elif relpath:
1498
1573
            relpath += '/'
1499
1574
        if revision is not None:
1500
 
            tree = tree.branch.repository.revision_tree(
1501
 
                revision[0].in_history(tree.branch).rev_id)
 
1575
            tree = branch.repository.revision_tree(
 
1576
                revision[0].in_history(branch).rev_id)
 
1577
        elif tree is None:
 
1578
            tree = branch.basis_tree()
1502
1579
 
1503
 
        for fp, fc, kind, fid, entry in tree.list_files():
 
1580
        for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
1504
1581
            if fp.startswith(relpath):
1505
 
                fp = fp[len(relpath):]
 
1582
                fp = osutils.pathjoin(prefix, fp[len(relpath):])
1506
1583
                if non_recursive and '/' in fp:
1507
1584
                    continue
1508
1585
                if not all and not selection[fc]:
1509
1586
                    continue
 
1587
                if kind is not None and fkind != kind:
 
1588
                    continue
1510
1589
                if verbose:
1511
1590
                    kindch = entry.kind_character()
1512
 
                    self.outf.write('%-8s %s%s\n' % (fc, fp, kindch))
 
1591
                    outstring = '%-8s %s%s' % (fc, fp, kindch)
 
1592
                    if show_ids and fid is not None:
 
1593
                        outstring = "%-50s %s" % (outstring, fid)
 
1594
                    self.outf.write(outstring + '\n')
1513
1595
                elif null:
1514
1596
                    self.outf.write(fp + '\0')
 
1597
                    if show_ids:
 
1598
                        if fid is not None:
 
1599
                            self.outf.write(fid)
 
1600
                        self.outf.write('\0')
1515
1601
                    self.outf.flush()
1516
1602
                else:
1517
 
                    self.outf.write(fp + '\n')
 
1603
                    if fid is not None:
 
1604
                        my_id = fid
 
1605
                    else:
 
1606
                        my_id = ''
 
1607
                    if show_ids:
 
1608
                        self.outf.write('%-50s %s\n' % (fp, my_id))
 
1609
                    else:
 
1610
                        self.outf.write(fp + '\n')
1518
1611
 
1519
1612
 
1520
1613
class cmd_unknowns(Command):
1526
1619
 
1527
1620
 
1528
1621
class cmd_ignore(Command):
1529
 
    """Ignore a command or pattern.
 
1622
    """Ignore specified files or patterns.
1530
1623
 
1531
1624
    To remove patterns from the ignore list, edit the .bzrignore file.
1532
1625
 
1533
 
    If the pattern contains a slash, it is compared to the whole path
1534
 
    from the branch root.  Otherwise, it is compared to only the last
1535
 
    component of the path.  To match a file only in the root directory,
1536
 
    prepend './'.
1537
 
 
1538
 
    Ignore patterns are case-insensitive on case-insensitive systems.
1539
 
 
1540
 
    Note: wildcards must be quoted from the shell on Unix.
 
1626
    Trailing slashes on patterns are ignored. 
 
1627
    If the pattern contains a slash or is a regular expression, it is compared 
 
1628
    to the whole path from the branch root.  Otherwise, it is compared to only
 
1629
    the last component of the path.  To match a file only in the root 
 
1630
    directory, prepend './'.
 
1631
 
 
1632
    Ignore patterns specifying absolute paths are not allowed.
 
1633
 
 
1634
    Ignore patterns may include globbing wildcards such as:
 
1635
      ? - Matches any single character except '/'
 
1636
      * - Matches 0 or more characters except '/'
 
1637
      /**/ - Matches 0 or more directories in a path
 
1638
      [a-z] - Matches a single character from within a group of characters
 
1639
 
 
1640
    Ignore patterns may also be Python regular expressions.  
 
1641
    Regular expression ignore patterns are identified by a 'RE:' prefix 
 
1642
    followed by the regular expression.  Regular expression ignore patterns
 
1643
    may not include named or numbered groups.
 
1644
 
 
1645
    Note: ignore patterns containing shell wildcards must be quoted from 
 
1646
    the shell on Unix.
1541
1647
 
1542
1648
    examples:
1543
1649
        bzr ignore ./Makefile
1544
1650
        bzr ignore '*.class'
 
1651
        bzr ignore 'lib/**/*.o'
 
1652
        bzr ignore 'RE:lib/.*\.o'
1545
1653
    """
1546
 
    # TODO: Complain if the filename is absolute
1547
 
    takes_args = ['name_pattern?']
 
1654
    takes_args = ['name_pattern*']
1548
1655
    takes_options = [
1549
1656
                     Option('old-default-rules',
1550
1657
                            help='Out the ignore rules bzr < 0.9 always used.')
1551
1658
                     ]
1552
1659
    
1553
 
    def run(self, name_pattern=None, old_default_rules=None):
 
1660
    def run(self, name_pattern_list=None, old_default_rules=None):
1554
1661
        from bzrlib.atomicfile import AtomicFile
1555
1662
        if old_default_rules is not None:
1556
1663
            # dump the rules and exit
1557
1664
            for pattern in ignores.OLD_DEFAULTS:
1558
1665
                print pattern
1559
1666
            return
1560
 
        if name_pattern is None:
1561
 
            raise BzrCommandError("ignore requires a NAME_PATTERN")
 
1667
        if not name_pattern_list:
 
1668
            raise errors.BzrCommandError("ignore requires at least one "
 
1669
                                  "NAME_PATTERN or --old-default-rules")
 
1670
        for name_pattern in name_pattern_list:
 
1671
            if name_pattern[0] == '/':
 
1672
                raise errors.BzrCommandError(
 
1673
                    "NAME_PATTERN should not be an absolute path")
1562
1674
        tree, relpath = WorkingTree.open_containing(u'.')
1563
1675
        ifn = tree.abspath('.bzrignore')
1564
1676
        if os.path.exists(ifn):
1575
1687
 
1576
1688
        if igns and igns[-1] != '\n':
1577
1689
            igns += '\n'
1578
 
        igns += name_pattern + '\n'
 
1690
        for name_pattern in name_pattern_list:
 
1691
            igns += name_pattern.rstrip('/') + '\n'
1579
1692
 
1580
 
        f = AtomicFile(ifn, 'wt')
 
1693
        f = AtomicFile(ifn, 'wb')
1581
1694
        try:
1582
1695
            f.write(igns.encode('utf-8'))
1583
1696
            f.commit()
1621
1734
        try:
1622
1735
            revno = int(revno)
1623
1736
        except ValueError:
1624
 
            raise BzrCommandError("not a valid revision-number: %r" % revno)
 
1737
            raise errors.BzrCommandError("not a valid revision-number: %r" % revno)
1625
1738
 
1626
1739
        print WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
1627
1740
 
1638
1751
    Root may be the top directory for tar, tgz and tbz2 formats. If none
1639
1752
    is given, the top directory will be the root name of the file.
1640
1753
 
 
1754
    If branch is omitted then the branch containing the CWD will be used.
 
1755
 
1641
1756
    Note: export of tree with non-ascii filenames to zip is not supported.
1642
1757
 
1643
1758
     Supported formats       Autodetected by extension
1648
1763
         tgz                      .tar.gz, .tgz
1649
1764
         zip                          .zip
1650
1765
    """
1651
 
    takes_args = ['dest']
 
1766
    takes_args = ['dest', 'branch?']
1652
1767
    takes_options = ['revision', 'format', 'root']
1653
 
    def run(self, dest, revision=None, format=None, root=None):
 
1768
    def run(self, dest, branch=None, revision=None, format=None, root=None):
1654
1769
        from bzrlib.export import export
1655
 
        tree = WorkingTree.open_containing(u'.')[0]
1656
 
        b = tree.branch
 
1770
 
 
1771
        if branch is None:
 
1772
            tree = WorkingTree.open_containing(u'.')[0]
 
1773
            b = tree.branch
 
1774
        else:
 
1775
            b = Branch.open(branch)
 
1776
            
1657
1777
        if revision is None:
1658
1778
            # should be tree.last_revision  FIXME
1659
1779
            rev_id = b.last_revision()
1660
1780
        else:
1661
1781
            if len(revision) != 1:
1662
 
                raise BzrError('bzr export --revision takes exactly 1 argument')
 
1782
                raise errors.BzrCommandError('bzr export --revision takes exactly 1 argument')
1663
1783
            rev_id = revision[0].in_history(b).rev_id
1664
1784
        t = b.repository.revision_tree(rev_id)
1665
1785
        try:
1666
1786
            export(t, dest, format, root)
1667
1787
        except errors.NoSuchExportFormat, e:
1668
 
            raise BzrCommandError('Unsupported export format: %s' % e.format)
 
1788
            raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
1669
1789
 
1670
1790
 
1671
1791
class cmd_cat(Command):
1672
1792
    """Write a file's text from a previous revision."""
1673
1793
 
1674
 
    takes_options = ['revision']
 
1794
    takes_options = ['revision', 'name-from-revision']
1675
1795
    takes_args = ['filename']
 
1796
    encoding_type = 'exact'
1676
1797
 
1677
1798
    @display_command
1678
 
    def run(self, filename, revision=None):
 
1799
    def run(self, filename, revision=None, name_from_revision=False):
1679
1800
        if revision is not None and len(revision) != 1:
1680
 
            raise BzrCommandError("bzr cat --revision takes exactly one number")
 
1801
            raise errors.BzrCommandError("bzr cat --revision takes exactly"
 
1802
                                        " one number")
 
1803
 
1681
1804
        tree = None
1682
1805
        try:
1683
1806
            tree, relpath = WorkingTree.open_containing(filename)
1684
1807
            b = tree.branch
1685
 
        except NotBranchError:
 
1808
        except (errors.NotBranchError, errors.NotLocalUrl):
1686
1809
            pass
1687
1810
 
 
1811
        if revision is not None and revision[0].get_branch() is not None:
 
1812
            b = Branch.open(revision[0].get_branch())
1688
1813
        if tree is None:
1689
1814
            b, relpath = Branch.open_containing(filename)
1690
 
        if revision is not None and revision[0].get_branch() is not None:
1691
 
            b = Branch.open(revision[0].get_branch())
 
1815
            tree = b.basis_tree()
1692
1816
        if revision is None:
1693
1817
            revision_id = b.last_revision()
1694
1818
        else:
1695
1819
            revision_id = revision[0].in_history(b).rev_id
1696
 
        b.print_file(relpath, revision_id)
 
1820
 
 
1821
        cur_file_id = tree.path2id(relpath)
 
1822
        rev_tree = b.repository.revision_tree(revision_id)
 
1823
        old_file_id = rev_tree.path2id(relpath)
 
1824
        
 
1825
        if name_from_revision:
 
1826
            if old_file_id is None:
 
1827
                raise errors.BzrCommandError("%r is not present in revision %s"
 
1828
                                                % (filename, revision_id))
 
1829
            else:
 
1830
                rev_tree.print_file(old_file_id)
 
1831
        elif cur_file_id is not None:
 
1832
            rev_tree.print_file(cur_file_id)
 
1833
        elif old_file_id is not None:
 
1834
            rev_tree.print_file(old_file_id)
 
1835
        else:
 
1836
            raise errors.BzrCommandError("%r is not present in revision %s" %
 
1837
                                         (filename, revision_id))
1697
1838
 
1698
1839
 
1699
1840
class cmd_local_time_offset(Command):
1732
1873
                     Option('unchanged',
1733
1874
                            help='commit even if nothing has changed'),
1734
1875
                     Option('file', type=str, 
 
1876
                            short_name='F',
1735
1877
                            argname='msgfile',
1736
1878
                            help='file containing commit message'),
1737
1879
                     Option('strict',
1753
1895
                StrictCommitFailed)
1754
1896
        from bzrlib.msgeditor import edit_commit_message, \
1755
1897
                make_commit_message_template
1756
 
        from tempfile import TemporaryFile
1757
1898
 
1758
1899
        # TODO: Need a blackbox test for invoking the external editor; may be
1759
1900
        # slightly problematic to run this cross-platform.
1760
1901
 
1761
1902
        # TODO: do more checks that the commit will succeed before 
1762
1903
        # spending the user's valuable time typing a commit message.
1763
 
        #
1764
 
        # TODO: if the commit *does* happen to fail, then save the commit 
1765
 
        # message to a temporary file where it can be recovered
1766
1904
        tree, selected_list = tree_files(selected_list)
1767
1905
        if selected_list == ['']:
1768
1906
            # workaround - commit of root of tree should be exactly the same
1772
1910
 
1773
1911
        if local and not tree.branch.get_bound_location():
1774
1912
            raise errors.LocalRequiresBoundBranch()
1775
 
        if message is None and not file:
1776
 
            template = make_commit_message_template(tree, selected_list)
1777
 
            message = edit_commit_message(template)
1778
 
            if message is None:
1779
 
                raise BzrCommandError("please specify a commit message"
1780
 
                                      " with either --message or --file")
1781
 
        elif message and file:
1782
 
            raise BzrCommandError("please specify either --message or --file")
1783
 
        
1784
 
        if file:
1785
 
            message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1786
1913
 
1787
 
        if message == "":
1788
 
            raise BzrCommandError("empty commit message specified")
 
1914
        def get_message(commit_obj):
 
1915
            """Callback to get commit message"""
 
1916
            my_message = message
 
1917
            if my_message is None and not file:
 
1918
                template = make_commit_message_template(tree, selected_list)
 
1919
                my_message = edit_commit_message(template)
 
1920
                if my_message is None:
 
1921
                    raise errors.BzrCommandError("please specify a commit"
 
1922
                        " message with either --message or --file")
 
1923
            elif my_message and file:
 
1924
                raise errors.BzrCommandError(
 
1925
                    "please specify either --message or --file")
 
1926
            if file:
 
1927
                my_message = codecs.open(file, 'rt', 
 
1928
                                         bzrlib.user_encoding).read()
 
1929
            if my_message == "":
 
1930
                raise errors.BzrCommandError("empty commit message specified")
 
1931
            return my_message
1789
1932
        
1790
1933
        if verbose:
1791
1934
            reporter = ReportCommitToLog()
1792
1935
        else:
1793
1936
            reporter = NullCommitReporter()
1794
 
        
 
1937
 
1795
1938
        try:
1796
 
            tree.commit(message, specific_files=selected_list,
 
1939
            tree.commit(message_callback=get_message,
 
1940
                        specific_files=selected_list,
1797
1941
                        allow_pointless=unchanged, strict=strict, local=local,
1798
1942
                        reporter=reporter)
1799
1943
        except PointlessCommit:
1800
1944
            # FIXME: This should really happen before the file is read in;
1801
1945
            # perhaps prepare the commit; get the message; then actually commit
1802
 
            raise BzrCommandError("no changes to commit."
1803
 
                                  " use --unchanged to commit anyhow")
 
1946
            raise errors.BzrCommandError("no changes to commit."
 
1947
                              " use --unchanged to commit anyhow")
1804
1948
        except ConflictsInTree:
1805
 
            raise BzrCommandError("Conflicts detected in working tree.  "
1806
 
                'Use "bzr conflicts" to list, "bzr resolve FILE" to resolve.')
 
1949
            raise errors.BzrCommandError('Conflicts detected in working '
 
1950
                'tree.  Use "bzr conflicts" to list, "bzr resolve FILE" to'
 
1951
                ' resolve.')
1807
1952
        except StrictCommitFailed:
1808
 
            raise BzrCommandError("Commit refused because there are unknown "
1809
 
                                  "files in the working tree.")
 
1953
            raise errors.BzrCommandError("Commit refused because there are"
 
1954
                              " unknown files in the working tree.")
1810
1955
        except errors.BoundBranchOutOfDate, e:
1811
 
            raise BzrCommandError(str(e) + "\n"
1812
 
                'To commit to master branch, run update and then commit.\n'
1813
 
                'You can also pass --local to commit to continue working '
1814
 
                'disconnected.')
 
1956
            raise errors.BzrCommandError(str(e) + "\n"
 
1957
            'To commit to master branch, run update and then commit.\n'
 
1958
            'You can also pass --local to commit to continue working '
 
1959
            'disconnected.')
 
1960
 
1815
1961
 
1816
1962
class cmd_check(Command):
1817
1963
    """Validate consistency of branch history.
1832
1978
        check(branch, verbose)
1833
1979
 
1834
1980
 
1835
 
class cmd_scan_cache(Command):
1836
 
    hidden = True
1837
 
    def run(self):
1838
 
        from bzrlib.hashcache import HashCache
1839
 
 
1840
 
        c = HashCache(u'.')
1841
 
        c.read()
1842
 
        c.scan()
1843
 
            
1844
 
        print '%6d stats' % c.stat_count
1845
 
        print '%6d in hashcache' % len(c._cache)
1846
 
        print '%6d files removed from cache' % c.removed_count
1847
 
        print '%6d hashes updated' % c.update_count
1848
 
        print '%6d files changed too recently to cache' % c.danger_count
1849
 
 
1850
 
        if c.needs_write:
1851
 
            c.write()
1852
 
 
1853
 
 
1854
1981
class cmd_upgrade(Command):
1855
1982
    """Upgrade branch storage to current format.
1856
1983
 
1860
1987
    """
1861
1988
    takes_args = ['url?']
1862
1989
    takes_options = [
1863
 
                     Option('format', 
1864
 
                            help='Upgrade to a specific format. Current formats'
1865
 
                                 ' are: default, knit, metaweave and weave.'
1866
 
                                 ' Default is knit; metaweave and weave are'
1867
 
                                 ' deprecated',
1868
 
                            type=get_format_type),
 
1990
                    RegistryOption('format',
 
1991
                        help='Upgrade to a specific format. Current formats'
 
1992
                             ' are: default, knit, metaweave and weave.'
 
1993
                             ' Default is knit; metaweave and weave are'
 
1994
                             ' deprecated',
 
1995
                        registry=bzrdir.format_registry,
 
1996
                        converter=get_format_type,
 
1997
                        value_switches=True),
1869
1998
                    ]
1870
1999
 
1871
2000
 
1898
2027
            # use branch if we're inside one; otherwise global config
1899
2028
            try:
1900
2029
                c = Branch.open_containing('.')[0].get_config()
1901
 
            except NotBranchError:
 
2030
            except errors.NotBranchError:
1902
2031
                c = config.GlobalConfig()
1903
2032
            if email:
1904
2033
                self.outf.write(c.user_email() + '\n')
1943
2072
class cmd_selftest(Command):
1944
2073
    """Run internal test suite.
1945
2074
    
1946
 
    This creates temporary test directories in the working directory,
1947
 
    but not existing data is affected.  These directories are deleted
1948
 
    if the tests pass, or left behind to help in debugging if they
1949
 
    fail and --keep-output is specified.
 
2075
    This creates temporary test directories in the working directory, but not
 
2076
    existing data is affected.  These directories are deleted if the tests
 
2077
    pass, or left behind to help in debugging if they fail and --keep-output
 
2078
    is specified.
1950
2079
    
1951
 
    If arguments are given, they are regular expressions that say
1952
 
    which tests should run.
 
2080
    If arguments are given, they are regular expressions that say which tests
 
2081
    should run.  Tests matching any expression are run, and other tests are
 
2082
    not run.
 
2083
 
 
2084
    Alternatively if --first is given, matching tests are run first and then
 
2085
    all other tests are run.  This is useful if you have been working in a
 
2086
    particular area, but want to make sure nothing else was broken.
1953
2087
 
1954
2088
    If the global option '--no-plugins' is given, plugins are not loaded
1955
2089
    before running the selftests.  This has two effects: features provided or
1956
2090
    modified by plugins will not be tested, and tests provided by plugins will
1957
2091
    not be run.
1958
2092
 
1959
 
    examples:
 
2093
    examples::
1960
2094
        bzr selftest ignore
 
2095
            run only tests relating to 'ignore'
1961
2096
        bzr --no-plugins selftest -v
 
2097
            disable plugins and list tests as they're run
1962
2098
    """
1963
2099
    # TODO: --list should give a list of all available tests
1964
2100
 
1977
2113
            return FakeNFSServer
1978
2114
        msg = "No known transport type %s. Supported types are: sftp\n" %\
1979
2115
            (typestring)
1980
 
        raise BzrCommandError(msg)
 
2116
        raise errors.BzrCommandError(msg)
1981
2117
 
1982
2118
    hidden = True
1983
2119
    takes_args = ['testspecs*']
1996
2132
                     Option('cache-dir', type=str,
1997
2133
                            help='a directory to cache intermediate'
1998
2134
                                 ' benchmark steps'),
 
2135
                     Option('clean-output',
 
2136
                            help='clean temporary tests directories'
 
2137
                                 ' without running tests'),
 
2138
                     Option('first',
 
2139
                            help='run all tests, but run specified tests first',
 
2140
                            )
1999
2141
                     ]
 
2142
    encoding_type = 'replace'
2000
2143
 
2001
2144
    def run(self, testspecs_list=None, verbose=None, one=False,
2002
2145
            keep_output=False, transport=None, benchmark=None,
2003
 
            lsprof_timed=None, cache_dir=None):
 
2146
            lsprof_timed=None, cache_dir=None, clean_output=False,
 
2147
            first=False):
2004
2148
        import bzrlib.ui
2005
2149
        from bzrlib.tests import selftest
2006
2150
        import bzrlib.benchmarks as benchmarks
2007
2151
        from bzrlib.benchmarks import tree_creator
2008
2152
 
 
2153
        if clean_output:
 
2154
            from bzrlib.tests import clean_selftest_output
 
2155
            clean_selftest_output()
 
2156
            return 0
 
2157
 
2009
2158
        if cache_dir is not None:
2010
2159
            tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
2011
 
        # we don't want progress meters from the tests to go to the
2012
 
        # real output; and we don't want log messages cluttering up
2013
 
        # the real logs.
2014
 
        save_ui = ui.ui_factory
2015
2160
        print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
2016
2161
        print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
2017
2162
        print
2018
 
        info('running tests...')
 
2163
        if testspecs_list is not None:
 
2164
            pattern = '|'.join(testspecs_list)
 
2165
        else:
 
2166
            pattern = ".*"
 
2167
        if benchmark:
 
2168
            test_suite_factory = benchmarks.test_suite
 
2169
            if verbose is None:
 
2170
                verbose = True
 
2171
            # TODO: should possibly lock the history file...
 
2172
            benchfile = open(".perf_history", "at", buffering=1)
 
2173
        else:
 
2174
            test_suite_factory = None
 
2175
            if verbose is None:
 
2176
                verbose = False
 
2177
            benchfile = None
2019
2178
        try:
2020
 
            ui.ui_factory = ui.SilentUIFactory()
2021
 
            if testspecs_list is not None:
2022
 
                pattern = '|'.join(testspecs_list)
2023
 
            else:
2024
 
                pattern = ".*"
2025
 
            if benchmark:
2026
 
                test_suite_factory = benchmarks.test_suite
2027
 
                if verbose is None:
2028
 
                    verbose = True
2029
 
                # TODO: should possibly lock the history file...
2030
 
                benchfile = open(".perf_history", "at")
2031
 
            else:
2032
 
                test_suite_factory = None
2033
 
                if verbose is None:
2034
 
                    verbose = False
2035
 
                benchfile = None
2036
 
            try:
2037
 
                result = selftest(verbose=verbose, 
2038
 
                                  pattern=pattern,
2039
 
                                  stop_on_failure=one, 
2040
 
                                  keep_output=keep_output,
2041
 
                                  transport=transport,
2042
 
                                  test_suite_factory=test_suite_factory,
2043
 
                                  lsprof_timed=lsprof_timed,
2044
 
                                  bench_history=benchfile)
2045
 
            finally:
2046
 
                if benchfile is not None:
2047
 
                    benchfile.close()
2048
 
            if result:
2049
 
                info('tests passed')
2050
 
            else:
2051
 
                info('tests failed')
2052
 
            return int(not result)
 
2179
            result = selftest(verbose=verbose, 
 
2180
                              pattern=pattern,
 
2181
                              stop_on_failure=one, 
 
2182
                              keep_output=keep_output,
 
2183
                              transport=transport,
 
2184
                              test_suite_factory=test_suite_factory,
 
2185
                              lsprof_timed=lsprof_timed,
 
2186
                              bench_history=benchfile,
 
2187
                              matching_tests_first=first,
 
2188
                              )
2053
2189
        finally:
2054
 
            ui.ui_factory = save_ui
 
2190
            if benchfile is not None:
 
2191
                benchfile.close()
 
2192
        if result:
 
2193
            info('tests passed')
 
2194
        else:
 
2195
            info('tests failed')
 
2196
        return int(not result)
2055
2197
 
2056
2198
 
2057
2199
class cmd_version(Command):
2082
2224
    
2083
2225
    @display_command
2084
2226
    def run(self, branch, other):
2085
 
        from bzrlib.revision import common_ancestor, MultipleRevisionSources
 
2227
        from bzrlib.revision import MultipleRevisionSources
2086
2228
        
2087
2229
        branch1 = Branch.open_containing(branch)[0]
2088
2230
        branch2 = Branch.open_containing(other)[0]
2145
2287
    takes_args = ['branch?']
2146
2288
    takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
2147
2289
                     Option('show-base', help="Show base revision text in "
2148
 
                            "conflicts"), 
 
2290
                            "conflicts"),
2149
2291
                     Option('uncommitted', help='Apply uncommitted changes'
2150
 
                            ' from a working copy, instead of branch changes')]
 
2292
                            ' from a working copy, instead of branch changes'),
 
2293
                     Option('pull', help='If the destination is already'
 
2294
                             ' completely merged into the source, pull from the'
 
2295
                             ' source rather than merging. When this happens,'
 
2296
                             ' you do not need to commit the result.'),
 
2297
                     ]
2151
2298
 
2152
2299
    def help(self):
2153
 
        from merge import merge_type_help
2154
2300
        from inspect import getdoc
2155
 
        return getdoc(self) + '\n' + merge_type_help() 
 
2301
        return getdoc(self) + '\n' + _mod_merge.merge_type_help()
2156
2302
 
2157
2303
    def run(self, branch=None, revision=None, force=False, merge_type=None,
2158
2304
            show_base=False, reprocess=False, remember=False, 
2159
 
            uncommitted=False):
 
2305
            uncommitted=False, pull=False):
2160
2306
        if merge_type is None:
2161
 
            merge_type = Merge3Merger
 
2307
            merge_type = _mod_merge.Merge3Merger
2162
2308
 
2163
2309
        tree = WorkingTree.open_containing(u'.')[0]
2164
2310
 
2165
2311
        if branch is not None:
2166
2312
            try:
2167
2313
                reader = bundle.read_bundle_from_url(branch)
2168
 
            except NotABundle:
 
2314
            except errors.NotABundle:
2169
2315
                pass # Continue on considering this url a Branch
2170
2316
            else:
2171
2317
                conflicts = merge_bundle(reader, tree, not force, merge_type,
2189
2335
            other_branch, path = Branch.open_containing(branch)
2190
2336
        else:
2191
2337
            if uncommitted:
2192
 
                raise BzrCommandError('Cannot use --uncommitted and --revision'
2193
 
                                      ' at the same time.')
 
2338
                raise errors.BzrCommandError('Cannot use --uncommitted and'
 
2339
                                             ' --revision at the same time.')
2194
2340
            branch = revision[0].get_branch() or branch
2195
2341
            if len(revision) == 1:
2196
2342
                base = [None, None]
2200
2346
            else:
2201
2347
                assert len(revision) == 2
2202
2348
                if None in revision:
2203
 
                    raise BzrCommandError(
 
2349
                    raise errors.BzrCommandError(
2204
2350
                        "Merge doesn't permit empty revision specifier.")
2205
2351
                base_branch, path = Branch.open_containing(branch)
2206
2352
                branch1 = revision[1].get_branch() or branch
2222
2368
        pb = ui.ui_factory.nested_progress_bar()
2223
2369
        try:
2224
2370
            try:
2225
 
                conflict_count = merge(other, base, check_clean=(not force),
2226
 
                                       merge_type=merge_type,
2227
 
                                       reprocess=reprocess,
2228
 
                                       show_base=show_base,
2229
 
                                       pb=pb, file_list=interesting_files)
 
2371
                conflict_count = _merge_helper(
 
2372
                    other, base, check_clean=(not force),
 
2373
                    merge_type=merge_type,
 
2374
                    reprocess=reprocess,
 
2375
                    show_base=show_base,
 
2376
                    pull=pull,
 
2377
                    pb=pb, file_list=interesting_files)
2230
2378
            finally:
2231
2379
                pb.finished()
2232
2380
            if conflict_count != 0:
2253
2401
        stored_location = tree.branch.get_parent()
2254
2402
        mutter("%s", stored_location)
2255
2403
        if stored_location is None:
2256
 
            raise BzrCommandError("No location specified or remembered")
 
2404
            raise errors.BzrCommandError("No location specified or remembered")
2257
2405
        display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
2258
2406
        self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
2259
2407
        return stored_location
2286
2434
                            "conflicts")]
2287
2435
 
2288
2436
    def help(self):
2289
 
        from merge import merge_type_help
2290
2437
        from inspect import getdoc
2291
 
        return getdoc(self) + '\n' + merge_type_help() 
 
2438
        return getdoc(self) + '\n' + _mod_merge.merge_type_help()
2292
2439
 
2293
2440
    def run(self, file_list=None, merge_type=None, show_base=False,
2294
2441
            reprocess=False):
2295
 
        from bzrlib.merge import merge_inner, transform_tree
2296
2442
        if merge_type is None:
2297
 
            merge_type = Merge3Merger
 
2443
            merge_type = _mod_merge.Merge3Merger
2298
2444
        tree, file_list = tree_files(file_list)
2299
2445
        tree.lock_write()
2300
2446
        try:
2301
2447
            parents = tree.get_parent_ids()
2302
2448
            if len(parents) != 2:
2303
 
                raise BzrCommandError("Sorry, remerge only works after normal"
2304
 
                                      " merges.  Not cherrypicking or"
2305
 
                                      " multi-merges.")
 
2449
                raise errors.BzrCommandError("Sorry, remerge only works after normal"
 
2450
                                             " merges.  Not cherrypicking or"
 
2451
                                             " multi-merges.")
2306
2452
            repository = tree.branch.repository
2307
2453
            base_revision = common_ancestor(parents[0],
2308
2454
                                            parents[1], repository)
2316
2462
                for filename in file_list:
2317
2463
                    file_id = tree.path2id(filename)
2318
2464
                    if file_id is None:
2319
 
                        raise NotVersionedError(filename)
 
2465
                        raise errors.NotVersionedError(filename)
2320
2466
                    interesting_ids.add(file_id)
2321
2467
                    if tree.kind(file_id) != "directory":
2322
2468
                        continue
2324
2470
                    for name, ie in tree.inventory.iter_entries(file_id):
2325
2471
                        interesting_ids.add(ie.file_id)
2326
2472
                new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
2327
 
            transform_tree(tree, tree.basis_tree(), interesting_ids)
 
2473
            else:
 
2474
                # Remerge only supports resolving contents conflicts
 
2475
                allowed_conflicts = ('text conflict', 'contents conflict')
 
2476
                restore_files = [c.path for c in conflicts
 
2477
                                 if c.typestring in allowed_conflicts]
 
2478
            _mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
2328
2479
            tree.set_conflicts(ConflictList(new_conflicts))
2329
 
            if file_list is None:
2330
 
                restore_files = list(tree.iter_conflicts())
2331
 
            else:
 
2480
            if file_list is not None:
2332
2481
                restore_files = file_list
2333
2482
            for filename in restore_files:
2334
2483
                try:
2335
2484
                    restore(tree.abspath(filename))
2336
 
                except NotConflicted:
 
2485
                except errors.NotConflicted:
2337
2486
                    pass
2338
 
            conflicts = merge_inner(tree.branch, other_tree, base_tree,
2339
 
                                    this_tree=tree,
2340
 
                                    interesting_ids=interesting_ids,
2341
 
                                    other_rev_id=parents[1],
2342
 
                                    merge_type=merge_type,
2343
 
                                    show_base=show_base,
2344
 
                                    reprocess=reprocess)
 
2487
            conflicts = _mod_merge.merge_inner(
 
2488
                                      tree.branch, other_tree, base_tree,
 
2489
                                      this_tree=tree,
 
2490
                                      interesting_ids=interesting_ids,
 
2491
                                      other_rev_id=parents[1],
 
2492
                                      merge_type=merge_type,
 
2493
                                      show_base=show_base,
 
2494
                                      reprocess=reprocess)
2345
2495
        finally:
2346
2496
            tree.unlock()
2347
2497
        if conflicts > 0:
2349
2499
        else:
2350
2500
            return 0
2351
2501
 
 
2502
 
2352
2503
class cmd_revert(Command):
2353
2504
    """Revert files to a previous revision.
2354
2505
 
2375
2526
    aliases = ['merge-revert']
2376
2527
 
2377
2528
    def run(self, revision=None, no_backup=False, file_list=None):
2378
 
        from bzrlib.commands import parse_spec
2379
2529
        if file_list is not None:
2380
2530
            if len(file_list) == 0:
2381
 
                raise BzrCommandError("No files specified")
 
2531
                raise errors.BzrCommandError("No files specified")
2382
2532
        else:
2383
2533
            file_list = []
2384
2534
        
2387
2537
            # FIXME should be tree.last_revision
2388
2538
            rev_id = tree.last_revision()
2389
2539
        elif len(revision) != 1:
2390
 
            raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
 
2540
            raise errors.BzrCommandError('bzr revert --revision takes exactly 1 argument')
2391
2541
        else:
2392
2542
            rev_id = revision[0].in_history(tree.branch).rev_id
2393
2543
        pb = ui.ui_factory.nested_progress_bar()
2394
2544
        try:
2395
2545
            tree.revert(file_list, 
2396
2546
                        tree.branch.repository.revision_tree(rev_id),
2397
 
                        not no_backup, pb)
 
2547
                        not no_backup, pb, report_changes=True)
2398
2548
        finally:
2399
2549
            pb.finished()
2400
2550
 
2401
2551
 
2402
2552
class cmd_assert_fail(Command):
2403
2553
    """Test reporting of assertion failures"""
 
2554
    # intended just for use in testing
 
2555
 
2404
2556
    hidden = True
 
2557
 
2405
2558
    def run(self):
2406
 
        assert False, "always fails"
 
2559
        raise AssertionError("always fails")
2407
2560
 
2408
2561
 
2409
2562
class cmd_help(Command):
2410
2563
    """Show help on a command or other topic.
2411
2564
 
2412
 
    For a list of all available commands, say 'bzr help commands'."""
 
2565
    For a list of all available commands, say 'bzr help commands'.
 
2566
    """
2413
2567
    takes_options = [Option('long', 'show help on all commands')]
2414
2568
    takes_args = ['topic?']
2415
2569
    aliases = ['?', '--help', '-?', '-h']
2416
2570
    
2417
2571
    @display_command
2418
2572
    def run(self, topic=None, long=False):
2419
 
        import help
 
2573
        import bzrlib.help
2420
2574
        if topic is None and long:
2421
2575
            topic = "commands"
2422
 
        help.help(topic)
 
2576
        bzrlib.help.help(topic)
2423
2577
 
2424
2578
 
2425
2579
class cmd_shell_complete(Command):
2426
2580
    """Show appropriate completions for context.
2427
2581
 
2428
 
    For a list of all available commands, say 'bzr shell-complete'."""
 
2582
    For a list of all available commands, say 'bzr shell-complete'.
 
2583
    """
2429
2584
    takes_args = ['context?']
2430
2585
    aliases = ['s-c']
2431
2586
    hidden = True
2439
2594
class cmd_fetch(Command):
2440
2595
    """Copy in history from another branch but don't merge it.
2441
2596
 
2442
 
    This is an internal method used for pull and merge."""
 
2597
    This is an internal method used for pull and merge.
 
2598
    """
2443
2599
    hidden = True
2444
2600
    takes_args = ['from_branch', 'to_branch']
2445
2601
    def run(self, from_branch, to_branch):
2452
2608
class cmd_missing(Command):
2453
2609
    """Show unmerged/unpulled revisions between two branches.
2454
2610
 
2455
 
    OTHER_BRANCH may be local or remote."""
 
2611
    OTHER_BRANCH may be local or remote.
 
2612
    """
2456
2613
    takes_args = ['other_branch?']
2457
2614
    takes_options = [Option('reverse', 'Reverse the order of revisions'),
2458
2615
                     Option('mine-only', 
2479
2636
        if other_branch is None:
2480
2637
            other_branch = parent
2481
2638
            if other_branch is None:
2482
 
                raise BzrCommandError("No peer location known or specified.")
2483
 
            print "Using last location: " + local_branch.get_parent()
 
2639
                raise errors.BzrCommandError("No peer location known or specified.")
 
2640
            display_url = urlutils.unescape_for_display(parent,
 
2641
                                                        self.outf.encoding)
 
2642
            print "Using last location: " + display_url
 
2643
 
2484
2644
        remote_branch = Branch.open(other_branch)
2485
2645
        if remote_branch.base == local_branch.base:
2486
2646
            remote_branch = local_branch
2601
2761
    takes_args = ['filename']
2602
2762
    takes_options = [Option('all', help='show annotations on all lines'),
2603
2763
                     Option('long', help='show date in annotations'),
2604
 
                     'revision'
 
2764
                     'revision',
 
2765
                     'show-ids',
2605
2766
                     ]
2606
2767
 
2607
2768
    @display_command
2608
 
    def run(self, filename, all=False, long=False, revision=None):
 
2769
    def run(self, filename, all=False, long=False, revision=None,
 
2770
            show_ids=False):
2609
2771
        from bzrlib.annotate import annotate_file
2610
2772
        tree, relpath = WorkingTree.open_containing(filename)
2611
2773
        branch = tree.branch
2614
2776
            if revision is None:
2615
2777
                revision_id = branch.last_revision()
2616
2778
            elif len(revision) != 1:
2617
 
                raise BzrCommandError('bzr annotate --revision takes exactly 1 argument')
 
2779
                raise errors.BzrCommandError('bzr annotate --revision takes exactly 1 argument')
2618
2780
            else:
2619
2781
                revision_id = revision[0].in_history(branch).rev_id
2620
2782
            file_id = tree.inventory.path2id(relpath)
2621
2783
            tree = branch.repository.revision_tree(revision_id)
2622
2784
            file_version = tree.inventory[file_id].revision
2623
 
            annotate_file(branch, file_version, file_id, long, all, sys.stdout)
 
2785
            annotate_file(branch, file_version, file_id, long, all, sys.stdout,
 
2786
                          show_ids=show_ids)
2624
2787
        finally:
2625
2788
            branch.unlock()
2626
2789
 
2636
2799
    def run(self, revision_id_list=None, revision=None):
2637
2800
        import bzrlib.gpg as gpg
2638
2801
        if revision_id_list is not None and revision is not None:
2639
 
            raise BzrCommandError('You can only supply one of revision_id or --revision')
 
2802
            raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
2640
2803
        if revision_id_list is None and revision is None:
2641
 
            raise BzrCommandError('You must supply either --revision or a revision_id')
 
2804
            raise errors.BzrCommandError('You must supply either --revision or a revision_id')
2642
2805
        b = WorkingTree.open_containing(u'.')[0].branch
2643
2806
        gpg_strategy = gpg.GPGStrategy(b.get_config())
2644
2807
        if revision_id_list is not None:
2657
2820
                if to_revid is None:
2658
2821
                    to_revno = b.revno()
2659
2822
                if from_revno is None or to_revno is None:
2660
 
                    raise BzrCommandError('Cannot sign a range of non-revision-history revisions')
 
2823
                    raise errors.BzrCommandError('Cannot sign a range of non-revision-history revisions')
2661
2824
                for revno in range(from_revno, to_revno + 1):
2662
2825
                    b.repository.sign_revision(b.get_rev_id(revno), 
2663
2826
                                               gpg_strategy)
2664
2827
            else:
2665
 
                raise BzrCommandError('Please supply either one revision, or a range.')
 
2828
                raise errors.BzrCommandError('Please supply either one revision, or a range.')
2666
2829
 
2667
2830
 
2668
2831
class cmd_bind(Command):
2680
2843
        b_other = Branch.open(location)
2681
2844
        try:
2682
2845
            b.bind(b_other)
2683
 
        except DivergedBranches:
2684
 
            raise BzrCommandError('These branches have diverged.'
2685
 
                                  ' Try merging, and then bind again.')
 
2846
        except errors.DivergedBranches:
 
2847
            raise errors.BzrCommandError('These branches have diverged.'
 
2848
                                         ' Try merging, and then bind again.')
2686
2849
 
2687
2850
 
2688
2851
class cmd_unbind(Command):
2698
2861
    def run(self):
2699
2862
        b, relpath = Branch.open_containing(u'.')
2700
2863
        if not b.unbind():
2701
 
            raise BzrCommandError('Local branch is not bound')
 
2864
            raise errors.BzrCommandError('Local branch is not bound')
2702
2865
 
2703
2866
 
2704
2867
class cmd_uncommit(Command):
2853
3016
            url = 'readonly+' + url
2854
3017
        t = get_transport(url)
2855
3018
        if inet:
2856
 
            server = smart.SmartStreamServer(sys.stdin, sys.stdout, t)
 
3019
            server = smart.SmartServerPipeStreamMedium(sys.stdin, sys.stdout, t)
2857
3020
        elif port is not None:
2858
3021
            if ':' in port:
2859
3022
                host, port = port.split(':')
2863
3026
            print 'listening on port: ', server.port
2864
3027
            sys.stdout.flush()
2865
3028
        else:
2866
 
            raise BzrCommandError("bzr serve requires one of --inet or --port")
 
3029
            raise errors.BzrCommandError("bzr serve requires one of --inet or --port")
2867
3030
        server.serve()
2868
3031
 
2869
3032
 
2870
3033
# command-line interpretation helper for merge-related commands
2871
 
def merge(other_revision, base_revision,
2872
 
          check_clean=True, ignore_zero=False,
2873
 
          this_dir=None, backup_files=False, merge_type=Merge3Merger,
2874
 
          file_list=None, show_base=False, reprocess=False,
2875
 
          pb=DummyProgress()):
 
3034
def _merge_helper(other_revision, base_revision,
 
3035
                  check_clean=True, ignore_zero=False,
 
3036
                  this_dir=None, backup_files=False,
 
3037
                  merge_type=None,
 
3038
                  file_list=None, show_base=False, reprocess=False,
 
3039
                  pull=False,
 
3040
                  pb=DummyProgress()):
2876
3041
    """Merge changes into a tree.
2877
3042
 
2878
3043
    base_revision
2900
3065
    clients might prefer to call merge.merge_inner(), which has less magic 
2901
3066
    behavior.
2902
3067
    """
2903
 
    from bzrlib.merge import Merger
 
3068
    # Loading it late, so that we don't always have to import bzrlib.merge
 
3069
    if merge_type is None:
 
3070
        merge_type = _mod_merge.Merge3Merger
2904
3071
    if this_dir is None:
2905
3072
        this_dir = u'.'
2906
3073
    this_tree = WorkingTree.open_containing(this_dir)[0]
2907
 
    if show_base and not merge_type is Merge3Merger:
2908
 
        raise BzrCommandError("Show-base is not supported for this merge"
2909
 
                              " type. %s" % merge_type)
 
3074
    if show_base and not merge_type is _mod_merge.Merge3Merger:
 
3075
        raise errors.BzrCommandError("Show-base is not supported for this merge"
 
3076
                                     " type. %s" % merge_type)
2910
3077
    if reprocess and not merge_type.supports_reprocess:
2911
 
        raise BzrCommandError("Conflict reduction is not supported for merge"
2912
 
                              " type %s." % merge_type)
 
3078
        raise errors.BzrCommandError("Conflict reduction is not supported for merge"
 
3079
                                     " type %s." % merge_type)
2913
3080
    if reprocess and show_base:
2914
 
        raise BzrCommandError("Cannot do conflict reduction and show base.")
 
3081
        raise errors.BzrCommandError("Cannot do conflict reduction and show base.")
2915
3082
    try:
2916
 
        merger = Merger(this_tree.branch, this_tree=this_tree, pb=pb)
 
3083
        merger = _mod_merge.Merger(this_tree.branch, this_tree=this_tree,
 
3084
                                   pb=pb)
2917
3085
        merger.pp = ProgressPhase("Merge phase", 5, pb)
2918
3086
        merger.pp.next_phase()
2919
3087
        merger.check_basis(check_clean)
2923
3091
        if merger.base_rev_id == merger.other_rev_id:
2924
3092
            note('Nothing to do.')
2925
3093
            return 0
 
3094
        if file_list is None:
 
3095
            if pull and merger.base_rev_id == merger.this_rev_id:
 
3096
                count = merger.this_tree.pull(merger.this_branch,
 
3097
                        False, merger.other_rev_id)
 
3098
                note('%d revision(s) pulled.' % (count,))
 
3099
                return 0
2926
3100
        merger.backup_files = backup_files
2927
3101
        merger.merge_type = merge_type 
2928
3102
        merger.set_interesting_files(file_list)
2936
3110
    return conflicts
2937
3111
 
2938
3112
 
 
3113
# Compatibility
 
3114
merge = _merge_helper
 
3115
 
 
3116
 
2939
3117
# these get imported and then picked up by the scan for cmd_*
2940
3118
# TODO: Some more consistent way to split command definitions across files;
2941
3119
# we do need to load at least some information about them to know of