~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
25
26
 
26
27
import bzrlib
32
33
    errors,
33
34
    ignores,
34
35
    log,
 
36
    merge as _mod_merge,
35
37
    osutils,
36
38
    repository,
37
39
    transport,
 
40
    tree as _mod_tree,
38
41
    ui,
39
42
    urlutils,
40
43
    )
41
 
from bzrlib.branch import Branch, BranchReferenceFormat
42
 
from bzrlib.bundle import read_bundle_from_url
 
44
from bzrlib.branch import Branch
43
45
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
44
46
from bzrlib.conflicts import ConflictList
 
47
from bzrlib.revision import common_ancestor
 
48
from bzrlib.revisionspec import RevisionSpec
 
49
from bzrlib.workingtree import WorkingTree
 
50
""")
 
51
 
45
52
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
53
from bzrlib.option import Option
52
54
from bzrlib.progress import DummyProgress, ProgressPhase
53
 
from bzrlib.revision import common_ancestor
54
 
from bzrlib.revisionspec import RevisionSpec
55
55
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
56
 
from bzrlib.transport.local import LocalTransport
57
 
from bzrlib.workingtree import WorkingTree
58
56
 
59
57
 
60
58
def tree_files(file_list, default_branch=u'.'):
61
59
    try:
62
60
        return internal_tree_files(file_list, default_branch)
63
 
    except FileInWrongBranch, e:
64
 
        raise BzrCommandError("%s is not in the same branch as %s" %
65
 
                             (e.path, file_list[0]))
 
61
    except errors.FileInWrongBranch, e:
 
62
        raise errors.BzrCommandError("%s is not in the same branch as %s" %
 
63
                                     (e.path, file_list[0]))
66
64
 
67
65
 
68
66
# XXX: Bad function name; should possibly also be a class method of
89
87
        try:
90
88
            new_list.append(tree.relpath(filename))
91
89
        except errors.PathNotChild:
92
 
            raise FileInWrongBranch(tree.branch, filename)
 
90
            raise errors.FileInWrongBranch(tree.branch, filename)
93
91
    return tree, new_list
94
92
 
95
93
 
107
105
        format = bzrdir.BzrDirMetaFormat1()
108
106
        format.repository_format = repository.RepositoryFormatKnit1()
109
107
        return format
 
108
    if typestring == "experimental-knit2":
 
109
        format = bzrdir.BzrDirMetaFormat1()
 
110
        format.repository_format = repository.RepositoryFormatKnit2()
 
111
        return format
110
112
    msg = "Unknown bzr format %s. Current formats are: default, knit,\n" \
111
113
          "metaweave and weave" % typestring
112
 
    raise BzrCommandError(msg)
 
114
    raise errors.BzrCommandError(msg)
113
115
 
114
116
 
115
117
# TODO: Make sure no commands unconditionally use the working directory as a
190
192
    def run(self, revision_id=None, revision=None):
191
193
 
192
194
        if revision_id is not None and revision is not None:
193
 
            raise BzrCommandError('You can only supply one of revision_id or --revision')
 
195
            raise errors.BzrCommandError('You can only supply one of'
 
196
                                         ' revision_id or --revision')
194
197
        if revision_id is None and revision is None:
195
 
            raise BzrCommandError('You must supply either --revision or a revision_id')
 
198
            raise errors.BzrCommandError('You must supply either'
 
199
                                         ' --revision or a revision_id')
196
200
        b = WorkingTree.open_containing(u'.')[0].branch
197
201
 
198
202
        # TODO: jam 20060112 should cat-revision always output utf-8?
201
205
        elif revision is not None:
202
206
            for rev in revision:
203
207
                if rev is None:
204
 
                    raise BzrCommandError('You cannot specify a NULL revision.')
 
208
                    raise errors.BzrCommandError('You cannot specify a NULL'
 
209
                                                 ' revision.')
205
210
                revno, rev_id = rev.in_history(b)
206
211
                self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
207
212
    
237
242
            for rev in revision_info_list:
238
243
                revs.append(RevisionSpec.from_string(rev))
239
244
        if len(revs) == 0:
240
 
            raise BzrCommandError('You must supply a revision identifier')
 
245
            raise errors.BzrCommandError('You must supply a revision identifier')
241
246
 
242
247
        b = WorkingTree.open_containing(u'.')[0].branch
243
248
 
294
299
                base_tree, base_path = WorkingTree.open_containing(
295
300
                                            file_ids_from)
296
301
            except errors.NoWorkingTree:
297
 
                base_branch, base_path = branch.Branch.open_containing(
 
302
                base_branch, base_path = Branch.open_containing(
298
303
                                            file_ids_from)
299
304
                base_tree = base_branch.basis_tree()
300
305
 
357
362
    """Show inventory of the current working copy or a revision.
358
363
 
359
364
    It is possible to limit the output to a particular entry
360
 
    type using the --kind option.  For example; --kind file.
 
365
    type using the --kind option.  For example: --kind file.
 
366
 
 
367
    It is also possible to restrict the list of files to a specific
 
368
    set. For example: bzr inventory --show-ids this/file
