/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

[merge] bzr.dev 2240

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 (
32
34
    errors,
33
35
    ignores,
34
36
    log,
 
37
    merge as _mod_merge,
35
38
    osutils,
36
39
    repository,
37
40
    transport,
 
41
    tree as _mod_tree,
38
42
    ui,
39
43
    urlutils,
40
44
    )
41
 
from bzrlib.branch import Branch, BranchReferenceFormat
42
 
from bzrlib.bundle import read_bundle_from_url
 
45
from bzrlib.branch import Branch
43
46
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
44
47
from bzrlib.conflicts import ConflictList
 
48
from bzrlib.revision import common_ancestor
 
49
from bzrlib.revisionspec import RevisionSpec
 
50
from bzrlib.workingtree import WorkingTree
 
51
""")
 
52
 
45
53
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
 
54
from bzrlib.option import Option, RegistryOption
52
55
from bzrlib.progress import DummyProgress, ProgressPhase
53
 
from bzrlib.revision import common_ancestor
54
 
from bzrlib.revisionspec import RevisionSpec
55
56
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
57
 
60
58
 
61
59
def tree_files(file_list, default_branch=u'.'):
62
60
    try:
63
61
        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]))
 
62
    except errors.FileInWrongBranch, e:
 
63
        raise errors.BzrCommandError("%s is not in the same branch as %s" %
 
64
                                     (e.path, file_list[0]))
67
65
 
68
66
 
69
67
# XXX: Bad function name; should possibly also be a class method of
78
76
 
79
77
    :param file_list: Filenames to convert.  
80
78
 
81
 
    :param default_branch: Fallback tree path to use if file_list is empty or None.
 
79
    :param default_branch: Fallback tree path to use if file_list is empty or
 
80
        None.
82
81
 
83
82
    :return: workingtree, [relative_paths]
84
83
    """
85
84
    if file_list is None or len(file_list) == 0:
86
85
        return WorkingTree.open_containing(default_branch)[0], file_list
87
 
    tree = WorkingTree.open_containing(file_list[0])[0]
 
86
    tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
88
87
    new_list = []
89
88
    for filename in file_list:
90
89
        try:
91
 
            new_list.append(tree.relpath(filename))
 
90
            new_list.append(tree.relpath(osutils.dereference_path(filename)))
92
91
        except errors.PathNotChild:
93
 
            raise FileInWrongBranch(tree.branch, filename)
 
92
            raise errors.FileInWrongBranch(tree.branch, filename)
94
93
    return tree, new_list
95
94
 
96
95
 
97
96
def get_format_type(typestring):
98
97
    """Parse and return a format specifier."""
99
 
    if typestring == "weave":
100
 
        return bzrdir.BzrDirFormat6()
 
98
    # Have to use BzrDirMetaFormat1 directly, so that
 
99
    # RepositoryFormat.set_default_format works
101
100
    if typestring == "default":
102
101
        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)
 
102
    try:
 
103
        return bzrdir.format_registry.make_bzrdir(typestring)
 
104
    except KeyError:
 
105
        msg = 'Unknown bzr format "%s". See "bzr help formats".' % typestring
 
106
        raise errors.BzrCommandError(msg)
118
107
 
119
108
 
120
109
# TODO: Make sure no commands unconditionally use the working directory as a
129
118
    This reports on versioned and unknown files, reporting them
130
119
    grouped by state.  Possible states are:
131
120
 
132
 
    added
 
121
    added / A
133
122
        Versioned in the working copy but not in the previous revision.
134
123
 
135
 
    removed
 
124
    removed / D
136
125
        Versioned in the previous revision but removed or deleted
137
126
        in the working copy.
138
127
 
139
 
    renamed
 
128
    renamed / R
140
129
        Path of this file changed from the previous revision;
141
130
        the text may also have changed.  This includes files whose
142
131
        parent directory was renamed.
143
132
 
144
 
    modified
 
133
    modified / M
145
134
        Text has changed since the previous revision.
146
135
 
147
 
    unknown
 
136
    unknown / ?
148
137
        Not versioned and not matching an ignore pattern.
149
138
 
150
139
    To see ignored files use 'bzr ignored'.  For details in the
151
140
    changes to file texts, use 'bzr diff'.
 
141
    
 
142
    --short gives a one character status flag for each item, similar
 
143
    to the SVN's status command.
152
144
 
153
145
    If no arguments are specified, the status of the entire working
154
146
    directory is shown.  Otherwise, only the status of the specified
162
154
    # TODO: --no-recurse, --recurse options
163
155
    
164
156
    takes_args = ['file*']
165
 
    takes_options = ['show-ids', 'revision']
 
157
    takes_options = ['show-ids', 'revision', 'short']
166
158
    aliases = ['st', 'stat']
167
159
 
168
160
    encoding_type = 'replace'
169
161
    
170
162
    @display_command
171
 
    def run(self, show_ids=False, file_list=None, revision=None):
 
163
    def run(self, show_ids=False, file_list=None, revision=None, short=False):
172
164
        from bzrlib.status import show_tree_status
173
165
 
174
166
        tree, file_list = tree_files(file_list)
175
167
            
176
168
        show_tree_status(tree, show_ids=show_ids,
177
169
                         specific_files=file_list, revision=revision,
178
 
                         to_file=self.outf)
 
170
                         to_file=self.outf,
 
171
                         short=short)
179
172
 
180
173
 
181
174
class cmd_cat_revision(Command):
195
188
    def run(self, revision_id=None, revision=None):
196
189
 
197
190
        if revision_id is not None and revision is not None:
198
 
            raise BzrCommandError('You can only supply one of revision_id or --revision')
 
191
            raise errors.BzrCommandError('You can only supply one of'
 
192
                                         ' revision_id or --revision')
199
193
        if revision_id is None and revision is None:
200
 
            raise BzrCommandError('You must supply either --revision or a revision_id')
 
194
            raise errors.BzrCommandError('You must supply either'
 
195
                                         ' --revision or a revision_id')
201
196
        b = WorkingTree.open_containing(u'.')[0].branch
202
197
 
203
198
        # TODO: jam 20060112 should cat-revision always output utf-8?
206
201
        elif revision is not None:
207
202
            for rev in revision:
208
203
                if rev is None:
209
 
                    raise BzrCommandError('You cannot specify a NULL revision.')
 
204
                    raise errors.BzrCommandError('You cannot specify a NULL'
 
205
                                                 ' revision.')
210
206
                revno, rev_id = rev.in_history(b)
211
207
                self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
212
208
    
213
209
 
 
210
class cmd_remove_tree(Command):
 
211
    """Remove the working tree from a given branch/checkout.
 
212
 
 
213
    Since a lightweight checkout is little more than a working tree
 
214
    this will refuse to run against one.
 
215
    """
 
216
 
 
217
    hidden = True
 
218
 
 
219
    takes_args = ['location?']
 
220
 
 
221
    def run(self, location='.'):
 
222
        d = bzrdir.BzrDir.open(location)
 
223
        
 
224
        try:
 
225
            working = d.open_workingtree()
 
226
        except errors.NoWorkingTree:
 
227
            raise errors.BzrCommandError("No working tree to remove")
 
228
        except errors.NotLocalUrl:
 
229
            raise errors.BzrCommandError("You cannot remove the working tree of a "
 
230
                                         "remote path")
 
231
        
 
232
        working_path = working.bzrdir.root_transport.base
 
233
        branch_path = working.branch.bzrdir.root_transport.base
 
234
        if working_path != branch_path:
 
235
            raise errors.BzrCommandError("You cannot remove the working tree from "
 
236
                                         "a lightweight checkout")
 
237
        
 
238
        d.destroy_workingtree()
 
239
        
 
240
 
