~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: John Arbash Meinel
  • Date: 2006-10-31 21:29:02 UTC
  • mfrom: (2104 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2110.
  • Revision ID: john@arbash-meinel.com-20061031212902-4b33920b90e9ce92
[merge] bzr.dev 2104

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
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
 
import bzrlib.tree
58
 
from bzrlib.workingtree import WorkingTree
59
56
 
60
57
 
61
58
def tree_files(file_list, default_branch=u'.'):
62
59
    try:
63
60
        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]))
 
61
    except errors.FileInWrongBranch, e:
 
62
        raise errors.BzrCommandError("%s is not in the same branch as %s" %
 
63
                                     (e.path, file_list[0]))
67
64
 
68
65
 
69
66
# XXX: Bad function name; should possibly also be a class method of
78
75
 
79
76
    :param file_list: Filenames to convert.  
80
77
 
81
 
    :param default_branch: Fallback tree path to use if file_list is empty or None.
 
78
    :param default_branch: Fallback tree path to use if file_list is empty or
 
79
        None.
82
80
 
83
81
    :return: workingtree, [relative_paths]
84
82
    """
85
83
    if file_list is None or len(file_list) == 0:
86
84
        return WorkingTree.open_containing(default_branch)[0], file_list
87
 
    tree = WorkingTree.open_containing(file_list[0])[0]
 
85
    tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
88
86
    new_list = []
89
87
    for filename in file_list:
90
88
        try:
91
 
            new_list.append(tree.relpath(filename))
 
89
            new_list.append(tree.relpath(osutils.dereference_path(filename)))
92
90
        except errors.PathNotChild:
93
 
            raise FileInWrongBranch(tree.branch, filename)
 
91
            raise errors.FileInWrongBranch(tree.branch, filename)
94
92
    return tree, new_list
95
93
 
96
94
 
114
112
        return format
115
113
    msg = "Unknown bzr format %s. Current formats are: default, knit,\n" \
116
114
          "metaweave and weave" % typestring
117
 
    raise BzrCommandError(msg)
 
115
    raise errors.BzrCommandError(msg)
118
116
 
119
117
 
120
118
# TODO: Make sure no commands unconditionally use the working directory as a
195
193
    def run(self, revision_id=None, revision=None):
196
194
 
197
195
        if revision_id is not None and revision is not None:
198
 
            raise BzrCommandError('You can only supply one of revision_id or --revision')
 
196
            raise errors.BzrCommandError('You can only supply one of'
 
197
                                         ' revision_id or --revision')
199
198
        if revision_id is None and revision is None:
200
 
            raise BzrCommandError('You must supply either --revision or a revision_id')
 
199
            raise errors.BzrCommandError('You must supply either'
 
200
                                         ' --revision or a revision_id')
201
201
        b = WorkingTree.open_containing(u'.')[0].branch
202
202
 
203
203
        # TODO: jam 20060112 should cat-revision always output utf-8?
206
206
        elif revision is not None:
207
207
            for rev in revision:
208
208
                if rev is None:
209
 
                    raise BzrCommandError('You cannot specify a NULL revision.')
 
209
                    raise errors.BzrCommandError('You cannot specify a NULL'
 
210
                                                 ' revision.')
210
211
                revno, rev_id = rev.in_history(b)
211
212
                self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
212
213
    
242
243
            for rev in revision_info_list:
243
244
                revs.append(RevisionSpec.from_string(rev))
244
245
        if len(revs) == 0:
245
 
            raise BzrCommandError('You must supply a revision identifier')
 
246
            raise errors.BzrCommandError('You must supply a revision identifier')
246
247
 
247
248
        b = WorkingTree.open_containing(u'.')[0].branch
248
249
 
299
300
                base_tree, base_path = WorkingTree.open_containing(
300
301
                                            file_ids_from)
301
302
            except errors.NoWorkingTree:
302
 
                base_branch, base_path = branch.Branch.open_containing(
 
303
                base_branch, base_path = Branch.open_containing(
303
304
                                            file_ids_from)
304
305
                base_tree = base_branch.basis_tree()
305
306
 
374
375
    @display_command
375
376
    def run(self, revision=None, show_ids=False, kind=None, file_list=None):
376
377
        if kind and kind not in ['file', 'directory', 'symlink']:
377
 
            raise BzrCommandError('invalid kind specified')
 
378
            raise errors.BzrCommandError('invalid kind specified')
378
379
 
379
380
        work_tree, file_list = tree_files(file_list)
380
381
 
381
382
        if revision is not None:
382
383
            if len(revision) > 1:
383
 
                raise BzrCommandError('bzr inventory --revision takes'
384
 
                                      ' exactly one revision identifier')
 
384
                raise errors.BzrCommandError('bzr inventory --revision takes'
 
385
                                             ' exactly one revision identifier')
385
386
            revision_id = revision[0].in_history(work_tree.branch).rev_id
386
387
            tree = work_tree.branch.repository.revision_tree(revision_id)
387
388
                        
395
396
            trees = [tree]
396
397
 
397
398
        if file_list is not None:
398
 
            file_ids = bzrlib.tree.find_ids_across_trees(file_list, trees,
 
399
            file_ids = _mod_tree.find_ids_across_trees(file_list, trees,
399
400
                                                      require_versioned=True)
400
401
            # find_ids_across_trees may include some paths that don't
401
402
            # exist in 'tree'.
437
438
            names_list = []
438
439
 
439
440
        if len(names_list) < 2:
440
 
            raise BzrCommandError("missing file argument")
 
441
            raise errors.BzrCommandError("missing file argument")
441
442
        tree, rel_names = tree_files(names_list)
442
443
        
443
444
        if os.path.isdir(names_list[-1]):
446
447
                self.outf.write("%s => %s\n" % pair)
447
448
        else:
448
449
            if len(names_list) != 2:
449
 
                raise BzrCommandError('to mv multiple files the destination '
450
 
                                      'must be a versioned directory')
 
450
                raise errors.BzrCommandError('to mv multiple files the destination '
 
451
                                             'must be a versioned directory')
451
452
            tree.rename_one(rel_names[0], rel_names[1])
452
453
            self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
453
454
            
481
482
        try:
482
483
            tree_to = WorkingTree.open_containing(u'.')[0]
483
484
            branch_to = tree_to.branch
484
 
        except NoWorkingTree:
 
485
        except errors.NoWorkingTree:
485
486
            tree_to = None
486
487
            branch_to = Branch.open_containing(u'.')[0]
487
488
 
489
490
        if location is not None:
490
491
            try:
491
492
                reader = bundle.read_bundle_from_url(location)
492
 
            except NotABundle:
 
493
            except errors.NotABundle:
493
494
                pass # Continue on considering this url a Branch
494
495
 
495
496
        stored_loc = branch_to.get_parent()
496
497
        if location is None:
497
498
            if stored_loc is None:
498
 
                raise BzrCommandError("No pull location known or specified.")
 
499
                raise errors.BzrCommandError("No pull location known or"
 
500
                                             " specified.")
499
501
            else:
500
502
                display_url = urlutils.unescape_for_display(stored_loc,
501
503
                        self.outf.encoding)
519
521
        elif len(revision) == 1:
520
522
            rev_id = revision[0].in_history(branch_from).rev_id
521
523
        else:
522
 
            raise BzrCommandError('bzr pull --revision takes one value.')
 
524
            raise errors.BzrCommandError('bzr pull --revision takes one value.')
523
525
 
524
526
        old_rh = branch_to.revision_history()
525
527
        if tree_to is not None:
579
581
        stored_loc = br_from.get_push_location()
580
582
        if location is None:
581
583
            if stored_loc is None:
582
 
                raise BzrCommandError("No push location known or specified.")
 
584
                raise errors.BzrCommandError("No push location known or specified.")
583
585
            else:
584
586
                display_url = urlutils.unescape_for_display(stored_loc,
585
587
                        self.outf.encoding)
593
595
        try:
594
596
            dir_to = bzrdir.BzrDir.open(location_url)
595
597
            br_to = dir_to.open_branch()
596
 
        except NotBranchError:
 
598
        except errors.NotBranchError:
597
599
            # create a branch.
598
600
            to_transport = to_transport.clone('..')
599
601
            if not create_prefix:
601
603
                    relurl = to_transport.relpath(location_url)
602
604
                    mutter('creating directory %s => %s', location_url, relurl)
603
605
                    to_transport.mkdir(relurl)
604
 
                except NoSuchFile:
605
 
                    raise BzrCommandError("Parent directory of %s "
606
 
                                          "does not exist." % location)
 
606
                except errors.NoSuchFile:
 
607
                    raise errors.BzrCommandError("Parent directory of %s "
 
608
                                                 "does not exist." % location)
607
609
            else:
608
610
                current = to_transport.base
609
611
                needed = [(to_transport, to_transport.relpath(location_url))]
612
614
                        to_transport, relpath = needed[-1]
613
615
                        to_transport.mkdir(relpath)
614
616
                        needed.pop()
615
 
                    except NoSuchFile:
 
617
                    except errors.NoSuchFile:
616
618
                        new_transport = to_transport.clone('..')
617
619
                        needed.append((new_transport,
618
620
                                       new_transport.relpath(to_transport.base)))
619
621
                        if new_transport.base == to_transport.base:
620
 
                            raise BzrCommandError("Could not create "
621
 
                                                  "path prefix.")
 
622
                            raise errors.BzrCommandError("Could not create "
 
623
                                                         "path prefix.")
622
624
            dir_to = br_from.bzrdir.clone(location_url,
623
625
                revision_id=br_from.last_revision())
624
626
            br_to = dir_to.open_branch()
639
641
                    warning('This transport does not update the working '
640
642
                            'tree of: %s' % (br_to.base,))
641
643
                    count = br_to.pull(br_from, overwrite)
642
 
                except NoWorkingTree:
 
644
                except errors.NoWorkingTree:
643
645
                    count = br_to.pull(br_from, overwrite)
644
646
                else:
645
647
                    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.")
 
648
            except errors.DivergedBranches:
 
649
                raise errors.BzrCommandError('These branches have diverged.'
 
650
                                        '  Try using "merge" and then "push".')
649
651
        note('%d revision(s) pushed.' % (count,))
650
652
 
651
653
        if verbose:
678
680
        if revision is None:
679
681
            revision = [None]
680
682
        elif len(revision) > 1:
681
 
            raise BzrCommandError(
 
683
            raise errors.BzrCommandError(
682
684
                'bzr branch --revision takes exactly 1 revision value')
683
685
        try:
684
686
            br_from = Branch.open(from_location)
685
687
        except OSError, e:
686
688
            if e.errno == errno.ENOENT:
687
 
                raise BzrCommandError('Source location "%s" does not'
688
 
                                      ' exist.' % to_location)
 
689
                raise errors.BzrCommandError('Source location "%s" does not'
 
690
                                             ' exist.' % to_location)
689
691
            else:
690
692
                raise
691
693
        br_from.lock_read()
711
713
            try:
712
714
                to_transport.mkdir('.')
713
715
            except errors.FileExists:
714
 
                raise BzrCommandError('Target directory "%s" already'
715
 
                                      ' exists.' % to_location)
 
716
                raise errors.BzrCommandError('Target directory "%s" already'
 
717
                                             ' exists.' % to_location)
716
718
            except errors.NoSuchFile:
717
 
                raise BzrCommandError('Parent of "%s" does not exist.' %
718
 
                                      to_location)
 
719
                raise errors.BzrCommandError('Parent of "%s" does not exist.'
 
720
                                             % to_location)
719
721
            try:
720
722
                # preserve whatever source format we have.
721
723
                dir = br_from.bzrdir.sprout(to_transport.base,
724
726
            except errors.NoSuchRevision:
725
727
                to_transport.delete_tree('.')
726
728
                msg = "The branch %s has no revision %s." % (from_location, revision[0])
727
 
                raise BzrCommandError(msg)
 
729
                raise errors.BzrCommandError(msg)
728
730
            except errors.UnlistableBranch:
729
731
                osutils.rmtree(to_location)
730
732
                msg = "The branch %s cannot be used as a --basis" % (basis,)
731
 
                raise BzrCommandError(msg)
 
733
                raise errors.BzrCommandError(msg)
732
734
            if name:
733
735
                branch.control_files.put_utf8('branch-name', name)
734
736
            note('Branched %d revision(s).' % branch.revno())
773
775
        if revision is None:
774
776
            revision = [None]
775
777
        elif len(revision) > 1:
776
 
            raise BzrCommandError(
 
778
            raise errors.BzrCommandError(
777
779
                'bzr checkout --revision takes exactly 1 revision value')
778
780
        if branch_location is None:
779
781
            branch_location = osutils.getcwd()
799
801
            os.mkdir(to_location)
800
802
        except OSError, e:
801
803
            if e.errno == errno.EEXIST:
802
 
                raise BzrCommandError('Target directory "%s" already'
803
 
                                      ' exists.' % to_location)
 
804
                raise errors.BzrCommandError('Target directory "%s" already'
 
805
                                             ' exists.' % to_location)
804
806
            if e.errno == errno.ENOENT:
805
 
                raise BzrCommandError('Parent of "%s" does not exist.' %
806
 
                                      to_location)
 
807
                raise errors.BzrCommandError('Parent of "%s" does not exist.'
 
808
                                             % to_location)
807
809
            else:
808
810
                raise
809
811
        old_format = bzrdir.BzrDirFormat.get_default_format()
824
826
 
825
827
    @display_command
826
828
    def run(self, dir=u'.'):
827
 
        from bzrlib.tree import find_renames
828
829
        tree = WorkingTree.open_containing(dir)[0]
829
830
        old_inv = tree.basis_tree().inventory
830
831
        new_inv = tree.read_working_inventory()
831
 
        renames = list(find_renames(old_inv, new_inv))
 
832
        renames = list(_mod_tree.find_renames(old_inv, new_inv))
832
833
        renames.sort()
833
834
        for old_name, new_name in renames:
834
835
            self.outf.write("%s => %s\n" % (old_name, new_name))
849
850
 
850
851
    def run(self, dir='.'):
851
852
        tree = WorkingTree.open_containing(dir)[0]
852
 
        tree.lock_write()
 
853
        master = tree.branch.get_master_branch()
 
854
        if master is not None:
 
855
            tree.lock_write()
 
856
        else:
 
857
            tree.lock_tree_write()
853
858
        try:
854
859
            existing_pending_merges = tree.get_parent_ids()[1:]
855
860
            last_rev = tree.last_revision()
913
918
        tree, file_list = tree_files(file_list)
914
919
        if new is False:
915
920
            if file_list is None:
916
 
                raise BzrCommandError('Specify one or more files to remove, or'
917
 
                                      ' use --new.')
 
921
                raise errors.BzrCommandError('Specify one or more files to'
 
922
                                             ' remove, or use --new.')
918
923
        else:
919
924
            added = tree.changes_from(tree.basis_tree(),
920
925
                specific_files=file_list).added
921
926
            file_list = sorted([f[0] for f in added], reverse=True)
922
927
            if len(file_list) == 0:
923
 
                raise BzrCommandError('No matching files.')
 
928
                raise errors.BzrCommandError('No matching files.')
924
929
        tree.remove(file_list, verbose=verbose, to_file=self.outf)
925
930
 
926
931
 
940
945
        tree, relpath = WorkingTree.open_containing(filename)
941
946
        i = tree.inventory.path2id(relpath)
942
947
        if i is None:
943
 
            raise BzrError("%r is not a versioned file" % filename)
 
948
            raise errors.BzrError("%r is not a versioned file" % filename)
944
949
        else:
945
950
            self.outf.write(i + '\n')
946
951
 
961
966
        inv = tree.inventory
962
967
        fid = inv.path2id(relpath)
963
968
        if fid is None:
964
 
            raise BzrError("%r is not a versioned file" % filename)
 
969
            raise errors.BzrError("%r is not a versioned file" % filename)
965
970
        for fip in inv.get_idpath(fid):
966
971
            self.outf.write(fip + '\n')
967
972
 
1081
1086
                    
1082
1087
        try:
1083
1088
            existing_bzrdir = bzrdir.BzrDir.open(location)
1084
 
        except NotBranchError:
 
1089
        except errors.NotBranchError:
1085
1090
            # really a NotBzrDir error...
1086
1091
            bzrdir.BzrDir.create_branch_convenience(location, format=format)
1087
1092
        else:
 
1093
            from bzrlib.transport.local import LocalTransport
1088
1094
            if existing_bzrdir.has_branch():
1089
1095
                if (isinstance(to_transport, LocalTransport)
1090
1096
                    and not existing_bzrdir.has_workingtree()):
1191
1197
            new_label = 'new/'
1192
1198
        else:
1193
1199
            if not ':' in prefix:
1194
 
                 raise BzrError("--diff-prefix expects two values separated by a colon")
 
1200
                 raise errors.BzrError("--diff-prefix expects two values"
 
1201
                                       " separated by a colon")
1195
1202
            old_label, new_label = prefix.split(":")
1196
1203
        
1197
1204
        try:
1199
1206
            tree2 = None
1200
1207
            b = None
1201
1208
            b2 = None
1202
 
        except FileInWrongBranch:
 
1209
        except errors.FileInWrongBranch:
1203
1210
            if len(file_list) != 2:
1204
 
                raise BzrCommandError("Files are in different branches")
 
1211
                raise errors.BzrCommandError("Files are in different branches")
1205
1212
 
1206
1213
            tree1, file1 = WorkingTree.open_containing(file_list[0])
1207
1214
            tree2, file2 = WorkingTree.open_containing(file_list[1])
1208
1215
            if file1 != "" or file2 != "":
1209
1216
                # FIXME diff those two files. rbc 20051123
1210
 
                raise BzrCommandError("Files are in different branches")
 
1217
                raise errors.BzrCommandError("Files are in different branches")
1211
1218
            file_list = None
1212
 
        except NotBranchError:
 
1219
        except errors.NotBranchError:
1213
1220
            if (revision is not None and len(revision) == 2
1214
1221
                and not revision[0].needs_branch()
1215
1222
                and not revision[1].needs_branch()):
1220
1227
                raise
1221
1228
        if revision is not None:
1222
1229
            if tree2 is not None:
1223
 
                raise BzrCommandError("Can't specify -r with two branches")
 
1230
                raise errors.BzrCommandError("Can't specify -r with two branches")
1224
1231
            if (len(revision) == 1) or (revision[1].spec is None):
1225
1232
                return diff_cmd_helper(tree1, file_list, diff_options,
1226
1233
                                       revision[0], 
1230
1237
                                       revision[0], revision[1],
1231
1238
                                       old_label=old_label, new_label=new_label)
1232
1239
            else:
1233
 
                raise BzrCommandError('bzr diff --revision takes exactly one or two revision identifiers')
 
1240
                raise errors.BzrCommandError('bzr diff --revision takes exactly'
 
1241
                                             ' one or two revision identifiers')
1234
1242
        else:
1235
1243
            if tree2 is not None:
1236
1244
                return show_diff_trees(tree1, tree2, sys.stdout, 
1288
1296
        for file_id in inv:
1289
1297
            if file_id in basis_inv:
1290
1298
                continue
 
1299
            if inv.is_root(file_id) and len(basis_inv) == 0:
 
1300
                continue
1291
1301
            path = inv.id2path(file_id)
1292
1302
            if not os.access(osutils.abspath(path), os.F_OK):
1293
1303
                continue
1371
1381
                    # either no tree, or is remote.
1372
1382
                    inv = b.basis_tree().inventory
1373
1383
                file_id = inv.path2id(fp)
 
1384
                if file_id is None:
 
1385
                    raise errors.BzrCommandError(
 
1386
                        "Path does not have any revision history: %s" %
 
1387
                        location)
1374
1388
        else:
1375
1389
            # local dir only
1376
1390
            # FIXME ? log the current subdir only RBC 20060203 
1392
1406
                # b is taken from revision[0].get_branch(), and
1393
1407
                # show_log will use its revision_history. Having
1394
1408
                # different branches will lead to weird behaviors.
1395
 
                raise BzrCommandError(
 
1409
                raise errors.BzrCommandError(
1396
1410
                    "Log doesn't accept two revisions in different branches.")
1397
1411
            if revision[0].spec is None:
1398
1412
                # missing begin-range means first revision
1406
1420
            else:
1407
1421
                rev2 = revision[1].in_history(b).revno
1408
1422
        else:
1409
 
            raise BzrCommandError('bzr log --revision takes one or two values.')
 
1423
            raise errors.BzrCommandError('bzr log --revision takes one or two values.')
1410
1424
 
1411
1425
        # By this point, the revision numbers are converted to the +ve
1412
1426
        # form if they were supplied in the -ve form, so we can do
1486
1500
            null=False):
1487
1501
 
1488
1502
        if verbose and null:
1489
 
            raise BzrCommandError('Cannot set both --verbose and --null')
 
1503
            raise errors.BzrCommandError('Cannot set both --verbose and --null')
1490
1504
        all = not (unknown or versioned or ignored)
1491
1505
 
1492
1506
        selection = {'I':ignored, '?':unknown, 'V':versioned}
1500
1514
            tree = tree.branch.repository.revision_tree(
1501
1515
                revision[0].in_history(tree.branch).rev_id)
1502
1516
 
1503
 
        for fp, fc, kind, fid, entry in tree.list_files():
 
1517
        for fp, fc, kind, fid, entry in tree.list_files(include_root=False):
1504
1518
            if fp.startswith(relpath):
1505
1519
                fp = fp[len(relpath):]
1506
1520
                if non_recursive and '/' in fp:
1558
1572
                print pattern
1559
1573
            return
1560
1574
        if name_pattern is None:
1561
 
            raise BzrCommandError("ignore requires a NAME_PATTERN")
 
1575
            raise errors.BzrCommandError("ignore requires a NAME_PATTERN")
1562
1576
        tree, relpath = WorkingTree.open_containing(u'.')
1563
1577
        ifn = tree.abspath('.bzrignore')
1564
1578
        if os.path.exists(ifn):
1621
1635
        try:
1622
1636
            revno = int(revno)
1623
1637
        except ValueError:
1624
 
            raise BzrCommandError("not a valid revision-number: %r" % revno)
 
1638
            raise errors.BzrCommandError("not a valid revision-number: %r" % revno)
1625
1639
 
1626
1640
        print WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
1627
1641
 
1659
1673
            rev_id = b.last_revision()
1660
1674
        else:
1661
1675
            if len(revision) != 1:
1662
 
                raise BzrError('bzr export --revision takes exactly 1 argument')
 
1676
                raise errors.BzrError('bzr export --revision takes exactly'
 
1677
                                      ' 1 argument')
1663
1678
            rev_id = revision[0].in_history(b).rev_id
1664
1679
        t = b.repository.revision_tree(rev_id)
1665
1680
        try:
1666
1681
            export(t, dest, format, root)
1667
1682
        except errors.NoSuchExportFormat, e:
1668
 
            raise BzrCommandError('Unsupported export format: %s' % e.format)
 
1683
            raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
1669
1684
 
1670
1685
 
1671
1686
class cmd_cat(Command):
1677
1692
    @display_command
1678
1693
    def run(self, filename, revision=None):
1679
1694
        if revision is not None and len(revision) != 1:
1680
 
            raise BzrCommandError("bzr cat --revision takes exactly one number")
 
1695
            raise errors.BzrCommandError("bzr cat --revision takes exactly one number")
1681
1696
        tree = None
1682
1697
        try:
1683
1698
            tree, relpath = WorkingTree.open_containing(filename)
1684
1699
            b = tree.branch
1685
 
        except NotBranchError:
 
1700
        except errors.NotBranchError:
1686
1701
            pass
1687
1702
 
1688
1703
        if tree is None:
1776
1791
            template = make_commit_message_template(tree, selected_list)
1777
1792
            message = edit_commit_message(template)
1778
1793
            if message is None:
1779
 
                raise BzrCommandError("please specify a commit message"
1780
 
                                      " with either --message or --file")
 
1794
                raise errors.BzrCommandError("please specify a commit message"
 
1795
                                             " with either --message or --file")
1781
1796
        elif message and file:
1782
 
            raise BzrCommandError("please specify either --message or --file")
 
1797
            raise errors.BzrCommandError("please specify either --message or --file")
1783
1798
        
1784
1799
        if file:
1785
1800
            message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1786
1801
 
1787
1802
        if message == "":
1788
 
            raise BzrCommandError("empty commit message specified")
 
1803
            raise errors.BzrCommandError("empty commit message specified")
1789
1804
        
1790
1805
        if verbose:
1791
1806
            reporter = ReportCommitToLog()
1799
1814
        except PointlessCommit:
1800
1815
            # FIXME: This should really happen before the file is read in;
1801
1816
            # perhaps prepare the commit; get the message; then actually commit
1802
 
            raise BzrCommandError("no changes to commit."
1803
 
                                  " use --unchanged to commit anyhow")
 
1817
            raise errors.BzrCommandError("no changes to commit."
 
1818
                                         " use --unchanged to commit anyhow")
1804
1819
        except ConflictsInTree:
1805
 
            raise BzrCommandError("Conflicts detected in working tree.  "
 
1820
            raise errors.BzrCommandError("Conflicts detected in working tree.  "
1806
1821
                'Use "bzr conflicts" to list, "bzr resolve FILE" to resolve.')
1807
1822
        except StrictCommitFailed:
1808
 
            raise BzrCommandError("Commit refused because there are unknown "
1809
 
                                  "files in the working tree.")
 
1823
            raise errors.BzrCommandError("Commit refused because there are unknown "
 
1824
                                         "files in the working tree.")
1810
1825
        except errors.BoundBranchOutOfDate, e:
1811
 
            raise BzrCommandError(str(e) + "\n"
 
1826
            raise errors.BzrCommandError(str(e) + "\n"
1812
1827
                'To commit to master branch, run update and then commit.\n'
1813
1828
                'You can also pass --local to commit to continue working '
1814
1829
                'disconnected.')
1898
1913
            # use branch if we're inside one; otherwise global config
1899
1914
            try:
1900
1915
                c = Branch.open_containing('.')[0].get_config()
1901
 
            except NotBranchError:
 
1916
            except errors.NotBranchError:
1902
1917
                c = config.GlobalConfig()
1903
1918
            if email:
1904
1919
                self.outf.write(c.user_email() + '\n')
1909
1924
        # display a warning if an email address isn't included in the given name.
1910
1925
        try:
1911
1926
            config.extract_email_address(name)
1912
 
        except BzrError, e:
 
1927
        except errors.NoEmailInUsername, e:
1913
1928
            warning('"%s" does not seem to contain an email address.  '
1914
1929
                    'This is allowed, but not recommended.', name)
1915
1930
        
1977
1992
            return FakeNFSServer
1978
1993
        msg = "No known transport type %s. Supported types are: sftp\n" %\
1979
1994
            (typestring)
1980
 
        raise BzrCommandError(msg)
 
1995
        raise errors.BzrCommandError(msg)
1981
1996
 
1982
1997
    hidden = True
1983
1998
    takes_args = ['testspecs*']
2082
2097
    
2083
2098
    @display_command
2084
2099
    def run(self, branch, other):
2085
 
        from bzrlib.revision import common_ancestor, MultipleRevisionSources
 
2100
        from bzrlib.revision import MultipleRevisionSources
2086
2101
        
2087
2102
        branch1 = Branch.open_containing(branch)[0]
2088
2103
        branch2 = Branch.open_containing(other)[0]
2150
2165
                            ' from a working copy, instead of branch changes')]
2151
2166
 
2152
2167
    def help(self):
2153
 
        from merge import merge_type_help
2154
2168
        from inspect import getdoc
2155
 
        return getdoc(self) + '\n' + merge_type_help() 
 
2169
        return getdoc(self) + '\n' + _mod_merge.merge_type_help()
2156
2170
 
2157
2171
    def run(self, branch=None, revision=None, force=False, merge_type=None,
2158
2172
            show_base=False, reprocess=False, remember=False, 
2159
2173
            uncommitted=False):
2160
2174
        if merge_type is None:
2161
 
            merge_type = Merge3Merger
 
2175
            merge_type = _mod_merge.Merge3Merger
2162
2176
 
2163
2177
        tree = WorkingTree.open_containing(u'.')[0]
2164
2178
 
2165
2179
        if branch is not None:
2166
2180
            try:
2167
2181
                reader = bundle.read_bundle_from_url(branch)
2168
 
            except NotABundle:
 
2182
            except errors.NotABundle:
2169
2183
                pass # Continue on considering this url a Branch
2170
2184
            else:
2171
2185
                conflicts = merge_bundle(reader, tree, not force, merge_type,
2189
2203
            other_branch, path = Branch.open_containing(branch)
2190
2204
        else:
2191
2205
            if uncommitted:
2192
 
                raise BzrCommandError('Cannot use --uncommitted and --revision'
2193
 
                                      ' at the same time.')
 
2206
                raise errors.BzrCommandError('Cannot use --uncommitted and'
 
2207
                                             ' --revision at the same time.')
2194
2208
            branch = revision[0].get_branch() or branch
2195
2209
            if len(revision) == 1:
2196
2210
                base = [None, None]
2200
2214
            else:
2201
2215
                assert len(revision) == 2
2202
2216
                if None in revision:
2203
 
                    raise BzrCommandError(
 
2217
                    raise errors.BzrCommandError(
2204
2218
                        "Merge doesn't permit empty revision specifier.")
2205
2219
                base_branch, path = Branch.open_containing(branch)
2206
2220
                branch1 = revision[1].get_branch() or branch
2222
2236
        pb = ui.ui_factory.nested_progress_bar()
2223
2237
        try:
2224
2238
            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)
 
2239
                conflict_count = _merge_helper(
 
2240
                    other, base, check_clean=(not force),
 
2241
                    merge_type=merge_type,
 
2242
                    reprocess=reprocess,
 
2243
                    show_base=show_base,
 
2244
                    pb=pb, file_list=interesting_files)
2230
2245
            finally:
2231
2246
                pb.finished()
2232
2247
            if conflict_count != 0:
2253
2268
        stored_location = tree.branch.get_parent()
2254
2269
        mutter("%s", stored_location)
2255
2270
        if stored_location is None:
2256
 
            raise BzrCommandError("No location specified or remembered")
 
2271
            raise errors.BzrCommandError("No location specified or remembered")
2257
2272
        display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
2258
2273
        self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
2259
2274
        return stored_location
2286
2301
                            "conflicts")]
2287
2302
 
2288
2303
    def help(self):
2289
 
        from merge import merge_type_help
2290
2304
        from inspect import getdoc
2291
 
        return getdoc(self) + '\n' + merge_type_help() 
 
2305
        return getdoc(self) + '\n' + _mod_merge.merge_type_help()
2292
2306
 
2293
2307
    def run(self, file_list=None, merge_type=None, show_base=False,
2294
2308
            reprocess=False):
2295
 
        from bzrlib.merge import merge_inner, transform_tree
2296
2309
        if merge_type is None:
2297
 
            merge_type = Merge3Merger
 
2310
            merge_type = _mod_merge.Merge3Merger
2298
2311
        tree, file_list = tree_files(file_list)
2299
2312
        tree.lock_write()
2300
2313
        try:
2301
2314
            parents = tree.get_parent_ids()
2302
2315
            if len(parents) != 2:
2303
 
                raise BzrCommandError("Sorry, remerge only works after normal"
2304
 
                                      " merges.  Not cherrypicking or"
2305
 
                                      " multi-merges.")
 
2316
                raise errors.BzrCommandError("Sorry, remerge only works after normal"
 
2317
                                             " merges.  Not cherrypicking or"
 
2318
                                             " multi-merges.")
2306
2319
            repository = tree.branch.repository
2307
2320
            base_revision = common_ancestor(parents[0],
2308
2321
                                            parents[1], repository)
2316
2329
                for filename in file_list:
2317
2330
                    file_id = tree.path2id(filename)
2318
2331
                    if file_id is None:
2319
 
                        raise NotVersionedError(filename)
 
2332
                        raise errors.NotVersionedError(filename)
2320
2333
                    interesting_ids.add(file_id)
2321
2334
                    if tree.kind(file_id) != "directory":
2322
2335
                        continue
2324
2337
                    for name, ie in tree.inventory.iter_entries(file_id):
2325
2338
                        interesting_ids.add(ie.file_id)
2326
2339
                new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
2327
 
            transform_tree(tree, tree.basis_tree(), interesting_ids)
 
2340
            else:
 
2341
                # Remerge only supports resolving contents conflicts
 
2342
                allowed_conflicts = ('text conflict', 'contents conflict')
 
2343
                restore_files = [c.path for c in conflicts
 
2344
                                 if c.typestring in allowed_conflicts]
 
2345
            _mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
2328
2346
            tree.set_conflicts(ConflictList(new_conflicts))
2329
 
            if file_list is None:
2330
 
                restore_files = list(tree.iter_conflicts())
2331
 
            else:
 
2347
            if file_list is not None:
2332
2348
                restore_files = file_list
2333
2349
            for filename in restore_files:
2334
2350
                try:
2335
2351
                    restore(tree.abspath(filename))
2336
 
                except NotConflicted:
 
2352
                except errors.NotConflicted:
2337
2353
                    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)
 
2354
            conflicts = _mod_merge.merge_inner(
 
2355
                                      tree.branch, other_tree, base_tree,
 
2356
                                      this_tree=tree,
 
2357
                                      interesting_ids=interesting_ids,
 
2358
                                      other_rev_id=parents[1],
 
2359
                                      merge_type=merge_type,
 
2360
                                      show_base=show_base,
 
2361
                                      reprocess=reprocess)
2345
2362
        finally:
2346
2363
            tree.unlock()
2347
2364
        if conflicts > 0:
2375
2392
    aliases = ['merge-revert']
2376
2393
 
2377
2394
    def run(self, revision=None, no_backup=False, file_list=None):
2378
 
        from bzrlib.commands import parse_spec
2379
2395
        if file_list is not None:
2380
2396
            if len(file_list) == 0:
2381
 
                raise BzrCommandError("No files specified")
 
2397
                raise errors.BzrCommandError("No files specified")
2382
2398
        else:
2383
2399
            file_list = []
2384
2400
        
2387
2403
            # FIXME should be tree.last_revision
2388
2404
            rev_id = tree.last_revision()
2389
2405
        elif len(revision) != 1:
2390
 
            raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
 
2406
            raise errors.BzrCommandError('bzr revert --revision takes exactly 1 argument')
2391
2407
        else:
2392
2408
            rev_id = revision[0].in_history(tree.branch).rev_id
2393
2409
        pb = ui.ui_factory.nested_progress_bar()
2479
2495
        if other_branch is None:
2480
2496
            other_branch = parent
2481
2497
            if other_branch is None:
2482
 
                raise BzrCommandError("No peer location known or specified.")
 
2498
                raise errors.BzrCommandError("No peer location known or specified.")
2483
2499
            print "Using last location: " + local_branch.get_parent()
2484
2500
        remote_branch = Branch.open(other_branch)
2485
2501
        if remote_branch.base == local_branch.base:
2614
2630
            if revision is None:
2615
2631
                revision_id = branch.last_revision()
2616
2632
            elif len(revision) != 1:
2617
 
                raise BzrCommandError('bzr annotate --revision takes exactly 1 argument')
 
2633
                raise errors.BzrCommandError('bzr annotate --revision takes exactly 1 argument')
2618
2634
            else:
2619
2635
                revision_id = revision[0].in_history(branch).rev_id
2620
2636
            file_id = tree.inventory.path2id(relpath)
2636
2652
    def run(self, revision_id_list=None, revision=None):
2637
2653
        import bzrlib.gpg as gpg
2638
2654
        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')
 
2655
            raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
2640
2656
        if revision_id_list is None and revision is None:
2641
 
            raise BzrCommandError('You must supply either --revision or a revision_id')
 
2657
            raise errors.BzrCommandError('You must supply either --revision or a revision_id')
2642
2658
        b = WorkingTree.open_containing(u'.')[0].branch
2643
2659
        gpg_strategy = gpg.GPGStrategy(b.get_config())
2644
2660
        if revision_id_list is not None:
2657
2673
                if to_revid is None:
2658
2674
                    to_revno = b.revno()
2659
2675
                if from_revno is None or to_revno is None:
2660
 
                    raise BzrCommandError('Cannot sign a range of non-revision-history revisions')
 
2676
                    raise errors.BzrCommandError('Cannot sign a range of non-revision-history revisions')
2661
2677
                for revno in range(from_revno, to_revno + 1):
2662
2678
                    b.repository.sign_revision(b.get_rev_id(revno), 
2663
2679
                                               gpg_strategy)
2664
2680
            else:
2665
 
                raise BzrCommandError('Please supply either one revision, or a range.')
 
2681
                raise errors.BzrCommandError('Please supply either one revision, or a range.')
2666
2682
 
2667
2683
 
2668
2684
class cmd_bind(Command):
2680
2696
        b_other = Branch.open(location)
2681
2697
        try:
2682
2698
            b.bind(b_other)
2683
 
        except DivergedBranches:
2684
 
            raise BzrCommandError('These branches have diverged.'
2685
 
                                  ' Try merging, and then bind again.')
 
2699
        except errors.DivergedBranches:
 
2700
            raise errors.BzrCommandError('These branches have diverged.'
 
2701
                                         ' Try merging, and then bind again.')
2686
2702
 
2687
2703
 
2688
2704
class cmd_unbind(Command):
2698
2714
    def run(self):
2699
2715
        b, relpath = Branch.open_containing(u'.')
2700
2716
        if not b.unbind():
2701
 
            raise BzrCommandError('Local branch is not bound')
 
2717
            raise errors.BzrCommandError('Local branch is not bound')
2702
2718
 
2703
2719
 
2704
2720
class cmd_uncommit(Command):
2853
2869
            url = 'readonly+' + url
2854
2870
        t = get_transport(url)
2855
2871
        if inet:
2856
 
            server = smart.SmartStreamServer(sys.stdin, sys.stdout, t)
 
2872
            server = smart.SmartServerPipeStreamMedium(sys.stdin, sys.stdout, t)
2857
2873
        elif port is not None:
2858
2874
            if ':' in port:
2859
2875
                host, port = port.split(':')
2863
2879
            print 'listening on port: ', server.port
2864
2880
            sys.stdout.flush()
2865
2881
        else:
2866
 
            raise BzrCommandError("bzr serve requires one of --inet or --port")
 
2882
            raise errors.BzrCommandError("bzr serve requires one of --inet or --port")
2867
2883
        server.serve()
2868
2884
 
2869
2885
 
2870
2886
# 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()):
 
2887
def _merge_helper(other_revision, base_revision,
 
2888
                  check_clean=True, ignore_zero=False,
 
2889
                  this_dir=None, backup_files=False,
 
2890
                  merge_type=None,
 
2891
                  file_list=None, show_base=False, reprocess=False,
 
2892
                  pb=DummyProgress()):
2876
2893
    """Merge changes into a tree.