361
369
    """
362
370
 
363
371
    takes_options = ['revision', 'show-ids', 'kind']
364
 
    
 
372
    takes_args = ['file*']
 
373
 
365
374
    @display_command
366
 
    def run(self, revision=None, show_ids=False, kind=None):
 
375
    def run(self, revision=None, show_ids=False, kind=None, file_list=None):
367
376
        if kind and kind not in ['file', 'directory', 'symlink']:
368
 
            raise BzrCommandError('invalid kind specified')
369
 
        tree = WorkingTree.open_containing(u'.')[0]
370
 
        if revision is None:
371
 
            inv = tree.read_working_inventory()
372
 
        else:
 
377
            raise errors.BzrCommandError('invalid kind specified')
 
378
 
 
379
        work_tree, file_list = tree_files(file_list)
 
380
 
 
381
        if revision is not None:
373
382
            if len(revision) > 1:
374
 
                raise BzrCommandError('bzr inventory --revision takes'
375
 
                    ' exactly one revision identifier')
376
 
            inv = tree.branch.repository.get_revision_inventory(
377
 
                revision[0].in_history(tree.branch).rev_id)
378
 
 
379
 
        for path, entry in inv.entries():
 
383
                raise errors.BzrCommandError('bzr inventory --revision takes'
 
384
                                             ' exactly one revision identifier')
 
385
            revision_id = revision[0].in_history(work_tree.branch).rev_id
 
386
            tree = work_tree.branch.repository.revision_tree(revision_id)
 
387
                        
 
388
            # We include work_tree as well as 'tree' here
 
389
            # So that doing '-r 10 path/foo' will lookup whatever file
 
390
            # exists now at 'path/foo' even if it has been renamed, as
 
391
            # well as whatever files existed in revision 10 at path/foo
 
392
            trees = [tree, work_tree]
 
393
        else:
 
394
            tree = work_tree
 
395
            trees = [tree]
 
396
 
 
397
        if file_list is not None:
 
398
            file_ids = _mod_tree.find_ids_across_trees(file_list, trees,
 
399
                                                      require_versioned=True)
 
400
            # find_ids_across_trees may include some paths that don't
 
401
            # exist in 'tree'.
 
402
            entries = sorted((tree.id2path(file_id), tree.inventory[file_id])
 
403
                             for file_id in file_ids if file_id in tree)
 
404
        else:
 
405
            entries = tree.inventory.entries()
 
406
 
 
407
        for path, entry in entries:
380
408
            if kind and kind != entry.kind:
381
409
                continue
382
410
            if show_ids:
409
437
            names_list = []
410
438
 
411
439
        if len(names_list) < 2:
412
 
            raise BzrCommandError("missing file argument")
 
440
            raise errors.BzrCommandError("missing file argument")
413
441
        tree, rel_names = tree_files(names_list)
414
442
        
415
443
        if os.path.isdir(names_list[-1]):
418
446
                self.outf.write("%s => %s\n" % pair)
419
447
        else:
420
448
            if len(names_list) != 2:
421
 
                raise BzrCommandError('to mv multiple files the destination '
422
 
                                      'must be a versioned directory')
 
449
                raise errors.BzrCommandError('to mv multiple files the destination '
 
450
                                             'must be a versioned directory')
423
451
            tree.rename_one(rel_names[0], rel_names[1])
424
452
            self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
425
453
            
453
481
        try:
454
482
            tree_to = WorkingTree.open_containing(u'.')[0]
455
483
            branch_to = tree_to.branch
456
 
        except NoWorkingTree:
 
484
        except errors.NoWorkingTree:
457
485
            tree_to = None
458
486
            branch_to = Branch.open_containing(u'.')[0]
459
487
 
461
489
        if location is not None:
462
490
            try:
463
491
                reader = bundle.read_bundle_from_url(location)
464
 
            except NotABundle:
 
492
            except errors.NotABundle:
465
493
                pass # Continue on considering this url a Branch
466
494
 
467
495
        stored_loc = branch_to.get_parent()
468
496
        if location is None:
469
497
            if stored_loc is None:
470
 
                raise BzrCommandError("No pull location known or specified.")
 
498
                raise errors.BzrCommandError("No pull location known or"
 
499
                                             " specified.")
471
500
            else:
472
501
                display_url = urlutils.unescape_for_display(stored_loc,
473
502
                        self.outf.encoding)
491
520
        elif len(revision) == 1:
492
521
            rev_id = revision[0].in_history(branch_from).rev_id
493
522
        else:
494
 
            raise BzrCommandError('bzr pull --revision takes one value.')
 
523
            raise errors.BzrCommandError('bzr pull --revision takes one value.')
495
524
 
496
525
        old_rh = branch_to.revision_history()
497
526
        if tree_to is not None:
551
580
        stored_loc = br_from.get_push_location()
552
581
        if location is None:
553
582
            if stored_loc is None:
554
 
                raise BzrCommandError("No push location known or specified.")
 
583
                raise errors.BzrCommandError("No push location known or specified.")
555
584
            else:
556
585
                display_url = urlutils.unescape_for_display(stored_loc,
557
586
                        self.outf.encoding)
565
594
        try:
566
595
            dir_to = bzrdir.BzrDir.open(location_url)
567
596
            br_to = dir_to.open_branch()
568
 
        except NotBranchError:
 
597
        except errors.NotBranchError:
569
598
            # create a branch.
570
599
            to_transport = to_transport.clone('..')
571
600
            if not create_prefix:
573
602
                    relurl = to_transport.relpath(location_url)
574
603
                    mutter('creating directory %s => %s', location_url, relurl)
575
604
                    to_transport.mkdir(relurl)
576
 
                except NoSuchFile:
577
 
                    raise BzrCommandError("Parent directory of %s "
578
 
                                          "does not exist." % location)
 
605
                except errors.NoSuchFile:
 
606
                    raise errors.BzrCommandError("Parent directory of %s "
 
607
                                                 "does not exist." % location)
579
608
            else:
580
609
                current = to_transport.base
581
610
                needed = [(to_transport, to_transport.relpath(location_url))]
584
613
                        to_transport, relpath = needed[-1]
585
614
                        to_transport.mkdir(relpath)
586
615
                        needed.pop()
587
 
                    except NoSuchFile:
 
616
                    except errors.NoSuchFile:
588
617
                        new_transport = to_transport.clone('..')
589
618
                        needed.append((new_transport,
590
619
                                       new_transport.relpath(to_transport.base)))
591
620
                        if new_transport.base == to_transport.base:
592
 
                            raise BzrCommandError("Could not create "
593
 
                                                  "path prefix.")
 
621
                            raise errors.BzrCommandError("Could not create "
 
622
                                                         "path prefix.")
594
623
            dir_to = br_from.bzrdir.clone(location_url,
595
624
                revision_id=br_from.last_revision())
596
625
            br_to = dir_to.open_branch()
611
640
                    warning('This transport does not update the working '
612
641
                            'tree of: %s' % (br_to.base,))
613
642
                    count = br_to.pull(br_from, overwrite)
614
 
                except NoWorkingTree:
 
643
                except errors.NoWorkingTree:
615
644
                    count = br_to.pull(br_from, overwrite)
616
645
                else:
617
646
                    count = tree_to.pull(br_from, overwrite)
618
 
            except DivergedBranches:
619
 
                raise BzrCommandError("These branches have diverged."
620
 
                                      "  Try a merge then push with overwrite.")
 
647
            except errors.DivergedBranches:
 
648
                raise errors.BzrCommandError('These branches have diverged.'
 
649
                                        '  Try using "merge" and then "push".')
621
650
        note('%d revision(s) pushed.' % (count,))
622
651
 
623
652
        if verbose:
650
679
        if revision is None:
651
680
            revision = [None]
652
681
        elif len(revision) > 1:
653
 
            raise BzrCommandError(
 
682
            raise errors.BzrCommandError(
654
683
                'bzr branch --revision takes exactly 1 revision value')
655
684
        try:
656
685
            br_from = Branch.open(from_location)
657
686
        except OSError, e:
658
687
            if e.errno == errno.ENOENT:
659
 
                raise BzrCommandError('Source location "%s" does not'
660
 
                                      ' exist.' % to_location)
 
688
                raise errors.BzrCommandError('Source location "%s" does not'
 
689
                                             ' exist.' % to_location)
661
690
            else:
662
691
                raise
663
692
        br_from.lock_read()
683
712
            try:
684
713
                to_transport.mkdir('.')
685
714
            except errors.FileExists:
686
 
                raise BzrCommandError('Target directory "%s" already'
687
 
                                      ' exists.' % to_location)
 
715
                raise errors.BzrCommandError('Target directory "%s" already'
 
716
                                             ' exists.' % to_location)
688
717
            except errors.NoSuchFile:
689
 
                raise BzrCommandError('Parent of "%s" does not exist.' %
690
 
                                      to_location)
 
718
                raise errors.BzrCommandError('Parent of "%s" does not exist.'
 
719
                                             % to_location)
691
720
            try:
692
721
                # preserve whatever source format we have.
693
722
                dir = br_from.bzrdir.sprout(to_transport.base,
696
725
            except errors.NoSuchRevision:
697
726
                to_transport.delete_tree('.')
698
727
                msg = "The branch %s has no revision %s." % (from_location, revision[0])
699
 
                raise BzrCommandError(msg)
 
728
                raise errors.BzrCommandError(msg)
700
729
            except errors.UnlistableBranch:
701
730
                osutils.rmtree(to_location)
702
731
                msg = "The branch %s cannot be used as a --basis" % (basis,)
703
 
                raise BzrCommandError(msg)
 
732
                raise errors.BzrCommandError(msg)
704
733
            if name:
705
734
                branch.control_files.put_utf8('branch-name', name)
706
735
            note('Branched %d revision(s).' % branch.revno())
745
774
        if revision is None:
746
775
            revision = [None]
747
776
        elif len(revision) > 1:
748
 
            raise BzrCommandError(
 
777
            raise errors.BzrCommandError(
749
778
                'bzr checkout --revision takes exactly 1 revision value')
750
779
        if branch_location is None:
751
780
            branch_location = osutils.getcwd()
760
789
        # if the source and to_location are the same, 
761
790
        # and there is no working tree,
762
791
        # then reconstitute a branch
763
 
        if (osutils.abspath(to_location) == 
 
792
        if (osutils.abspath(to_location) ==
764
793
            osutils.abspath(branch_location)):
765
794
            try:
766
795
                source.bzrdir.open_workingtree()
771
800
            os.mkdir(to_location)
772
801
        except OSError, e:
773
802
            if e.errno == errno.EEXIST:
774
 
                raise BzrCommandError('Target directory "%s" already'
775
 
                                      ' exists.' % to_location)
 
803
                raise errors.BzrCommandError('Target directory "%s" already'
 
804
                                             ' exists.' % to_location)
776
805
            if e.errno == errno.ENOENT:
777
 
                raise BzrCommandError('Parent of "%s" does not exist.' %
778
 
                                      to_location)
 
806
                raise errors.BzrCommandError('Parent of "%s" does not exist.'
 
807
                                             % to_location)
779
808
            else:
780
809
                raise
781
810
        old_format = bzrdir.BzrDirFormat.get_default_format()
796
825
 
797
826
    @display_command
798
827
    def run(self, dir=u'.'):
799
 
        from bzrlib.tree import find_renames
800
828
        tree = WorkingTree.open_containing(dir)[0]
801
829
        old_inv = tree.basis_tree().inventory
802
830
        new_inv = tree.read_working_inventory()
803
 
        renames = list(find_renames(old_inv, new_inv))
 
831
        renames = list(_mod_tree.find_renames(old_inv, new_inv))
804
832
        renames.sort()
805
833
        for old_name, new_name in renames:
806
834
            self.outf.write("%s => %s\n" % (old_name, new_name))
823
851
        tree = WorkingTree.open_containing(dir)[0]
824
852
        tree.lock_write()
825
853
        try:
826
 
            existing_pending_merges = tree.pending_merges()
 
854
            existing_pending_merges = tree.get_parent_ids()[1:]
827
855
            last_rev = tree.last_revision()
828
856
            if last_rev == tree.branch.last_revision():
829
857
                # may be up to date, check master too.
835
863
            conflicts = tree.update()
836
864
            revno = tree.branch.revision_id_to_revno(tree.last_revision())
837
865
            note('Updated to revision %d.' % (revno,))
838
 
            if tree.pending_merges() != existing_pending_merges:
 
866
            if tree.get_parent_ids()[1:] != existing_pending_merges:
839
867
                note('Your local commits will now show as pending merges with '
840
868
                     "'bzr status', and can be committed with 'bzr commit'.")
841
869
            if conflicts != 0:
885
913
        tree, file_list = tree_files(file_list)
886
914
        if new is False:
887
915
            if file_list is None:
888
 
                raise BzrCommandError('Specify one or more files to remove, or'
889
 
                                      ' use --new.')
 
916
                raise errors.BzrCommandError('Specify one or more files to'
 
917
                                             ' remove, or use --new.')
890
918
        else:
891
919
            added = tree.changes_from(tree.basis_tree(),
892
920
                specific_files=file_list).added
893
921
            file_list = sorted([f[0] for f in added], reverse=True)
894
922
            if len(file_list) == 0:
895
 
                raise BzrCommandError('No matching files.')
 
923
                raise errors.BzrCommandError('No matching files.')
896
924
        tree.remove(file_list, verbose=verbose, to_file=self.outf)
897
925
 
898
926
 
911
939
    def run(self, filename):
912
940
        tree, relpath = WorkingTree.open_containing(filename)
913
941
        i = tree.inventory.path2id(relpath)
914
 
        if i == None:
915
 
            raise BzrError("%r is not a versioned file" % filename)
 
942
        if i is None:
 
943
            raise errors.BzrError("%r is not a versioned file" % filename)
916
944
        else:
917
945
            self.outf.write(i + '\n')
918
946
 
932
960
        tree, relpath = WorkingTree.open_containing(filename)
933
961
        inv = tree.inventory
934
962
        fid = inv.path2id(relpath)
935
 
        if fid == None:
936
 
            raise BzrError("%r is not a versioned file" % filename)
 
963
        if fid is None:
 
964
            raise errors.BzrError("%r is not a versioned file" % filename)
937
965
        for fip in inv.get_idpath(fid):
938
966
            self.outf.write(fip + '\n')
939
967
 
996
1024
            last_revision = wt.last_revision()
997
1025
 
998
1026
        revision_ids = b.repository.get_ancestry(last_revision)
999
 
        assert revision_ids[0] == None
 
1027
        assert revision_ids[0] is None
1000
1028
        revision_ids.pop(0)
1001
1029
        for revision_id in revision_ids:
1002
1030
            self.outf.write(revision_id + '\n')
1053
1081
                    
1054
1082
        try:
1055
1083
            existing_bzrdir = bzrdir.BzrDir.open(location)
1056
 
        except NotBranchError:
 
1084
        except errors.NotBranchError:
1057
1085
            # really a NotBzrDir error...
1058
1086
            bzrdir.BzrDir.create_branch_convenience(location, format=format)
1059
1087
        else:
 
1088
            from bzrlib.transport.local import LocalTransport
1060
1089
            if existing_bzrdir.has_branch():
1061
1090
                if (isinstance(to_transport, LocalTransport)
1062
1091
                    and not existing_bzrdir.has_workingtree()):
1163
1192
            new_label = 'new/'
1164
1193
        else:
1165
1194
            if not ':' in prefix:
1166
 
                 raise BzrError("--diff-prefix expects two values separated by a colon")
 
1195
                 raise errors.BzrError("--diff-prefix expects two values"
 
1196
                                       " separated by a colon")
1167
1197
            old_label, new_label = prefix.split(":")
1168
1198
        
1169
1199
        try:
1171
1201
            tree2 = None
1172
1202
            b = None
1173
1203
            b2 = None
1174
 
        except FileInWrongBranch:
 
1204
        except errors.FileInWrongBranch:
1175
1205
            if len(file_list) != 2:
1176
 
                raise BzrCommandError("Files are in different branches")
 
1206
                raise errors.BzrCommandError("Files are in different branches")
1177
1207
 
1178
1208
            tree1, file1 = WorkingTree.open_containing(file_list[0])
1179
1209
            tree2, file2 = WorkingTree.open_containing(file_list[1])
1180
1210
            if file1 != "" or file2 != "":
1181
1211
                # FIXME diff those two files. rbc 20051123
1182
 
                raise BzrCommandError("Files are in different branches")
 
1212
                raise errors.BzrCommandError("Files are in different branches")
1183
1213
            file_list = None
1184
 
        except NotBranchError:
 
1214
        except errors.NotBranchError:
1185
1215
            if (revision is not None and len(revision) == 2
1186
1216
                and not revision[0].needs_branch()
1187
1217
                and not revision[1].needs_branch()):
1192
1222
                raise
1193
1223
        if revision is not None:
1194
1224
            if tree2 is not None:
1195
 
                raise BzrCommandError("Can't specify -r with two branches")
 
1225
                raise errors.BzrCommandError("Can't specify -r with two branches")
1196
1226
            if (len(revision) == 1) or (revision[1].spec is None):
1197
1227
                return diff_cmd_helper(tree1, file_list, diff_options,
1198
1228
                                       revision[0], 
1202
1232
                                       revision[0], revision[1],
1203
1233
                                       old_label=old_label, new_label=new_label)
1204
1234
            else:
1205
 
                raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
 
1235
                raise errors.BzrCommandError('bzr diff --revision takes exactly'
 
1236
                                             ' one or two revision identifiers')
1206
1237
        else:
1207
1238
            if tree2 is not None:
1208
1239
                return show_diff_trees(tree1, tree2, sys.stdout, 
1260
1291
        for file_id in inv:
1261
1292
            if file_id in basis_inv:
1262
1293
                continue
 
1294
            if inv.is_root(file_id) and len(basis_inv) == 0:
 
1295
                continue
1263
1296
            path = inv.id2path(file_id)
1264
1297
            if not os.access(osutils.abspath(path), os.F_OK):
1265
1298
                continue
1346
1379
        else:
1347
1380
            # local dir only
1348
1381
            # FIXME ? log the current subdir only RBC 20060203 
1349
 
            dir, relpath = bzrdir.BzrDir.open_containing('.')
 
1382
            if revision is not None \
 
1383
                    and len(revision) > 0 and revision[0].get_branch():
 
1384
                location = revision[0].get_branch()
 
1385
            else:
 
1386
                location = '.'
 
1387
            dir, relpath = bzrdir.BzrDir.open_containing(location)
1350
1388
            b = dir.open_branch()
1351
1389
 
1352
1390
        if revision is None:
1355
1393
        elif len(revision) == 1:
1356
1394
            rev1 = rev2 = revision[0].in_history(b).revno
1357
1395
        elif len(revision) == 2:
 
1396
            if revision[1].get_branch() != revision[0].get_branch():
 
1397
                # b is taken from revision[0].get_branch(), and
 
1398
                # show_log will use its revision_history. Having
 
1399
                # different branches will lead to weird behaviors.
 
1400
                raise errors.BzrCommandError(
 
1401
                    "Log doesn't accept two revisions in different branches.")
1358
1402
            if revision[0].spec is None:
1359
1403
                # missing begin-range means first revision
1360
1404
                rev1 = 1
1367
1411
            else:
1368
1412
                rev2 = revision[1].in_history(b).revno
1369
1413
        else:
1370
 
            raise BzrCommandError('bzr log --revision takes one or two values.')
 
1414
            raise errors.BzrCommandError('bzr log --revision takes one or two values.')
1371
1415
 
1372
1416
        # By this point, the revision numbers are converted to the +ve
1373
1417
        # form if they were supplied in the -ve form, so we can do
1375
1419
        if rev1 > rev2:
1376
1420
            (rev2, rev1) = (rev1, rev2)
1377
1421
 
1378
 
        if (log_format == None):
 
1422
        if (log_format is None):
1379
1423
            default = b.get_config().log_format()
1380
1424
            log_format = get_log_format(long=long, short=short, line=line, 
1381
1425
                                        default=default)
1447
1491
            null=False):
1448
1492
 
1449
1493
        if verbose and null:
1450
 
            raise BzrCommandError('Cannot set both --verbose and --null')
 
1494
            raise errors.BzrCommandError('Cannot set both --verbose and --null')
1451
1495
        all = not (unknown or versioned or ignored)
1452
1496
 
1453
1497
        selection = {'I':ignored, '?':unknown, 'V':versioned}
1461
1505
            tree = tree.branch.repository.revision_tree(
1462
1506
                revision[0].in_history(tree.branch).rev_id)
1463
1507
 
1464
 
        for fp, fc, kind, fid, entry in tree.list_files():
 
1508
        for fp, fc, kind, fid, entry in tree.list_files(include_root=False):
1465
1509
            if fp.startswith(relpath):
1466
1510
                fp = fp[len(relpath):]
1467
1511
                if non_recursive and '/' in fp:
1519
1563
                print pattern
1520
1564
            return
1521
1565
        if name_pattern is None:
1522
 
            raise BzrCommandError("ignore requires a NAME_PATTERN")
 
1566
            raise errors.BzrCommandError("ignore requires a NAME_PATTERN")
1523
1567
        tree, relpath = WorkingTree.open_containing(u'.')
1524
1568
        ifn = tree.abspath('.bzrignore')
1525
1569
        if os.path.exists(ifn):
1582
1626
        try:
1583
1627
            revno = int(revno)
1584
1628
        except ValueError:
1585
 
            raise BzrCommandError("not a valid revision-number: %r" % revno)
 
1629
            raise errors.BzrCommandError("not a valid revision-number: %r" % revno)
1586
1630
 
1587
1631
        print WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
1588
1632
 
1620
1664
            rev_id = b.last_revision()
1621
1665
        else:
1622
1666
            if len(revision) != 1:
1623
 
                raise BzrError('bzr export --revision takes exactly 1 argument')
 
1667
                raise errors.BzrError('bzr export --revision takes exactly'
 
1668
                                      ' 1 argument')
1624
1669
            rev_id = revision[0].in_history(b).rev_id
1625
1670
        t = b.repository.revision_tree(rev_id)
1626
1671
        try:
1627
1672
            export(t, dest, format, root)
1628
1673
        except errors.NoSuchExportFormat, e:
1629
 
            raise BzrCommandError('Unsupported export format: %s' % e.format)
 
1674
            raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
1630
1675
 
1631
1676
 
1632
1677
class cmd_cat(Command):
1638
1683
    @display_command
1639
1684
    def run(self, filename, revision=None):
1640
1685
        if revision is not None and len(revision) != 1:
1641
 
            raise BzrCommandError("bzr cat --revision takes exactly one number")
 
1686
            raise errors.BzrCommandError("bzr cat --revision takes exactly one number")
1642
1687
        tree = None
1643
1688
        try:
1644
1689
            tree, relpath = WorkingTree.open_containing(filename)
1645
1690
            b = tree.branch
1646
 
        except NotBranchError:
 
1691
        except errors.NotBranchError:
1647
1692
            pass
1648
1693
 
1649
1694
        if tree is None:
1650
1695
            b, relpath = Branch.open_containing(filename)
 
1696
        if revision is not None and revision[0].get_branch() is not None:
 
1697
            b = Branch.open(revision[0].get_branch())
1651
1698
        if revision is None:
1652
1699
            revision_id = b.last_revision()
1653
1700
        else:
1735
1782
            template = make_commit_message_template(tree, selected_list)
1736
1783
            message = edit_commit_message(template)
1737
1784
            if message is None:
1738
 
                raise BzrCommandError("please specify a commit message"
1739
 
                                      " with either --message or --file")
 
1785
                raise errors.BzrCommandError("please specify a commit message"
 
1786
                                             " with either --message or --file")
1740
1787
        elif message and file:
1741
 
            raise BzrCommandError("please specify either --message or --file")
 
1788
            raise errors.BzrCommandError("please specify either --message or --file")
1742
1789
        
1743
1790
        if file:
1744
1791
            message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1745
1792
 
1746
1793
        if message == "":
1747
 
            raise BzrCommandError("empty commit message specified")
 
1794
            raise errors.BzrCommandError("empty commit message specified")
1748
1795
        
1749
1796
        if verbose:
1750
1797
            reporter = ReportCommitToLog()
1758
1805
        except PointlessCommit:
1759
1806
            # FIXME: This should really happen before the file is read in;
1760
1807
            # perhaps prepare the commit; get the message; then actually commit
1761
 
            raise BzrCommandError("no changes to commit."
1762
 
                                  " use --unchanged to commit anyhow")
 
1808
            raise errors.BzrCommandError("no changes to commit."
 
1809
                                         " use --unchanged to commit anyhow")
1763
1810
        except ConflictsInTree:
1764
 
            raise BzrCommandError("Conflicts detected in working tree.  "
 
1811
            raise errors.BzrCommandError("Conflicts detected in working tree.  "
1765
1812
                'Use "bzr conflicts" to list, "bzr resolve FILE" to resolve.')
1766
1813
        except StrictCommitFailed:
1767
 
            raise BzrCommandError("Commit refused because there are unknown "
1768
 
                                  "files in the working tree.")
 
1814
            raise errors.BzrCommandError("Commit refused because there are unknown "
 
1815
                                         "files in the working tree.")
1769
1816
        except errors.BoundBranchOutOfDate, e:
1770
 
            raise BzrCommandError(str(e) + "\n"
 
1817
            raise errors.BzrCommandError(str(e) + "\n"
1771
1818
                'To commit to master branch, run update and then commit.\n'
1772
1819
                'You can also pass --local to commit to continue working '
1773
1820
                'disconnected.')
1857
1904
            # use branch if we're inside one; otherwise global config
1858
1905
            try:
1859
1906
                c = Branch.open_containing('.')[0].get_config()
1860
 
            except NotBranchError:
 
1907
            except errors.NotBranchError:
1861
1908
                c = config.GlobalConfig()
1862
1909
            if email:
1863
1910
                self.outf.write(c.user_email() + '\n')
1868
1915
        # display a warning if an email address isn't included in the given name.
1869
1916
        try:
1870
1917
            config.extract_email_address(name)
1871
 
        except BzrError, e:
 
1918
        except errors.NoEmailInUsername, e:
1872
1919
            warning('"%s" does not seem to contain an email address.  '
1873
1920
                    'This is allowed, but not recommended.', name)
1874
1921
        
1936
1983
            return FakeNFSServer
1937
1984
        msg = "No known transport type %s. Supported types are: sftp\n" %\
1938
1985
            (typestring)
1939
 
        raise BzrCommandError(msg)
 
1986
        raise errors.BzrCommandError(msg)
1940
1987
 
1941
1988
    hidden = True
1942
1989
    takes_args = ['testspecs*']
1985
2032
                test_suite_factory = benchmarks.test_suite
1986
2033
                if verbose is None:
1987
2034
                    verbose = True
 
2035
                # TODO: should possibly lock the history file...
1988
2036
                benchfile = open(".perf_history", "at")
1989
2037
            else:
1990
2038
                test_suite_factory = None
2040
2088
    
2041
2089
    @display_command
2042
2090
    def run(self, branch, other):
2043
 
        from bzrlib.revision import common_ancestor, MultipleRevisionSources
 
2091
        from bzrlib.revision import MultipleRevisionSources
2044
2092
        
2045
2093
        branch1 = Branch.open_containing(branch)[0]
2046
2094
        branch2 = Branch.open_containing(other)[0]
2108
2156
                            ' from a working copy, instead of branch changes')]
2109
2157
 
2110
2158
    def help(self):
2111
 
        from merge import merge_type_help
2112
2159
        from inspect import getdoc
2113
 
        return getdoc(self) + '\n' + merge_type_help() 
 
2160
        return getdoc(self) + '\n' + _mod_merge.merge_type_help()
2114
2161
 
2115
2162
    def run(self, branch=None, revision=None, force=False, merge_type=None,
2116
2163
            show_base=False, reprocess=False, remember=False, 
2117
2164
            uncommitted=False):
2118
2165
        if merge_type is None:
2119
 
            merge_type = Merge3Merger
 
2166
            merge_type = _mod_merge.Merge3Merger
2120
2167
 
2121
2168
        tree = WorkingTree.open_containing(u'.')[0]
2122
2169
 
2123
2170
        if branch is not None:
2124
2171
            try:
2125
2172
                reader = bundle.read_bundle_from_url(branch)
2126
 
            except NotABundle:
 
2173
            except errors.NotABundle:
2127
2174
                pass # Continue on considering this url a Branch
2128
2175
            else:
2129
2176
                conflicts = merge_bundle(reader, tree, not force, merge_type,
2133
2180
                else:
2134
2181
                    return 1
2135
2182
 
2136
 
        branch = self._get_remembered_parent(tree, branch, 'Merging from')
 
2183
        if revision is None \
 
2184
                or len(revision) < 1 or revision[0].needs_branch():
 
2185
            branch = self._get_remembered_parent(tree, branch, 'Merging from')
2137
2186
 
2138
2187
        if revision is None or len(revision) < 1:
2139
2188
            if uncommitted:
2145
2194
            other_branch, path = Branch.open_containing(branch)
2146
2195
        else:
2147
2196
            if uncommitted:
2148
 
                raise BzrCommandError('Cannot use --uncommitted and --revision'
2149
 
                                      ' at the same time.')
 
2197
                raise errors.BzrCommandError('Cannot use --uncommitted and'
 
2198
                                             ' --revision at the same time.')
 
2199
            branch = revision[0].get_branch() or branch
2150
2200
            if len(revision) == 1:
2151
2201
                base = [None, None]
2152
2202
                other_branch, path = Branch.open_containing(branch)
2155
2205
            else:
2156
2206
                assert len(revision) == 2
2157
2207
                if None in revision:
2158
 
                    raise BzrCommandError(
2159
 
                        "Merge doesn't permit that revision specifier.")
2160
 
                other_branch, path = Branch.open_containing(branch)
 
2208
                    raise errors.BzrCommandError(
 
2209
                        "Merge doesn't permit empty revision specifier.")
 
2210
                base_branch, path = Branch.open_containing(branch)
 
2211
                branch1 = revision[1].get_branch() or branch
 
2212
                other_branch, path1 = Branch.open_containing(branch1)
 
2213
                if revision[0].get_branch() is not None:
 
2214
                    # then path was obtained from it, and is None.
 
2215
                    path = path1
2161
2216
 
2162
 
                base = [branch, revision[0].in_history(other_branch).revno]
2163
 
                other = [branch, revision[1].in_history(other_branch).revno]
 
2217
                base = [branch, revision[0].in_history(base_branch).revno]
 
2218
                other = [branch1, revision[1].in_history(other_branch).revno]
2164
2219
 
2165
2220
        if tree.branch.get_parent() is None or remember:
2166
2221
            tree.branch.set_parent(other_branch.base)
2172
2227
        pb = ui.ui_factory.nested_progress_bar()
2173
2228
        try:
2174
2229
            try:
2175
 
                conflict_count = merge(other, base, check_clean=(not force),
2176
 
                                       merge_type=merge_type,
2177
 
                                       reprocess=reprocess,
2178
 
                                       show_base=show_base,
2179
 
                                       pb=pb, file_list=interesting_files)
 
2230
                conflict_count = _merge_helper(
 
2231
                    other, base, check_clean=(not force),
 
2232
                    merge_type=merge_type,
 
2233
                    reprocess=reprocess,
 
2234
                    show_base=show_base,
 
2235
                    pb=pb, file_list=interesting_files)
2180
2236
            finally:
2181
2237
                pb.finished()
2182
2238
            if conflict_count != 0:
2203
2259
        stored_location = tree.branch.get_parent()
2204
2260
        mutter("%s", stored_location)
2205
2261
        if stored_location is None:
2206
 
            raise BzrCommandError("No location specified or remembered")
 
2262
            raise errors.BzrCommandError("No location specified or remembered")
2207
2263
        display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
2208
2264
        self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
2209
2265
        return stored_location
2236
2292
                            "conflicts")]
2237
2293
 
2238
2294
    def help(self):
2239
 
        from merge import merge_type_help
2240
2295
        from inspect import getdoc
2241
 
        return getdoc(self) + '\n' + merge_type_help() 
 
2296
        return getdoc(self) + '\n' + _mod_merge.merge_type_help()
2242
2297
 
2243
2298
    def run(self, file_list=None, merge_type=None, show_base=False,
2244
2299
            reprocess=False):
2245
 
        from bzrlib.merge import merge_inner, transform_tree
2246
2300
        if merge_type is None:
2247
 
            merge_type = Merge3Merger
 
2301
            merge_type = _mod_merge.Merge3Merger
2248
2302
        tree, file_list = tree_files(file_list)
2249
2303
        tree.lock_write()
2250
2304
        try:
2251
2305
            parents = tree.get_parent_ids()
2252
2306
            if len(parents) != 2:
2253
 
                raise BzrCommandError("Sorry, remerge only works after normal"
2254
 
                                      " merges.  Not cherrypicking or"
2255
 
                                      " multi-merges.")
 
2307
                raise errors.BzrCommandError("Sorry, remerge only works after normal"
 
2308
                                             " merges.  Not cherrypicking or"
 
2309
                                             " multi-merges.")
2256
2310
            repository = tree.branch.repository
2257
2311
            base_revision = common_ancestor(parents[0],
2258
2312
                                            parents[1], repository)
2266
2320
                for filename in file_list:
2267
2321
                    file_id = tree.path2id(filename)
2268
2322
                    if file_id is None:
2269
 
                        raise NotVersionedError(filename)
 
2323
                        raise errors.NotVersionedError(filename)
2270
2324
                    interesting_ids.add(file_id)
2271
2325
                    if tree.kind(file_id) != "directory":
2272
2326
                        continue
2274
2328
                    for name, ie in tree.inventory.iter_entries(file_id):
2275
2329
                        interesting_ids.add(ie.file_id)
2276
2330
                new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
2277
 
            transform_tree(tree, tree.basis_tree(), interesting_ids)
 
2331
            _mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
2278
2332
            tree.set_conflicts(ConflictList(new_conflicts))
2279
2333
            if file_list is None:
2280
2334
                restore_files = list(tree.iter_conflicts())
2283
2337
            for filename in restore_files:
2284
2338
                try:
2285
2339
                    restore(tree.abspath(filename))
2286
 
                except NotConflicted:
 
2340
                except errors.NotConflicted:
2287
2341
                    pass
2288
 
            conflicts = merge_inner(tree.branch, other_tree, base_tree,
2289
 
                                    this_tree=tree,
2290
 
                                    interesting_ids=interesting_ids,
2291
 
                                    other_rev_id=parents[1],
2292
 
                                    merge_type=merge_type,
2293
 
                                    show_base=show_base,
2294
 
                                    reprocess=reprocess)
 
2342
            conflicts = _mod_merge.merge_inner(
 
2343
                                      tree.branch, other_tree, base_tree,
 
2344
                                      this_tree=tree,
 
2345
                                      interesting_ids=interesting_ids,
 
2346
                                      other_rev_id=parents[1],
 
2347
                                      merge_type=merge_type,
 
2348
                                      show_base=show_base,
 
2349
                                      reprocess=reprocess)
2295
2350
        finally:
2296
2351
            tree.unlock()
2297
2352
        if conflicts > 0:
2300
2355
            return 0
2301
2356
 
2302
2357
class cmd_revert(Command):
2303
 
    """Reverse all changes since the last commit.