214
241
class cmd_revno(Command):
215
242
    """Show current revision number.
216
243
 
242
269
            for rev in revision_info_list:
243
270
                revs.append(RevisionSpec.from_string(rev))
244
271
        if len(revs) == 0:
245
 
            raise BzrCommandError('You must supply a revision identifier')
 
272
            raise errors.BzrCommandError('You must supply a revision identifier')
246
273
 
247
274
        b = WorkingTree.open_containing(u'.')[0].branch
248
275
 
299
326
                base_tree, base_path = WorkingTree.open_containing(
300
327
                                            file_ids_from)
301
328
            except errors.NoWorkingTree:
302
 
                base_branch, base_path = branch.Branch.open_containing(
 
329
                base_branch, base_path = Branch.open_containing(
303
330
                                            file_ids_from)
304
331
                base_tree = base_branch.basis_tree()
305
332
 
374
401
    @display_command
375
402
    def run(self, revision=None, show_ids=False, kind=None, file_list=None):
376
403
        if kind and kind not in ['file', 'directory', 'symlink']:
377
 
            raise BzrCommandError('invalid kind specified')
 
404
            raise errors.BzrCommandError('invalid kind specified')
378
405
 
379
406
        work_tree, file_list = tree_files(file_list)
380
407
 
381
408
        if revision is not None:
382
409
            if len(revision) > 1:
383
 
                raise BzrCommandError('bzr inventory --revision takes'
384
 
                                      ' exactly one revision identifier')
 
410
                raise errors.BzrCommandError('bzr inventory --revision takes'
 
411
                                             ' exactly one revision identifier')
385
412
            revision_id = revision[0].in_history(work_tree.branch).rev_id
386
413
            tree = work_tree.branch.repository.revision_tree(revision_id)
387
414
                        
395
422
            trees = [tree]
396
423
 
397
424
        if file_list is not None:
398
 
            file_ids = bzrlib.tree.find_ids_across_trees(file_list, trees,
 
425
            file_ids = _mod_tree.find_ids_across_trees(file_list, trees,
399
426
                                                      require_versioned=True)
400
427
            # find_ids_across_trees may include some paths that don't
401
428
            # exist in 'tree'.
437
464
            names_list = []
438
465
 
439
466
        if len(names_list) < 2:
440
 
            raise BzrCommandError("missing file argument")
 
467
            raise errors.BzrCommandError("missing file argument")
441
468
        tree, rel_names = tree_files(names_list)
442
469
        
443
470
        if os.path.isdir(names_list[-1]):
446
473
                self.outf.write("%s => %s\n" % pair)
447
474
        else:
448
475
            if len(names_list) != 2:
449
 
                raise BzrCommandError('to mv multiple files the destination '
450
 
                                      'must be a versioned directory')
 
476
                raise errors.BzrCommandError('to mv multiple files the destination '
 
477
                                             'must be a versioned directory')
451
478
            tree.rename_one(rel_names[0], rel_names[1])
452
479
            self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
453
480
            
481
508
        try:
482
509
            tree_to = WorkingTree.open_containing(u'.')[0]
483
510
            branch_to = tree_to.branch
484
 
        except NoWorkingTree:
 
511
        except errors.NoWorkingTree:
485
512
            tree_to = None
486
513
            branch_to = Branch.open_containing(u'.')[0]
487
514
 
489
516
        if location is not None:
490
517
            try:
491
518
                reader = bundle.read_bundle_from_url(location)
492
 
            except NotABundle:
 
519
            except errors.NotABundle:
493
520
                pass # Continue on considering this url a Branch
494
521
 
495
522
        stored_loc = branch_to.get_parent()
496
523
        if location is None:
497
524
            if stored_loc is None:
498
 
                raise BzrCommandError("No pull location known or specified.")
 
525
                raise errors.BzrCommandError("No pull location known or"
 
526
                                             " specified.")
499
527
            else:
500
528
                display_url = urlutils.unescape_for_display(stored_loc,
501
529
                        self.outf.encoding)
519
547
        elif len(revision) == 1:
520
548
            rev_id = revision[0].in_history(branch_from).rev_id
521
549
        else:
522
 
            raise BzrCommandError('bzr pull --revision takes one value.')
 
550
            raise errors.BzrCommandError('bzr pull --revision takes one value.')
523
551
 
524
552
        old_rh = branch_to.revision_history()
525
553
        if tree_to is not None:
579
607
        stored_loc = br_from.get_push_location()
580
608
        if location is None:
581
609
            if stored_loc is None:
582
 
                raise BzrCommandError("No push location known or specified.")
 
610
                raise errors.BzrCommandError("No push location known or specified.")
583
611
            else:
584
612
                display_url = urlutils.unescape_for_display(stored_loc,
585
613
                        self.outf.encoding)
593
621
        try:
594
622
            dir_to = bzrdir.BzrDir.open(location_url)
595
623
            br_to = dir_to.open_branch()
596
 
        except NotBranchError:
 
624
        except errors.NotBranchError:
597
625
            # create a branch.
598
626
            to_transport = to_transport.clone('..')
599
627
            if not create_prefix:
601
629
                    relurl = to_transport.relpath(location_url)
602
630
                    mutter('creating directory %s => %s', location_url, relurl)
603
631
                    to_transport.mkdir(relurl)
604
 
                except NoSuchFile:
605
 
                    raise BzrCommandError("Parent directory of %s "
606
 
                                          "does not exist." % location)
 
632
                except errors.NoSuchFile:
 
633
                    raise errors.BzrCommandError("Parent directory of %s "
 
634
                                                 "does not exist." % location)
607
635
            else:
608
636
                current = to_transport.base
609
637
                needed = [(to_transport, to_transport.relpath(location_url))]
612
640
                        to_transport, relpath = needed[-1]
613
641
                        to_transport.mkdir(relpath)
614
642
                        needed.pop()
615
 
                    except NoSuchFile:
 
643
                    except errors.NoSuchFile:
616
644
                        new_transport = to_transport.clone('..')
617
645
                        needed.append((new_transport,
618
646
                                       new_transport.relpath(to_transport.base)))
619
647
                        if new_transport.base == to_transport.base:
620
 
                            raise BzrCommandError("Could not create "
621
 
                                                  "path prefix.")
 
648
                            raise errors.BzrCommandError("Could not create "
 
649
                                                         "path prefix.")
622
650
            dir_to = br_from.bzrdir.clone(location_url,
623
651
                revision_id=br_from.last_revision())
624
652
            br_to = dir_to.open_branch()
639
667
                    warning('This transport does not update the working '
640
668
                            'tree of: %s' % (br_to.base,))
641
669
                    count = br_to.pull(br_from, overwrite)
642
 
                except NoWorkingTree:
 
670
                except errors.NoWorkingTree:
643
671
                    count = br_to.pull(br_from, overwrite)
644
672
                else:
645
673
                    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.")
 
674
            except errors.DivergedBranches:
 
675
                raise errors.BzrCommandError('These branches have diverged.'
 
676
                                        '  Try using "merge" and then "push".')
649
677
        note('%d revision(s) pushed.' % (count,))
650
678
 
651
679
        if verbose:
678
706
        if revision is None:
679
707
            revision = [None]
680
708
        elif len(revision) > 1:
681
 
            raise BzrCommandError(
 
709
            raise errors.BzrCommandError(
682
710
                'bzr branch --revision takes exactly 1 revision value')
683
711
        try:
684
712
            br_from = Branch.open(from_location)
685
713
        except OSError, e:
686
714
            if e.errno == errno.ENOENT:
687
 
                raise BzrCommandError('Source location "%s" does not'
688
 
                                      ' exist.' % to_location)
 
715
                raise errors.BzrCommandError('Source location "%s" does not'
 
716
                                             ' exist.' % to_location)
689
717
            else:
690
718
                raise
691
719
        br_from.lock_read()
711
739
            try:
712
740
                to_transport.mkdir('.')
713
741
            except errors.FileExists:
714
 
                raise BzrCommandError('Target directory "%s" already'
715
 
                                      ' exists.' % to_location)
 
742
                raise errors.BzrCommandError('Target directory "%s" already'
 
743
                                             ' exists.' % to_location)
716
744
            except errors.NoSuchFile:
717
 
                raise BzrCommandError('Parent of "%s" does not exist.' %
718
 
                                      to_location)
 
745
                raise errors.BzrCommandError('Parent of "%s" does not exist.'
 
746
                                             % to_location)
719
747
            try:
720
748
                # preserve whatever source format we have.
721
749
                dir = br_from.bzrdir.sprout(to_transport.base,
724
752
            except errors.NoSuchRevision:
725
753
                to_transport.delete_tree('.')
726
754
                msg = "The branch %s has no revision %s." % (from_location, revision[0])
727
 
                raise BzrCommandError(msg)
 
755
                raise errors.BzrCommandError(msg)
728
756
            except errors.UnlistableBranch:
729
757
                osutils.rmtree(to_location)
730
758
                msg = "The branch %s cannot be used as a --basis" % (basis,)
731
 
                raise BzrCommandError(msg)
 
759
                raise errors.BzrCommandError(msg)
732
760
            if name:
733
761
                branch.control_files.put_utf8('branch-name', name)
734
762
            note('Branched %d revision(s).' % branch.revno())
773
801
        if revision is None:
774
802
            revision = [None]
775
803
        elif len(revision) > 1:
776
 
            raise BzrCommandError(
 
804
            raise errors.BzrCommandError(
777
805
                'bzr checkout --revision takes exactly 1 revision value')
778
806
        if branch_location is None:
779
807
            branch_location = osutils.getcwd()
799
827
            os.mkdir(to_location)
800
828
        except OSError, e:
801
829
            if e.errno == errno.EEXIST:
802
 
                raise BzrCommandError('Target directory "%s" already'
803
 
                                      ' exists.' % to_location)
 
830
                raise errors.BzrCommandError('Target directory "%s" already'
 
831
                                             ' exists.' % to_location)
804
832
            if e.errno == errno.ENOENT:
805
 
                raise BzrCommandError('Parent of "%s" does not exist.' %
806
 
                                      to_location)
 
833
                raise errors.BzrCommandError('Parent of "%s" does not exist.'
 
834
                                             % to_location)
807
835
            else:
808
836
                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)
 
837
        source.create_checkout(to_location, revision_id, lightweight)
815
838
 
816
839
 
817
840
class cmd_renames(Command):
824
847
 
825
848
    @display_command
826
849
    def run(self, dir=u'.'):
827
 
        from bzrlib.tree import find_renames
828
850
        tree = WorkingTree.open_containing(dir)[0]
829
851
        old_inv = tree.basis_tree().inventory
830
852
        new_inv = tree.read_working_inventory()
831
 
        renames = list(find_renames(old_inv, new_inv))
 
853
        renames = list(_mod_tree.find_renames(old_inv, new_inv))
832
854
        renames.sort()
833
855
        for old_name, new_name in renames:
834
856
            self.outf.write("%s => %s\n" % (old_name, new_name))
849
871
 
850
872
    def run(self, dir='.'):
851
873
        tree = WorkingTree.open_containing(dir)[0]
852
 
        tree.lock_write()
 
874
        master = tree.branch.get_master_branch()
 
875
        if master is not None:
 
876
            tree.lock_write()
 
877
        else:
 
878
            tree.lock_tree_write()
853
879
        try:
854
880
            existing_pending_merges = tree.get_parent_ids()[1:]
855
881
            last_rev = tree.last_revision()
913
939
        tree, file_list = tree_files(file_list)
914
940
        if new is False:
915
941
            if file_list is None:
916
 
                raise BzrCommandError('Specify one or more files to remove, or'
917
 
                                      ' use --new.')
 
942
                raise errors.BzrCommandError('Specify one or more files to'
 
943
                                             ' remove, or use --new.')
918
944
        else:
919
945
            added = tree.changes_from(tree.basis_tree(),
920
946
                specific_files=file_list).added
921
947
            file_list = sorted([f[0] for f in added], reverse=True)
922
948
            if len(file_list) == 0:
923
 
                raise BzrCommandError('No matching files.')
 
949
                raise errors.BzrCommandError('No matching files.')
924
950
        tree.remove(file_list, verbose=verbose, to_file=self.outf)
925
951
 
926
952
 
940
966
        tree, relpath = WorkingTree.open_containing(filename)
941
967
        i = tree.inventory.path2id(relpath)
942
968
        if i is None:
943
 
            raise BzrError("%r is not a versioned file" % filename)
 
969
            raise errors.NotVersionedError(filename)
944
970
        else:
945
971
            self.outf.write(i + '\n')
946
972
 
961
987
        inv = tree.inventory
962
988
        fid = inv.path2id(relpath)
963
989
        if fid is None:
964
 
            raise BzrError("%r is not a versioned file" % filename)
 
990
            raise errors.NotVersionedError(filename)
965
991
        for fip in inv.get_idpath(fid):
966
992
            self.outf.write(fip + '\n')
967
993
 
1053
1079
    """