2877
2894
 
2878
2895
    base_revision
2900
2917
    clients might prefer to call merge.merge_inner(), which has less magic 
2901
2918
    behavior.
2902
2919
    """
2903
 
    from bzrlib.merge import Merger
 
2920
    # Loading it late, so that we don't always have to import bzrlib.merge
 
2921
    if merge_type is None:
 
2922
        merge_type = _mod_merge.Merge3Merger
2904
2923
    if this_dir is None:
2905
2924
        this_dir = u'.'
2906
2925
    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)
 
2926
    if show_base and not merge_type is _mod_merge.Merge3Merger:
 
2927
        raise errors.BzrCommandError("Show-base is not supported for this merge"
 
2928
                                     " type. %s" % merge_type)
2910
2929
    if reprocess and not merge_type.supports_reprocess:
2911
 
        raise BzrCommandError("Conflict reduction is not supported for merge"
2912
 
                              " type %s." % merge_type)
 
2930
        raise errors.BzrCommandError("Conflict reduction is not supported for merge"
 
2931
                                     " type %s." % merge_type)
2913
2932
    if reprocess and show_base:
2914
 
        raise BzrCommandError("Cannot do conflict reduction and show base.")
 
2933
        raise errors.BzrCommandError("Cannot do conflict reduction and show base.")
2915
2934
    try:
2916
 
        merger = Merger(this_tree.branch, this_tree=this_tree, pb=pb)
 
2935
        merger = _mod_merge.Merger(this_tree.branch, this_tree=this_tree,
 
2936
                                   pb=pb)
2917
2937
        merger.pp = ProgressPhase("Merge phase", 5, pb)
2918
2938
        merger.pp.next_phase()
2919
2939
        merger.check_basis(check_clean)
2936
2956
    return conflicts
2937
2957
 
2938
2958
 
 
2959
# Compatibility
 
2960
merge = _merge_helper
 
2961
 
 
2962
 
2939
2963
# these get imported and then picked up by the scan for cmd_*
2940
2964
# TODO: Some more consistent way to split command definitions across files;
2941
2965
# we do need to load at least some information about them to know of