2304
 
 
2305
 
    Only versioned files are affected.  Specify filenames to revert only 
2306
 
    those files.  By default, any files that are changed will be backed up
2307
 
    first.  Backup files have a '~' appended to their name.
 
2358
    """Revert files to a previous revision.
 
2359
 
 
2360
    Giving a list of files will revert only those files.  Otherwise, all files
 
2361
    will be reverted.  If the revision is not specified with '--revision', the
 
2362
    last committed revision is used.
 
2363
 
 
2364
    To remove only some changes, without reverting to a prior version, use
 
2365
    merge instead.  For example, "merge . --r-2..-3" will remove the changes
 
2366
    introduced by -2, without affecting the changes introduced by -1.  Or
 
2367
    to remove certain changes on a hunk-by-hunk basis, see the Shelf plugin.
 
2368
    
 
2369
    By default, any files that have been manually changed will be backed up
 
2370
    first.  (Files changed only by merge are not backed up.)  Backup files have
 
2371
    '.~#~' appended to their name, where # is a number.
 
2372
 
 
2373
    When you provide files, you can use their current pathname or the pathname
 
2374
    from the target revision.  So you can use revert to "undelete" a file by
 
2375
    name.  If you name a directory, all the contents of that directory will be
 
2376
    reverted.
2308
2377
    """