1054
1080
    takes_args = ['location?']
1055
1081
    takes_options = [
1056
 
                     Option('format', 
 
1082
                     RegistryOption('format',
1057
1083
                            help='Specify a format for this branch. Current'
1058
1084
                                 ' formats are: default, knit, metaweave and'
1059
1085
                                 ' weave. Default is knit; metaweave and'
1060
1086
                                 ' weave are deprecated',
1061
 
                            type=get_format_type),
 
1087
                            registry=bzrdir.format_registry,
 
1088
                            converter=get_format_type,
 
1089
                            value_switches=True),
1062
1090
                     ]
1063
1091
    def run(self, location=None, format=None):
1064
1092
        if format is None:
1081
1109
                    
1082
1110
        try:
1083
1111
            existing_bzrdir = bzrdir.BzrDir.open(location)
1084
 
        except NotBranchError:
 
1112
        except errors.NotBranchError:
1085
1113
            # really a NotBzrDir error...
1086
1114
            bzrdir.BzrDir.create_branch_convenience(location, format=format)
1087
1115
        else:
 
1116
            from bzrlib.transport.local import LocalTransport
1088
1117
            if existing_bzrdir.has_branch():
1089
1118
                if (isinstance(to_transport, LocalTransport)
1090
1119
                    and not existing_bzrdir.has_workingtree()):
1110
1139
        (add files here)
1111
1140
    """
1112
1141
    takes_args = ["location"] 
1113
 
    takes_options = [Option('format', 
 
1142
    takes_options = [RegistryOption('format',
1114
1143
                            help='Specify a format for this repository.'
1115
1144
                                 ' Current formats are: default, knit,'
1116
1145
                                 ' metaweave and weave. Default is knit;'
1117
1146
                                 ' metaweave and weave are deprecated',
1118
 
                            type=get_format_type),
 
1147
                            registry=bzrdir.format_registry,
 
1148
                            converter=get_format_type,
 
1149
                            value_switches=True),
1119
1150
                     Option('trees',
1120
1151
                             help='Allows branches in repository to have'
1121
1152
                             ' a working tree')]
1171
1202
    #       deleted files.
1172
1203
 
1173
1204
    # TODO: This probably handles non-Unix newlines poorly.
1174
 
    
 
1205
 
1175
1206
    takes_args = ['file*']
1176
 
    takes_options = ['revision', 'diff-options', 'prefix']
 
1207
    takes_options = ['revision', 'diff-options',
 
1208
        Option('prefix', type=str,
 
1209
               short_name='p',
 
1210
               help='Set prefixes to added to old and new filenames, as '
 
1211
                    'two values separated by a colon.'),
 
1212
        ]
1177
1213
    aliases = ['di', 'dif']
1178
1214
    encoding_type = 'exact'
1179
1215
 
1189
1225
        elif prefix == '1':
1190
1226
            old_label = 'old/'
1191
1227
            new_label = 'new/'
1192
 
        else:
1193
 
            if not ':' in prefix:
1194
 
                 raise BzrError("--diff-prefix expects two values separated by a colon")
 
1228
        elif ':' in prefix:
1195
1229
            old_label, new_label = prefix.split(":")
 
1230
        else:
 
1231
            raise BzrCommandError(
 
1232
                "--prefix expects two values separated by a colon")
 
1233
 
 
1234
        if revision and len(revision) > 2:
 
1235
            raise errors.BzrCommandError('bzr diff --revision takes exactly'
 
1236
                                         ' one or two revision specifiers')
1196
1237
        
1197
1238
        try:
1198
1239
            tree1, file_list = internal_tree_files(file_list)
1199
1240
            tree2 = None
1200
1241
            b = None
1201
1242
            b2 = None
1202
 
        except FileInWrongBranch:
 
1243
        except errors.FileInWrongBranch:
1203
1244
            if len(file_list) != 2:
1204
 
                raise BzrCommandError("Files are in different branches")
 
1245
                raise errors.BzrCommandError("Files are in different branches")
1205
1246
 
1206
1247
            tree1, file1 = WorkingTree.open_containing(file_list[0])
1207
1248
            tree2, file2 = WorkingTree.open_containing(file_list[1])
1208
1249
            if file1 != "" or file2 != "":
1209
1250
                # FIXME diff those two files. rbc 20051123
1210
 
                raise BzrCommandError("Files are in different branches")
 
1251
                raise errors.BzrCommandError("Files are in different branches")
1211
1252
            file_list = None
1212
 
        except NotBranchError:
 
1253
        except errors.NotBranchError:
1213
1254
            if (revision is not None and len(revision) == 2
1214
1255
                and not revision[0].needs_branch()
1215
1256
                and not revision[1].needs_branch()):
1218
1259
                tree1, tree2 = None, None
1219
1260
            else:
1220
1261
                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)
 
1262
 
 
1263
        if tree2 is not None:
 
1264
            if revision is not None:
 
1265
                # FIXME: but there should be a clean way to diff between
 
1266
                # non-default versions of two trees, it's not hard to do
 
1267
                # internally...
 
1268
                raise errors.BzrCommandError(
 
1269
                        "Sorry, diffing arbitrary revisions across branches "
 
1270
                        "is not implemented yet")
 
1271
            return show_diff_trees(tree1, tree2, sys.stdout, 
 
1272
                                   specific_files=file_list,
 
1273
                                   external_diff_options=diff_options,
 
1274
                                   old_label=old_label, new_label=new_label)
 
1275
 
 
1276
        return diff_cmd_helper(tree1, file_list, diff_options,
 
1277
                               revision_specs=revision,
 
1278
                               old_label=old_label, new_label=new_label)
1243
1279
 
1244
1280
 
1245
1281
class cmd_deleted(Command):
1288
1324
        for file_id in inv:
1289
1325
            if file_id in basis_inv:
1290
1326
                continue
 
1327
            if inv.is_root(file_id) and len(basis_inv) == 0:
 
1328
                continue
1291
1329
            path = inv.id2path(file_id)
1292
1330
            if not os.access(osutils.abspath(path), os.F_OK):
1293
1331
                continue
1329
1367
                            help='show from oldest to newest'),
1330
1368
                     'timezone', 
1331
1369
                     Option('verbose', 
 
1370
                             short_name='v',
1332
1371
                             help='show files changed in each revision'),
1333
1372
                     'show-ids', 'revision',
1334
1373
                     'log-format',
1335
1374
                     'line', 'long', 
1336
1375
                     Option('message',
 
1376
                            short_name='m',
1337
1377
                            help='show revisions whose message matches this regexp',
1338
1378
                            type=str),
1339
1379
                     'short',
1371
1411
                    # either no tree, or is remote.
1372
1412
                    inv = b.basis_tree().inventory
1373
1413
                file_id = inv.path2id(fp)
 
1414
                if file_id is None:
 
1415
                    raise errors.BzrCommandError(
 
1416
                        "Path does not have any revision history: %s" %
 
1417
                        location)
1374
1418
        else:
1375
1419
            # local dir only
1376
1420
            # FIXME ? log the current subdir only RBC 20060203 
1392
1436
                # b is taken from revision[0].get_branch(), and
1393
1437
                # show_log will use its revision_history. Having
1394
1438
                # different branches will lead to weird behaviors.
1395
 
                raise BzrCommandError(
 
1439
                raise errors.BzrCommandError(
1396
1440
                    "Log doesn't accept two revisions in different branches.")
1397
1441
            if revision[0].spec is None:
1398
1442
                # missing begin-range means first revision
1406
1450
            else:
1407
1451
                rev2 = revision[1].in_history(b).revno
1408
1452
        else:
1409
 
            raise BzrCommandError('bzr log --revision takes one or two values.')
 
1453
            raise errors.BzrCommandError('bzr log --revision takes one or two values.')
1410
1454
 
1411
1455
        # By this point, the revision numbers are converted to the +ve
1412
1456
        # form if they were supplied in the -ve form, so we can do
1466
1510
class cmd_ls(Command):
1467
1511
    """List files in a tree.