2309
2378
    takes_options = ['revision', 'no-backup']
2310
2379
    takes_args = ['file*']
2311
2380
    aliases = ['merge-revert']
2312
2381
 
2313
2382
    def run(self, revision=None, no_backup=False, file_list=None):
2314
 
        from bzrlib.commands import parse_spec
2315
2383
        if file_list is not None:
2316
2384
            if len(file_list) == 0:
2317
 
                raise BzrCommandError("No files specified")
 
2385
                raise errors.BzrCommandError("No files specified")
2318
2386
        else:
2319
2387
            file_list = []
2320
2388
        
2323
2391
            # FIXME should be tree.last_revision
2324
2392
            rev_id = tree.last_revision()
2325
2393
        elif len(revision) != 1:
2326
 
            raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
 
2394
            raise errors.BzrCommandError('bzr revert --revision takes exactly 1 argument')
2327
2395
        else:
2328
2396
            rev_id = revision[0].in_history(tree.branch).rev_id
2329
2397
        pb = ui.ui_factory.nested_progress_bar()
2415
2483
        if other_branch is None:
2416
2484
            other_branch = parent
2417
2485
            if other_branch is None:
2418
 
                raise BzrCommandError("No peer location known or specified.")
 
2486
                raise errors.BzrCommandError("No peer location known or specified.")
2419
2487
            print "Using last location: " + local_branch.get_parent()
2420
2488
        remote_branch = Branch.open(other_branch)
2421
2489
        if remote_branch.base == local_branch.base:
2425
2493
            remote_branch.lock_read()
2426
2494
            try:
2427
2495
                local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
2428
 
                if (log_format == None):
 
2496
                if (log_format is None):
2429
2497
                    default = local_branch.get_config().log_format()
2430
2498
                    log_format = get_log_format(long=long, short=short, 
2431
2499
                                                line=line, default=default)
2479
2547
        import bzrlib.plugin
2480
2548
        from inspect import getdoc
2481
2549
        for name, plugin in bzrlib.plugin.all_plugins().items():
2482
 
            if hasattr(plugin, '__path__'):
 
2550
            if getattr(plugin, '__path__', None) is not None:
2483
2551
                print plugin.__path__[0]
2484
 
            elif hasattr(plugin, '__file__'):
 
2552
            elif getattr(plugin, '__file__', None) is not None:
2485
2553
                print plugin.__file__
2486
2554
            else:
2487
 
                print `plugin`
 
2555
                print repr(plugin)
2488
2556
                
2489
2557
            d = getdoc(plugin)
2490
2558
            if d:
2550
2618
            if revision is None:
2551
2619
                revision_id = branch.last_revision()