1468
1512
    """
 
1513
 
 
1514
    takes_args = ['path?']
1469
1515
    # TODO: Take a revision or remote path and list that tree instead.
1470
 
    hidden = True
1471
1516
    takes_options = ['verbose', 'revision',
1472
1517
                     Option('non-recursive',
1473
1518
                            help='don\'t recurse into sub-directories'),
1478
1523
                     Option('ignored', help='Print ignored files'),
1479
1524
 
1480
1525
                     Option('null', help='Null separate the files'),
 
1526
                     'kind', 'show-ids'
1481
1527
                    ]
1482
1528
    @display_command
1483
1529
    def run(self, revision=None, verbose=False, 
1484
1530
            non_recursive=False, from_root=False,
1485
1531
            unknown=False, versioned=False, ignored=False,
1486
 
            null=False):
 
1532
            null=False, kind=None, show_ids=False, path=None):
 
1533
 
 
1534
        if kind and kind not in ('file', 'directory', 'symlink'):
 
1535
            raise errors.BzrCommandError('invalid kind specified')
1487
1536
 
1488
1537
        if verbose and null:
1489
 
            raise BzrCommandError('Cannot set both --verbose and --null')
 
1538
            raise errors.BzrCommandError('Cannot set both --verbose and --null')
1490
1539
        all = not (unknown or versioned or ignored)
1491
1540
 
1492
1541
        selection = {'I':ignored, '?':unknown, 'V':versioned}
1493
1542
 
1494
 
        tree, relpath = WorkingTree.open_containing(u'.')
 
1543
        if path is None:
 
1544
            fs_path = '.'
 
1545
            prefix = ''
 
1546
        else:
 
1547
            if from_root:
 
1548
                raise errors.BzrCommandError('cannot specify both --from-root'
 
1549
                                             ' and PATH')
 
1550
            fs_path = path
 
1551
            prefix = path
 
1552
        tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
 
1553
            fs_path)
1495
1554
        if from_root:
1496
1555
            relpath = u''
1497
1556
        elif relpath:
1498
1557
            relpath += '/'
1499
1558
        if revision is not None:
1500
 
            tree = tree.branch.repository.revision_tree(
1501
 
                revision[0].in_history(tree.branch).rev_id)
 
1559
            tree = branch.repository.revision_tree(
 
1560
                revision[0].in_history(branch).rev_id)
 
1561
        elif tree is None:
 
1562
            tree = branch.basis_tree()
1502
1563
 
1503
 
        for fp, fc, kind, fid, entry in tree.list_files():
 
1564
        for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
1504
1565
            if fp.startswith(relpath):
1505
 
                fp = fp[len(relpath):]
 
1566
                fp = osutils.pathjoin(prefix, fp[len(relpath):])
1506
1567
                if non_recursive and '/' in fp:
1507
1568
                    continue
1508
1569
                if not all and not selection[fc]:
1509
1570
                    continue
 
1571
                if kind is not None and fkind != kind:
 
1572
                    continue
1510
1573
                if verbose:
1511
1574
                    kindch = entry.kind_character()
1512
 
                    self.outf.write('%-8s %s%s\n' % (fc, fp, kindch))
 
1575
                    outstring = '%-8s %s%s' % (fc, fp, kindch)
 
1576
                    if show_ids and fid is not None:
 
1577
                        outstring = "%-50s %s" % (outstring, fid)
 
1578
                    self.outf.write(outstring + '\n')
1513
1579
                elif null:
1514
1580
                    self.outf.write(fp + '\0')
 
1581
                    if show_ids:
 
1582
                        if fid is not None:
 
1583
                            self.outf.write(fid)
 
1584
                        self.outf.write('\0')
1515
1585
                    self.outf.flush()
1516
1586
                else:
1517
 
                    self.outf.write(fp + '\n')
 
1587
                    if fid is not None:
 
1588
                        my_id = fid
 
1589
                    else:
 
1590
                        my_id = ''
 
1591
                    if show_ids:
 
1592
                        self.outf.write('%-50s %s\n' % (fp, my_id))
 
1593
                    else:
 
1594
                        self.outf.write(fp + '\n')
1518
1595
 
1519
1596
 
1520
1597
class cmd_unknowns(Command):
1526
1603
 
1527
1604
 
1528
1605
class cmd_ignore(Command):
1529
 
    """Ignore a command or pattern.
 
1606
    """Ignore specified files or patterns.
1530
1607
 
1531
1608
    To remove patterns from the ignore list, edit the .bzrignore file.
1532
1609
 
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.
 
1610
    Trailing slashes on patterns are ignored. 
 
1611
    If the pattern contains a slash or is a regular expression, it is compared 
 
1612
    to the whole path from the branch root.  Otherwise, it is compared to only
 
1613
    the last component of the path.  To match a file only in the root 
 
1614
    directory, prepend './'.
 
1615
 
 
1616
    Ignore patterns specifying absolute paths are not allowed.
 
1617
 
 
1618
    Ignore patterns may include globbing wildcards such as:
 
1619
      ? - Matches any single character except '/'
 
1620
      * - Matches 0 or more characters except '/'
 
1621
      /**/ - Matches 0 or more directories in a path
 
1622
      [a-z] - Matches a single character from within a group of characters
 
1623
 
 
1624
    Ignore patterns may also be Python regular expressions.  
 
1625
    Regular expression ignore patterns are identified by a 'RE:' prefix 
 
1626
    followed by the regular expression.  Regular expression ignore patterns
 
1627
    may not include named or numbered groups.
 
1628
 
 
1629
    Note: ignore patterns containing shell wildcards must be quoted from 
 
1630
    the shell on Unix.
1541
1631
 
1542
1632
    examples:
1543
1633
        bzr ignore ./Makefile
1544
1634
        bzr ignore '*.class'
 
1635
        bzr ignore 'lib/**/*.o'
 
1636
        bzr ignore 'RE:lib/.*\.o'
1545
1637
    """
1546
 
    # TODO: Complain if the filename is absolute
1547
 
    takes_args = ['name_pattern?']
 
1638
    takes_args = ['name_pattern*']
1548
1639
    takes_options = [
1549
1640
                     Option('old-default-rules',
1550
1641
                            help='Out the ignore rules bzr < 0.9 always used.')
1551
1642
                     ]
1552
1643
    
1553
 
    def run(self, name_pattern=None, old_default_rules=None):
 
1644
    def run(self, name_pattern_list=None, old_default_rules=None):
1554
1645
        from bzrlib.atomicfile import AtomicFile
1555
1646
        if old_default_rules is not None:
1556
1647
            # dump the rules and exit
1557
1648
            for pattern in ignores.OLD_DEFAULTS:
1558
1649
                print pattern
1559
1650
            return
1560
 
        if name_pattern is None:
1561
 
            raise BzrCommandError("ignore requires a NAME_PATTERN")
 