2552
2620
            elif len(revision) != 1:
2553
 
                raise BzrCommandError('bzr annotate --revision takes exactly 1 argument')
 
2621
                raise errors.BzrCommandError('bzr annotate --revision takes exactly 1 argument')
2554
2622
            else:
2555
2623
                revision_id = revision[0].in_history(branch).rev_id
2556
2624
            file_id = tree.inventory.path2id(relpath)
2572
2640
    def run(self, revision_id_list=None, revision=None):
2573
2641
        import bzrlib.gpg as gpg
2574
2642
        if revision_id_list is not None and revision is not None:
2575
 
            raise BzrCommandError('You can only supply one of revision_id or --revision')
 
2643
            raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
2576
2644
        if revision_id_list is None and revision is None:
2577
 
            raise BzrCommandError('You must supply either --revision or a revision_id')
 
2645
            raise errors.BzrCommandError('You must supply either --revision or a revision_id')
2578
2646
        b = WorkingTree.open_containing(u'.')[0].branch
2579
2647
        gpg_strategy = gpg.GPGStrategy(b.get_config())
2580
2648
        if revision_id_list is not None:
2593
2661
                if to_revid is None:
2594
2662
                    to_revno = b.revno()
2595
2663
                if from_revno is None or to_revno is None:
2596
 
                    raise BzrCommandError('Cannot sign a range of non-revision-history revisions')
 
2664
                    raise errors.BzrCommandError('Cannot sign a range of non-revision-history revisions')
2597
2665
                for revno in range(from_revno, to_revno + 1):
2598
2666
                    b.repository.sign_revision(b.get_rev_id(revno), 
2599
2667
                                               gpg_strategy)
2600
2668
            else:
2601
 
                raise BzrCommandError('Please supply either one revision, or a range.')
 
2669
                raise errors.BzrCommandError('Please supply either one revision, or a range.')
2602
2670
 
2603
2671
 
2604
2672
class cmd_bind(Command):
2616
2684
        b_other = Branch.open(location)
2617
2685
        try:
2618
2686
            b.bind(b_other)
2619
 
        except DivergedBranches:
2620
 
            raise BzrCommandError('These branches have diverged.'
2621
 
                                  ' Try merging, and then bind again.')
 
2687
        except errors.DivergedBranches:
 
2688
            raise errors.BzrCommandError('These branches have diverged.'
 
2689
                                         ' Try merging, and then bind again.')
2622
2690
 
2623
2691
 
2624
2692
class cmd_unbind(Command):
2634
2702
    def run(self):
2635
2703
        b, relpath = Branch.open_containing(u'.')
2636
2704
        if not b.unbind():
2637
 
            raise BzrCommandError('Local branch is not bound')
 