1651
        if not name_pattern_list:
 
1652
            raise errors.BzrCommandError("ignore requires at least one "
 
1653
                                  "NAME_PATTERN or --old-default-rules")
 
1654
        for name_pattern in name_pattern_list:
 
1655
            if name_pattern[0] == '/':
 
1656
                raise errors.BzrCommandError(
 
1657
                    "NAME_PATTERN should not be an absolute path")
1562
1658
        tree, relpath = WorkingTree.open_containing(u'.')
1563
1659
        ifn = tree.abspath('.bzrignore')
1564
1660
        if os.path.exists(ifn):
1575
1671
 
1576
1672
        if igns and igns[-1] != '\n':
1577
1673
            igns += '\n'
1578
 
        igns += name_pattern + '\n'
 
1674
        for name_pattern in name_pattern_list:
 
1675
            igns += name_pattern.rstrip('/') + '\n'
1579
1676
 
1580
 
        f = AtomicFile(ifn, 'wt')
 
1677
        f = AtomicFile(ifn, 'wb')
1581
1678
        try:
1582
1679
            f.write(igns.encode('utf-8'))
1583
1680
            f.commit()
1621
1718
        try:
1622
1719
            revno = int(revno)
1623
1720
        except ValueError:
1624
 
            raise BzrCommandError("not a valid revision-number: %r" % revno)
 
1721
            raise errors.BzrCommandError("not a valid revision-number: %r" % revno)
1625
1722
 
1626
1723
        print WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
1627
1724
 
1638
1735
    Root may be the top directory for tar, tgz and tbz2 formats. If none
1639
1736
    is given, the top directory will be the root name of the file.
1640
1737
 
 
1738
    If branch is omitted then the branch containing the CWD will be used.
 
1739
 
1641
1740
    Note: export of tree with non-ascii filenames to zip is not supported.
1642
1741
 
1643
1742
     Supported formats       Autodetected by extension
1648
1747
         tgz                      .tar.gz, .tgz
1649
1748
         zip                          .zip
1650
1749
    """
1651
 
    takes_args = ['dest']
 
1750
    takes_args = ['dest', 'branch?']
1652
1751
    takes_options = ['revision', 'format', 'root']
1653
 
    def run(self, dest, revision=None, format=None, root=None):
 
1752
    def run(self, dest, branch=None, revision=None, format=None, root=None):
1654
1753
        from bzrlib.export import export
1655
 
        tree = WorkingTree.open_containing(u'.')[0]
1656
 
        b = tree.branch
 
1754
 
 
1755
        if branch is None:
 
1756
            tree = WorkingTree.open_containing(u'.')[0]
 
1757
            b = tree.branch
 
1758
        else:
 
1759
            b = Branch.open(branch)
 
1760
            
1657
1761
        if revision is None:
1658
1762
            # should be tree.last_revision  FIXME
1659
1763
            rev_id = b.last_revision()
1660
1764
        else:
1661
1765
            if len(revision) != 1:
1662
 
                raise BzrError('bzr export --revision takes exactly 1 argument')
 
1766
                raise errors.BzrCommandError('bzr export --revision takes exactly 1 argument')
1663
1767
            rev_id = revision[0].in_history(b).rev_id
1664
1768
        t = b.repository.revision_tree(rev_id)
1665
1769
        try:
1666
1770
            export(t, dest, format, root)
1667
1771
        except errors.NoSuchExportFormat, e:
1668
 
            raise BzrCommandError('Unsupported export format: %s' % e.format)
 
1772
            raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
1669
1773
 
1670
1774
 
1671
1775
class cmd_cat(Command):
1672
1776
    """Write a file's text from a previous revision."""
1673
1777
 
1674
 
    takes_options = ['revision']
 
1778
    takes_options = ['revision', 'name-from-revision']
1675
1779
    takes_args = ['filename']
 
1780
    encoding_type = 'exact'
1676
1781
 
1677
1782
    @display_command
1678
 
    def run(self, filename, revision=None):
 
1783
    def run(self, filename, revision=None, name_from_revision=False):
1679
1784
        if revision is not None and len(revision) != 1:
1680
 
            raise BzrCommandError("bzr cat --revision takes exactly one number")
 
1785
            raise errors.BzrCommandError("bzr cat --revision takes exactly"
 
1786
                                        " one number")
 
1787
 
1681
1788
        tree = None
1682
1789
        try:
1683
1790
            tree, relpath = WorkingTree.open_containing(filename)
1684
1791
            b = tree.branch
1685
 
        except NotBranchError:
 
1792
        except (errors.NotBranchError, errors.NotLocalUrl):
1686
1793
            pass
1687
1794
 
 
1795
        if revision is not None and revision[0].get_branch() is not None:
 
1796
            b = Branch.open(revision[0].get_branch())
1688
1797
        if tree is None:
1689
1798
            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())
 
1799
            tree = b.basis_tree()
1692
1800
        if revision is None:
1693
1801
            revision_id = b.last_revision()
1694
1802
        else:
1695
1803
            revision_id = revision[0].in_history(b).rev_id
1696
 
        b.print_file(relpath, revision_id)
 
1804
 
 
1805
        cur_file_id = tree.path2id(relpath)
 
1806
        rev_tree = b.repository.revision_tree(revision_id)
 
1807
        old_file_id = rev_tree.path2id(relpath)
 
1808
        
 
1809
        if name_from_revision:
 
1810
            if old_file_id is None:
 
1811
                raise errors.BzrCommandError("%r is not present in revision %s"
 
1812
                                                % (filename, revision_id))
 
1813
            else:
 
1814
                rev_tree.print_file(old_file_id)
 
1815
        elif cur_file_id is not None:
 
1816
            rev_tree.print_file(cur_file_id)
 
1817
        elif old_file_id is not None:
 
1818
            rev_tree.print_file(old_file_id)
 
1819
        else:
 
1820
            raise errors.BzrCommandError("%r is not present in revision %s" %
 
1821
                                         (filename, revision_id))
1697
1822
 
1698
1823
 
1699
1824
class cmd_local_time_offset(Command):
1732
1857
                     Option('unchanged',
1733
1858
                            help='commit even if nothing has changed'),
1734
1859
                     Option('file', type=str, 
 
1860
                            short_name='F',
1735
1861
                            argname='msgfile',
1736
1862
                            help='file containing commit message'),
1737
1863
                     Option('strict',
1753
1879
                StrictCommitFailed)
1754
1880
        from bzrlib.msgeditor import edit_commit_message, \
1755
1881
                make_commit_message_template
1756
 
        from tempfile import TemporaryFile
1757
1882
 
1758
1883
        # TODO: Need a blackbox test for invoking the external editor; may be
1759
1884
        # slightly problematic to run this cross-platform.
1760
1885
 
1761
1886
        # TODO: do more checks that the commit will succeed before 
1762
1887
        # 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
1888
        tree, selected_list = tree_files(selected_list)
1767
1889
        if selected_list == ['']:
1768
1890
            # workaround - commit of root of tree should be exactly the same
1772
1894
 
1773
1895
        if local and not tree.branch.get_bound_location():
1774
1896
            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
1897
 
1787
 
        if message == "":
1788
 
            raise BzrCommandError("empty commit message specified")
 
1898
        def get_message(commit_obj):
 
1899
            """Callback to get commit message"""
 
1900
            my_message = message
 
1901
            if my_message is None and not file:
 
1902
                template = make_commit_message_template(tree, selected_list)
 
1903
                my_message = edit_commit_message(template)
 
1904
                if my_message is None:
 
1905
                    raise errors.BzrCommandError("please specify a commit"
 
1906
                        " message with either --message or --file")
 
1907
            elif my_message and file:
 
1908
                raise errors.BzrCommandError(
 
1909
                    "please specify either --message or --file")
 
1910
            if file:
 
1911
                my_message = codecs.open(file, 'rt', 
 
1912
                                         bzrlib.user_encoding).read()
 
1913
            if my_message == "":
 
1914
                raise errors.BzrCommandError("empty commit message specified")
 
1915
            return my_message
1789
1916
        
1790
1917
        if verbose:
1791
1918
            reporter = ReportCommitToLog()
1792
1919
        else:
1793
1920
            reporter = NullCommitReporter()
1794
 
        
 
1921
 
1795
1922
        try:
1796
 
            tree.commit(message, specific_files=selected_list,
 
1923
            tree.commit(message_callback=get_message,
 
1924
                        specific_files=selected_list,
1797
1925
                        allow_pointless=unchanged, strict=strict, local=local,
1798
1926
                        reporter=reporter)
1799
1927
        except PointlessCommit:
1800
1928
            # FIXME: This should really happen before the file is read in;
1801
1929
            # perhaps prepare the commit; get the message; then actually commit
1802
 
            raise BzrCommandError("no changes to commit."
1803
 
                                  " use --unchanged to commit anyhow")
 
1930
            raise errors.BzrCommandError("no changes to commit."
 
1931
                              " use --unchanged to commit anyhow")
1804
1932
        except ConflictsInTree:
1805
 
            raise BzrCommandError("Conflicts detected in working tree.  "
1806
 
                'Use "bzr conflicts" to list, "bzr resolve FILE" to resolve.')
 
1933
            raise errors.BzrCommandError('Conflicts detected in working '
 
1934
                'tree.  Use "bzr conflicts" to list, "bzr resolve FILE" to'
 
1935
                ' resolve.')
1807
1936
        except StrictCommitFailed:
1808
 
            raise BzrCommandError("Commit refused because there are unknown "
1809
 
                                  "files in the working tree.")
 
1937
            raise errors.BzrCommandError("Commit refused because there are"
 
1938
                              " unknown files in the working tree.")
1810
1939
        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.')
 
1940
            raise errors.BzrCommandError(str(e) + "\n"
 
1941
            'To commit to master branch, run update and then commit.\n'
 
1942
            'You can also pass --local to commit to continue working '
 
1943
            'disconnected.')
 
1944
 
1815
1945
 
1816
1946
class cmd_check(Command):
1817
1947
    """Validate consistency of branch history.
1832
1962
        check(branch, verbose)
1833
1963
 
1834
1964
 
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
1965
class cmd_upgrade(Command):
1855
1966
    """Upgrade branch storage to current format.
1856
1967
 
1860
1971
    """
1861
1972
    takes_args = ['url?']
1862
1973
    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),
 
1974
                    RegistryOption('format',
 
1975
                        help='Upgrade to a specific format. Current formats'
 
1976
                             ' are: default, knit, metaweave and weave.'
 
1977
                             ' Default is knit; metaweave and weave are'
 
1978
                             ' deprecated',
 
1979
                        registry=bzrdir.format_registry,
 
1980
                        converter=get_format_type,
 
1981
                        value_switches=True),
1869
1982
                    ]
1870
1983
 
1871
1984
 
1898
2011
            # use branch if we're inside one; otherwise global config
1899
2012
            try:
1900
2013
                c = Branch.open_containing('.')[0].get_config()
1901
 
            except NotBranchError:
 
2014
            except errors.NotBranchError:
1902
2015
                c = config.GlobalConfig()
1903
2016
            if email:
1904
2017
                self.outf.write(c.user_email() + '\n')
1943
2056
class cmd_selftest(Command):
1944
2057
    """Run internal test suite.
1945
2058
    
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.
 
2059
    This creates temporary test directories in the working directory, but not
 
2060
    existing data is affected.  These directories are deleted if the tests
 
2061
    pass, or left behind to help in debugging if they fail and --keep-output
 
2062
    is specified.
1950
2063
    
1951
 
    If arguments are given, they are regular expressions that say
1952
 
    which tests should run.
 
2064
    If arguments are given, they are regular expressions that say which tests
 
2065
    should run.  Tests matching any expression are run, and other tests are
 
2066
    not run.
 
2067
 
 
2068
    Alternatively if --first is given, matching tests are run first and then
 
2069
    all other tests are run.  This is useful if you have been working in a
 
2070
    particular area, but want to make sure nothing else was broken.
1953
2071
 
1954
2072
    If the global option '--no-plugins' is given, plugins are not loaded
1955
2073
    before running the selftests.  This has two effects: features provided or
1956
2074
    modified by plugins will not be tested, and tests provided by plugins will
1957
2075
    not be run.
1958
2076
 
1959
 
    examples:
 
2077
    examples::
1960
2078
        bzr selftest ignore
 
2079
            run only tests relating to 'ignore'
1961
2080
        bzr --no-plugins selftest -v
 
2081
            disable plugins and list tests as they're run
1962
2082
    """
1963
2083
    # TODO: --list should give a list of all available tests
1964
2084
 
1977
2097
            return FakeNFSServer
1978
2098
        msg = "No known transport type %s. Supported types are: sftp\n" %\
1979
2099
            (typestring)
1980
 
        raise BzrCommandError(msg)
 
2100
        raise errors.BzrCommandError(msg)
1981
2101
 
1982
2102
    hidden = True
1983
2103
    takes_args = ['testspecs*']
1996
2116
                     Option('cache-dir', type=str,
1997
2117
                            help='a directory to cache intermediate'
1998
2118
                                 ' benchmark steps'),
 
2119
                     Option('clean-output',
 
2120
                            help='clean temporary tests directories'
 
2121
                                 ' without running tests'),
 
2122
                     Option('first',
 
2123
                            help='run all tests, but run specified tests first',
 
2124
                            )
1999
2125
                     ]
 
2126
    encoding_type = 'replace'
2000
2127
 
2001
2128
    def run(self, testspecs_list=None, verbose=None, one=False,
2002
2129
            keep_output=False, transport=None, benchmark=None,
2003
 
            lsprof_timed=None, cache_dir=None):
 
2130
            lsprof_timed=None, cache_dir=None, clean_output=False,
 
2131
            first=False):
2004
2132
        import bzrlib.ui
2005
2133
        from bzrlib.tests import selftest
2006
2134
        import bzrlib.benchmarks as benchmarks
2007
2135
        from bzrlib.benchmarks import tree_creator
2008
2136
 
 
2137
        if clean_output:
 
2138
            from bzrlib.tests import clean_selftest_output
 
2139
            clean_selftest_output()
 
2140
            return 0
 
2141
 
2009
2142
        if cache_dir is not None:
2010
2143
            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
2144
        print '%10s: %s' % ('bzr', osutils.realpath(sys.argv[0]))
2016
2145
        print '%10s: %s' % ('bzrlib', bzrlib.__path__[0])
2017
2146
        print
2018
 
        info('running tests...')
 
2147
        if testspecs_list is not None:
 
2148
            pattern = '|'.join(testspecs_list)
 
2149
        else:
 
2150
            pattern = ".*"
 
2151
        if benchmark:
 
2152
            test_suite_factory = benchmarks.test_suite
 
2153
            if verbose is None:
 
2154
                verbose = True
 
2155
            # TODO: should possibly lock the history file...
 
2156
            benchfile = open(".perf_history", "at", buffering=1)
 
2157
        else:
 
2158
            test_suite_factory = None
 
2159
            if verbose is None:
 
2160
                verbose = False
 
2161
            benchfile = None
2019
2162
        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)
 
2163
            result = selftest(verbose=verbose, 
 
2164
                              pattern=pattern,
 
2165
                              stop_on_failure=one, 
 
2166
                              keep_output=keep_output,
 
2167
                              transport=transport,
 
2168
                              test_suite_factory=test_suite_factory,
 
2169
                              lsprof_timed=lsprof_timed,
 
2170
                              bench_history=benchfile,
 
2171
                              matching_tests_first=first,
 
2172
                              )
2053
2173
        finally:
2054
 
            ui.ui_factory = save_ui
 
2174
            if benchfile is not None:
 
2175
                benchfile.close()
 
2176
        if result:
 
2177
            info('tests passed')
 
2178
        else:
 
2179
            info('tests failed')
 
2180
        return int(not result)
2055
2181
 
2056
2182
 
2057
2183
class cmd_version(Command):
2082
2208
    
2083
2209
    @display_command
2084
2210
    def run(self, branch, other):
2085
 
        from bzrlib.revision import common_ancestor, MultipleRevisionSources
 
2211
        from bzrlib.revision import MultipleRevisionSources
2086
2212
        
2087
2213
        branch1 = Branch.open_containing(branch)[0]
2088
2214
        branch2 = Branch.open_containing(other)[0]
2145
2271
    takes_args = ['branch?']
2146
2272
    takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
2147
2273
                     Option('show-base', help="Show base revision text in "
2148
 
                            "conflicts"), 
 
2274
                            "conflicts"),
2149
2275
                     Option('uncommitted', help='Apply uncommitted changes'
2150
 
                            ' from a working copy, instead of branch changes')]
 
2276
                            ' from a working copy, instead of branch changes'),
 
2277
                     Option('pull', help='If the destination is already'
 
2278
                             ' completely merged into the source, pull from the'
 
2279
                             ' source rather than merging. When this happens,'
 
2280
                             ' you do not need to commit the result.'),
 
2281
                     ]
2151
2282
 
2152
2283
    def help(self):
2153
 
        from merge import merge_type_help
2154
2284
        from inspect import getdoc
2155
 
        return getdoc(self) + '\n' + merge_type_help() 
 
2285
        return getdoc(self) + '\n' + _mod_merge.merge_type_help()
2156
2286
 
2157
2287
    def run(self, branch=None, revision=None, force=False, merge_type=None,
2158
2288
            show_base=False, reprocess=False, remember=False, 
2159
 
            uncommitted=False):
 
2289
            uncommitted=False, pull=False):
2160
2290
        if merge_type is None:
2161
 
            merge_type = Merge3Merger
 
2291
            merge_type = _mod_merge.Merge3Merger
2162
2292
 
2163
2293
        tree = WorkingTree.open_containing(u'.')[0]
2164
2294
 
2165
2295
        if branch is not None:
2166
2296
            try:
2167
2297
                reader = bundle.read_bundle_from_url(branch)
2168
 
            except NotABundle:
 
2298
            except errors.NotABundle:
2169
2299
                pass # Continue on considering this url a Branch
2170
2300
            else:
2171
2301
                conflicts = merge_bundle(reader, tree, not force, merge_type,
2189
2319
            other_branch, path = Branch.open_containing(branch)
2190
2320
        else:
2191
2321
            if uncommitted:
2192
 
                raise BzrCommandError('Cannot use --uncommitted and --revision'
2193
 
                                      ' at the same time.')
 
2322
                raise errors.BzrCommandError('Cannot use --uncommitted and'
 
2323
                                             ' --revision at the same time.')
2194
2324
            branch = revision[0].get_branch() or branch
2195
2325
            if len(revision) == 1:
2196
2326
                base = [None, None]
2200
2330
            else:
2201
2331
                assert len(revision) == 2
2202
2332
                if None in revision:
2203
 
                    raise BzrCommandError(
 
2333
                    raise errors.BzrCommandError(
2204
2334
                        "Merge doesn't permit empty revision specifier.")
2205
2335
                base_branch, path = Branch.open_containing(branch)
2206
2336
                branch1 = revision[1].get_branch() or branch
2222
2352
        pb = ui.ui_factory.nested_progress_bar()
2223
2353
        try:
2224
2354
            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)
 
2355
                conflict_count = _merge_helper(
 
2356
                    other, base, check_clean=(not force),
 
2357
                    merge_type=merge_type,
 
2358
                    reprocess=reprocess,
 
2359
                    show_base=show_base,
 
2360
                    pull=pull,
 
2361
                    pb=pb, file_list=interesting_files)
2230
2362
            finally:
2231
2363
                pb.finished()
2232
2364
            if conflict_count != 0:
2253
2385
        stored_location = tree.branch.get_parent()
2254
2386
        mutter("%s", stored_location)
2255
2387
        if stored_location is None:
2256
 
            raise BzrCommandError("No location specified or remembered")
 
2388
            raise errors.BzrCommandError("No location specified or remembered")
2257
2389
        display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
2258
2390
        self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
2259
2391
        return stored_location
2286
2418
                            "conflicts")]
2287
2419
 
2288
2420
    def help(self):
2289
 
        from merge import merge_type_help
2290
2421
        from inspect import getdoc
2291
 
        return getdoc(self) + '\n' + merge_type_help() 
 
2422
        return getdoc(self) + '\n' + _mod_merge.merge_type_help()
2292
2423
 
2293
2424
    def run(self, file_list=None, merge_type=None, show_base=False,
2294
2425
            reprocess=False):
2295
 
        from bzrlib.merge import merge_inner, transform_tree
2296
2426
        if merge_type is None:
2297
 
            merge_type = Merge3Merger
 
2427
            merge_type = _mod_merge.Merge3Merger
2298
2428
        tree, file_list = tree_files(file_list)
2299
2429
        tree.lock_write()
2300
2430
        try:
2301
2431
            parents = tree.get_parent_ids()
2302
2432
            if len(parents) != 2:
2303
 
                raise BzrCommandError("Sorry, remerge only works after normal"
2304
 
                                      " merges.  Not cherrypicking or"
2305
 
                                      " multi-merges.")
 
2433
                raise errors.BzrCommandError("Sorry, remerge only works after normal"
 
2434
                                             " merges.  Not cherrypicking or"
 
2435
                                             " multi-merges.")
2306
2436
            repository = tree.branch.repository
2307
2437
            base_revision = common_ancestor(parents[0],
2308
2438
                                            parents[1], repository)
2316
2446
                for filename in file_list:
2317
2447
                    file_id = tree.path2id(filename)
2318
2448
                    if file_id is None:
2319
 
                        raise NotVersionedError(filename)
 
2449
                        raise errors.NotVersionedError(filename)
2320
2450
                    interesting_ids.add(file_id)
2321
2451
                    if tree.kind(file_id) != "directory":
2322
2452
                        continue
2324
2454
                    for name, ie in tree.inventory.iter_entries(file_id):
2325
2455
                        interesting_ids.add(ie.file_id)
2326
2456
                new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
2327
 
            transform_tree(tree, tree.basis_tree(), interesting_ids)
 
2457
            else:
 
2458
                # Remerge only supports resolving contents conflicts
 
2459
                allowed_conflicts = ('text conflict', 'contents conflict')
 
2460
                restore_files = [c.path for c in conflicts
 
2461
                                 if c.typestring in allowed_conflicts]
 
2462
            _mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
2328
2463
            tree.set_conflicts(ConflictList(new_conflicts))
2329
 
            if file_list is None:
2330
 
                restore_files = list(tree.iter_conflicts())
2331
 
            else:
 
2464
            if file_list is not None:
2332
2465
                restore_files = file_list
2333
2466
            for filename in restore_files:
2334
2467
                try:
2335
2468
                    restore(tree.abspath(filename))
2336
 
                except NotConflicted:
 
2469
                except errors.NotConflicted:
2337
2470
                    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)
 
2471
            conflicts = _mod_merge.merge_inner(
 
2472
                                      tree.branch, other_tree, base_tree,
 
2473
                                      this_tree=tree,
 
2474
                                      interesting_ids=interesting_ids,
 
2475
                                      other_rev_id=parents[1],
 
2476
                                      merge_type=merge_type,
 
2477
                                      show_base=show_base,
 
2478
                                      reprocess=reprocess)
2345
2479
        finally:
2346
2480
            tree.unlock()
2347
2481
        if conflicts > 0:
2349
2483
        else:
2350
2484
            return 0
2351
2485
 
 
2486
 
2352
2487
class cmd_revert(Command):
2353
2488
    """Revert files to a previous revision.
2354
2489
 
2375
2510
    aliases = ['merge-revert']
2376
2511
 
2377
2512
    def run(self, revision=None, no_backup=False, file_list=None):
2378
 
        from bzrlib.commands import parse_spec
2379
2513
        if file_list is not None:
2380
2514
            if len(file_list) == 0:
2381
 
                raise BzrCommandError("No files specified")
 
2515
                raise errors.BzrCommandError("No files specified")
2382
2516
        else:
2383
2517
            file_list = []
2384
2518
        
2387
2521
            # FIXME should be tree.last_revision
2388
2522
            rev_id = tree.last_revision()
2389
2523
        elif len(revision) != 1:
2390
 
            raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
 
2524
            raise errors.BzrCommandError('bzr revert --revision takes exactly 1 argument')
2391
2525
        else:
2392
2526
            rev_id = revision[0].in_history(tree.branch).rev_id
2393
2527
        pb = ui.ui_factory.nested_progress_bar()
2401
2535
 
2402
2536
class cmd_assert_fail(Command):
2403
2537
    """Test reporting of assertion failures"""
 
2538
    # intended just for use in testing
 
2539
 
2404
2540
    hidden = True
 
2541
 
2405
2542
    def run(self):
2406
 
        assert False, "always fails"
 
2543
        raise AssertionError("always fails")
2407
2544
 
2408
2545
 
2409
2546
class cmd_help(Command):
2410
2547
    """Show help on a command or other topic.
2411
2548
 
2412
 
    For a list of all available commands, say 'bzr help commands'."""
 
2549
    For a list of all available commands, say 'bzr help commands'.
 
2550
    """
2413
2551
    takes_options = [Option('long', 'show help on all commands')]
2414
2552
    takes_args = ['topic?']
2415
2553
    aliases = ['?', '--help', '-?', '-h']
2416
2554
    
2417
2555
    @display_command
2418
2556
    def run(self, topic=None, long=False):
2419
 
        import help
 
2557
        import bzrlib.help
2420
2558
        if topic is None and long:
2421
2559
            topic = "commands"
2422
 
        help.help(topic)
 
2560
        bzrlib.help.help(topic)
2423
2561
 
2424
2562
 
2425
2563
class cmd_shell_complete(Command):
2426
2564
    """Show appropriate completions for context.
2427
2565
 
2428
 
    For a list of all available commands, say 'bzr shell-complete'."""
 
2566
    For a list of all available commands, say 'bzr shell-complete'.
 
2567
    """
2429
2568
    takes_args = ['context?']
2430
2569
    aliases = ['s-c']
2431
2570
    hidden = True
2439
2578
class cmd_fetch(Command):
2440
2579
    """Copy in history from another branch but don't merge it.
2441
2580
 
2442
 
    This is an internal method used for pull and merge."""
 
2581
    This is an internal method used for pull and merge.
 
2582
    """
2443
2583
    hidden = True
2444
2584
    takes_args = ['from_branch', 'to_branch']
2445
2585
    def run(self, from_branch, to_branch):
2452
2592
class cmd_missing(Command):
2453
2593
    """Show unmerged/unpulled revisions between two branches.
2454
2594
 
2455
 
    OTHER_BRANCH may be local or remote."""
 
2595
    OTHER_BRANCH may be local or remote.
 
2596
    """
2456
2597
    takes_args = ['other_branch?']
2457
2598
    takes_options = [Option('reverse', 'Reverse the order of revisions'),
2458
2599
                     Option('mine-only', 
2479
2620
        if other_branch is None:
2480
2621
            other_branch = parent
2481
2622
            if other_branch is None:
2482
 
                raise BzrCommandError("No peer location known or specified.")
 
2623
                raise errors.BzrCommandError("No peer location known or specified.")
2483
2624
            print "Using last location: " + local_branch.get_parent()
2484
2625
        remote_branch = Branch.open(other_branch)
2485
2626
        if remote_branch.base == local_branch.base:
2601
2742
    takes_args = ['filename']
2602
2743
    takes_options = [Option('all', help='show annotations on all lines'),
2603
2744
                     Option('long', help='show date in annotations'),
2604
 
                     'revision'
 
2745
                     'revision',
 
2746
                     'show-ids',
2605
2747
                     ]
2606
2748
 
2607
2749
    @display_command
2608
 
    def run(self, filename, all=False, long=False, revision=None):
 
2750
    def run(self, filename, all=False, long=False, revision=None,
 
2751
            show_ids=False):
2609
2752
        from bzrlib.annotate import annotate_file
2610
2753
        tree, relpath = WorkingTree.open_containing(filename)
2611
2754
        branch = tree.branch
2614
2757
            if revision is None:
2615
2758
                revision_id = branch.last_revision()
2616
2759
            elif len(revision) != 1:
2617
 
                raise BzrCommandError('bzr annotate --revision takes exactly 1 argument')
 
2760
                raise errors.BzrCommandError('bzr annotate --revision takes exactly 1 argument')
2618
2761
            else:
2619
2762
                revision_id = revision[0].in_history(branch).rev_id
2620
2763
            file_id = tree.inventory.path2id(relpath)
2621
2764
            tree = branch.repository.revision_tree(revision_id)
2622
2765
            file_version = tree.inventory[file_id].revision
2623
 
            annotate_file(branch, file_version, file_id, long, all, sys.stdout)
 
2766
            annotate_file(branch, file_version, file_id, long, all, sys.stdout,
 
2767
                          show_ids=show_ids)
2624
2768
        finally:
2625
2769
            branch.unlock()
2626
2770
 
2636
2780
    def run(self, revision_id_list=None, revision=None):
2637
2781
        import bzrlib.gpg as gpg
2638
2782
        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')
 
2783
            raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
2640
2784
        if revision_id_list is None and revision is None:
2641
 
            raise BzrCommandError('You must supply either --revision or a revision_id')
 
2785
            raise errors.BzrCommandError('You must supply either --revision or a revision_id')
2642
2786
        b = WorkingTree.open_containing(u'.')[0].branch
2643
2787
        gpg_strategy = gpg.GPGStrategy(b.get_config())
2644
2788
        if revision_id_list is not None:
2657
2801
                if to_revid is None:
2658
2802
                    to_revno = b.revno()
2659
2803
                if from_revno is None or to_revno is None:
2660
 
                    raise BzrCommandError('Cannot sign a range of non-revision-history revisions')
 
2804
                    raise errors.BzrCommandError('Cannot sign a range of non-revision-history revisions')
2661
2805
                for revno in range(from_revno, to_revno + 1):
2662
2806
                    b.repository.sign_revision(b.get_rev_id(revno), 
2663
2807
                                               gpg_strategy)
2664
2808
            else:
2665
 
                raise BzrCommandError('Please supply either one revision, or a range.')
 
2809
                raise errors.BzrCommandError('Please supply either one revision, or a range.')
2666
2810
 
2667
2811
 
2668
2812
class cmd_bind(Command):
2680
2824
        b_other = Branch.open(location)
2681
2825
        try:
2682
2826
            b.bind(b_other)
2683
 
        except DivergedBranches:
2684
 
            raise BzrCommandError('These branches have diverged.'
2685
 
                                  ' Try merging, and then bind again.')
 
2827
        except errors.DivergedBranches:
 
2828
            raise errors.BzrCommandError('These branches have diverged.'
 
2829
                                         ' Try merging, and then bind again.')
2686
2830
 
2687
2831
 
2688
2832
class cmd_unbind(Command):
2698
2842
    def run(self):
2699
2843
        b, relpath = Branch.open_containing(u'.')
2700
2844
        if not b.unbind():
2701
 
            raise BzrCommandError('Local branch is not bound')
 
2845
            raise errors.BzrCommandError('Local branch is not bound')
2702
2846
 
2703
2847
 
2704
2848
class cmd_uncommit(Command):
2853
2997
            url = 'readonly+' + url
2854
2998
        t = get_transport(url)
2855
2999
        if inet:
2856
 
            server = smart.SmartStreamServer(sys.stdin, sys.stdout, t)
 
3000
            server = smart.SmartServerPipeStreamMedium(sys.stdin, sys.stdout, t)
2857
3001
        elif port is not None:
2858
3002
            if ':' in port:
2859
3003
                host, port = port.split(':')
2863
3007
            print 'listening on port: ', server.port
2864
3008
            sys.stdout.flush()
2865
3009
        else:
2866
 
            raise BzrCommandError("bzr serve requires one of --inet or --port")
 
3010
            raise errors.BzrCommandError("bzr serve requires one of --inet or --port")
2867
3011
        server.serve()
2868
3012
 
2869
3013
 
2870
3014
# 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()):
 
3015
def _merge_helper(other_revision, base_revision,
 
3016
                  check_clean=True, ignore_zero=False,
 
3017
                  this_dir=None, backup_files=False,
 
3018
                  merge_type=None,
 
3019
                  file_list=None, show_base=False, reprocess=False,
 
3020
                  pull=False,
 
3021
                  pb=DummyProgress()):
2876
3022
    """Merge changes into a tree.
2877
3023
 
2878
3024
    base_revision
2900
3046
    clients might prefer to call merge.merge_inner(), which has less magic 
2901
3047
    behavior.
2902
3048
    """
2903
 
    from bzrlib.merge import Merger
 
3049
    # Loading it late, so that we don't always have to import bzrlib.merge
 
3050
    if merge_type is None:
 
3051
        merge_type = _mod_merge.Merge3Merger
2904
3052
    if this_dir is None:
2905
3053
        this_dir = u'.'
2906
3054
    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)
 
3055
    if show_base and not merge_type is _mod_merge.Merge3Merger:
 
3056
        raise errors.BzrCommandError("Show-base is not supported for this merge"
 
3057
                                     " type. %s" % merge_type)
2910
3058
    if reprocess and not merge_type.supports_reprocess:
2911
 
        raise BzrCommandError("Conflict reduction is not supported for merge"
2912
 
                              " type %s." % merge_type)
 
3059
        raise errors.BzrCommandError("Conflict reduction is not supported for merge"
 
3060
                                     " type %s." % merge_type)
2913
3061
    if reprocess and show_base:
2914
 
        raise BzrCommandError("Cannot do conflict reduction and show base.")
 
3062
        raise errors.BzrCommandError("Cannot do conflict reduction and show base.")
2915
3063
    try:
2916
 
        merger = Merger(this_tree.branch, this_tree=this_tree, pb=pb)
 
3064
        merger = _mod_merge.Merger(this_tree.branch, this_tree=this_tree,
 
3065
                                   pb=pb)
2917
3066
        merger.pp = ProgressPhase("Merge phase", 5, pb)
2918
3067
        merger.pp.next_phase()
2919
3068
        merger.check_basis(check_clean)
2923
3072
        if merger.base_rev_id == merger.other_rev_id:
2924
3073
            note('Nothing to do.')
2925
3074
            return 0
 
3075
        if file_list is None:
 
3076
            if pull and merger.base_rev_id == merger.this_rev_id:
 
3077
                count = merger.this_tree.pull(merger.this_branch,
 
3078
                        False, merger.other_rev_id)
 
3079
                note('%d revision(s) pulled.' % (count,))
 
3080
                return 0
2926
3081
        merger.backup_files = backup_files
2927
3082
        merger.merge_type = merge_type 
2928
3083
        merger.set_interesting_files(file_list)
2936
3091
    return conflicts
2937
3092
 
2938
3093
 
 
3094
# Compatibility
 
3095
merge = _merge_helper
 
3096
 
 
3097
 
2939
3098
# these get imported and then picked up by the scan for cmd_*
2940
3099
# TODO: Some more consistent way to split command definitions across files;
2941
3100
# we do need to load at least some information about them to know of