2705
            raise errors.BzrCommandError('Local branch is not bound')
2638
2706
 
2639
2707
 
2640
2708
class cmd_uncommit(Command):
2742
2810
            pass
2743
2811
        
2744
2812
 
 
2813
class cmd_wait_until_signalled(Command):
 
2814
    """Test helper for test_start_and_stop_bzr_subprocess_send_signal.
 
2815
 
 
2816
    This just prints a line to signal when it is ready, then blocks on stdin.
 
2817
    """
 
2818
 
 
2819
    hidden = True
 
2820
 
 
2821
    def run(self):
 
2822
        sys.stdout.write("running\n")
 
2823
        sys.stdout.flush()
 
2824
        sys.stdin.readline()
 
2825
 
 
2826
 
 
2827
class cmd_serve(Command):
 
2828
    """Run the bzr server."""
 
2829
 
 
2830
    aliases = ['server']
 
2831
 
 
2832
    takes_options = [
 
2833
        Option('inet',
 
2834
               help='serve on stdin/out for use from inetd or sshd'),
 
2835
        Option('port',
 
2836
               help='listen for connections on nominated port of the form '
 
2837
                    '[hostname:]portnumber. Passing 0 as the port number will '
 
2838
                    'result in a dynamically allocated port.',
 
2839
               type=str),
 
2840
        Option('directory',
 
2841
               help='serve contents of directory',
 
2842
               type=unicode),
 
2843
        Option('allow-writes',
 
2844
               help='By default the server is a readonly server. Supplying '
 
2845
                    '--allow-writes enables write access to the contents of '
 
2846
                    'the served directory and below. '
 
2847
                ),
 
2848
        ]
 
2849
 
 
2850
    def run(self, port=None, inet=False, directory=None, allow_writes=False):
 
2851
        from bzrlib.transport import smart
 
2852
        from bzrlib.transport import get_transport
 
2853
        if directory is None:
 
2854
            directory = os.getcwd()
 
2855
        url = urlutils.local_path_to_url(directory)
 
2856
        if not allow_writes:
 
2857
            url = 'readonly+' + url
 
2858
        t = get_transport(url)
 
2859
        if inet:
 
2860
            server = smart.SmartServerPipeStreamMedium(sys.stdin, sys.stdout, t)
 
2861
        elif port is not None:
 
2862
            if ':' in port:
 
2863
                host, port = port.split(':')
 
2864
            else:
 
2865
                host = '127.0.0.1'
 
2866
            server = smart.SmartTCPServer(t, host=host, port=int(port))
 
2867
            print 'listening on port: ', server.port
 
2868
            sys.stdout.flush()
 
2869
        else:
 
2870
            raise errors.BzrCommandError("bzr serve requires one of --inet or --port")
 
2871
        server.serve()
 
2872
 
2745
2873
 
2746
2874
# command-line interpretation helper for merge-related commands
2747
 
def merge(other_revision, base_revision,
2748
 
          check_clean=True, ignore_zero=False,
2749
 
          this_dir=None, backup_files=False, merge_type=Merge3Merger,
2750
 
          file_list=None, show_base=False, reprocess=False,
2751
 
          pb=DummyProgress()):
 
2875
def _merge_helper(other_revision, base_revision,
 
2876
                  check_clean=True, ignore_zero=False,
 
2877
                  this_dir=None, backup_files=False,
 
2878
                  merge_type=None,
 
2879
                  file_list=None, show_base=False, reprocess=False,
 
2880
                  pb=DummyProgress()):
2752
2881
    """Merge changes into a tree.
2753
2882
 
2754
2883
    base_revision
2776
2905
    clients might prefer to call merge.merge_inner(), which has less magic 
2777
2906
    behavior.
2778
2907
    """
2779
 
    from bzrlib.merge import Merger
 
2908
    # Loading it late, so that we don't always have to import bzrlib.merge
 
2909
    if merge_type is None:
 
2910
        merge_type = _mod_merge.Merge3Merger
2780
2911
    if this_dir is None:
2781
2912
        this_dir = u'.'
2782
2913
    this_tree = WorkingTree.open_containing(this_dir)[0]
2783
 
    if show_base and not merge_type is Merge3Merger:
2784
 
        raise BzrCommandError("Show-base is not supported for this merge"
2785
 
                              " type. %s" % merge_type)
 
2914
    if show_base and not merge_type is _mod_merge.Merge3Merger:
 
2915
        raise errors.BzrCommandError("Show-base is not supported for this merge"
 
2916
                                     " type. %s" % merge_type)
2786
2917
    if reprocess and not merge_type.supports_reprocess:
2787
 
        raise BzrCommandError("Conflict reduction is not supported for merge"
2788
 
                              " type %s." % merge_type)
 
2918
        raise errors.BzrCommandError("Conflict reduction is not supported for merge"
 
2919
                                     " type %s." % merge_type)
2789
2920
    if reprocess and show_base:
2790
 
        raise BzrCommandError("Cannot do conflict reduction and show base.")
 
2921
        raise errors.BzrCommandError("Cannot do conflict reduction and show base.")
2791
2922
    try:
2792
 
        merger = Merger(this_tree.branch, this_tree=this_tree, pb=pb)
 
2923
        merger = _mod_merge.Merger(this_tree.branch, this_tree=this_tree,
 
2924
                                   pb=pb)
2793
2925
        merger.pp = ProgressPhase("Merge phase", 5, pb)
2794
2926
        merger.pp.next_phase()
2795
2927
        merger.check_basis(check_clean)
2812
2944
    return conflicts
2813
2945
 
2814
2946
 
 
2947
# Compatibility
 
2948
merge = _merge_helper
 
2949
 
 
2950
 
2815
2951
# these get imported and then picked up by the scan for cmd_*
2816
2952
# TODO: Some more consistent way to split command definitions across files;
2817
2953
# we do need to load at least some information about them to know of 
2818
2954
# aliases.  ideally we would avoid loading the implementation until the
2819
2955
# details were needed.
 
2956
from bzrlib.cmd_version_info import cmd_version_info
2820
2957
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
2821
2958
from bzrlib.bundle.commands import cmd_bundle_revisions
2822
2959
from bzrlib.sign_my_commits import cmd_sign_my_commits