~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-11 00:23:23 UTC
  • mfrom: (2070 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2071.
  • Revision ID: john@arbash-meinel.com-20061011002323-82ba88c293d7caff
[merge] bzr.dev 2070

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Copyright (C) 2004, 2005, 2006 by 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
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
7
 
 
 
7
#
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
12
 
 
 
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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
27
 
from bzrlib.branch import Branch, BranchReferenceFormat
28
 
from bzrlib import (bundle, branch, bzrdir, errors, osutils, ui, config,
29
 
    repository, log)
30
 
from bzrlib.bundle import read_bundle_from_url
 
28
from bzrlib import (
 
29
    branch,
 
30
    bundle,
 
31
    bzrdir,
 
32
    config,
 
33
    errors,
 
34
    ignores,
 
35
    log,
 
36
    merge as _mod_merge,
 
37
    osutils,
 
38
    repository,
 
39
    transport,
 
40
    tree as _mod_tree,
 
41
    ui,
 
42
    urlutils,
 
43
    )
 
44
from bzrlib.branch import Branch
31
45
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
32
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
 
33
52
from bzrlib.commands import Command, display_command
34
 
from bzrlib.errors import (BzrError, BzrCheckError, BzrCommandError, 
35
 
                           NotBranchError, DivergedBranches, NotConflicted,
36
 
                           NoSuchFile, NoWorkingTree, FileInWrongBranch,
37
 
                           NotVersionedError, NotABundle)
38
 
from bzrlib.merge import Merge3Merger
39
53
from bzrlib.option import Option
40
54
from bzrlib.progress import DummyProgress, ProgressPhase
41
 
from bzrlib.revision import common_ancestor
42
 
from bzrlib.revisionspec import RevisionSpec
43
55
from bzrlib.trace import mutter, note, log_error, warning, is_quiet, info
44
 
from bzrlib.transport.local import LocalTransport
45
 
import bzrlib.urlutils as urlutils
46
 
from bzrlib.workingtree import WorkingTree
47
56
 
48
57
 
49
58
def tree_files(file_list, default_branch=u'.'):
50
59
    try:
51
60
        return internal_tree_files(file_list, default_branch)
52
 
    except FileInWrongBranch, e:
53
 
        raise BzrCommandError("%s is not in the same branch as %s" %
54
 
                             (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]))
55
64
 
56
65
 
57
66
# XXX: Bad function name; should possibly also be a class method of
78
87
        try:
79
88
            new_list.append(tree.relpath(filename))
80
89
        except errors.PathNotChild:
81
 
            raise FileInWrongBranch(tree.branch, filename)
 
90
            raise errors.FileInWrongBranch(tree.branch, filename)
82
91
    return tree, new_list
83
92
 
84
93
 
96
105
        format = bzrdir.BzrDirMetaFormat1()
97
106
        format.repository_format = repository.RepositoryFormatKnit1()
98
107
        return format
 
108
    if typestring == "experimental-knit2":
 
109
        format = bzrdir.BzrDirMetaFormat1()
 
110
        format.repository_format = repository.RepositoryFormatKnit2()
 
111
        return format
99
112
    msg = "Unknown bzr format %s. Current formats are: default, knit,\n" \
100
113
          "metaweave and weave" % typestring
101
 
    raise BzrCommandError(msg)
 
114
    raise errors.BzrCommandError(msg)
102
115
 
103
116
 
104
117
# TODO: Make sure no commands unconditionally use the working directory as a
179
192
    def run(self, revision_id=None, revision=None):
180
193
 
181
194
        if revision_id is not None and revision is not None:
182
 
            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')
183
197
        if revision_id is None and revision is None:
184
 
            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')
185
200
        b = WorkingTree.open_containing(u'.')[0].branch
186
201
 
187
202
        # TODO: jam 20060112 should cat-revision always output utf-8?
190
205
        elif revision is not None:
191
206
            for rev in revision:
192
207
                if rev is None:
193
 
                    raise BzrCommandError('You cannot specify a NULL revision.')
 
208
                    raise errors.BzrCommandError('You cannot specify a NULL'
 
209
                                                 ' revision.')
194
210
                revno, rev_id = rev.in_history(b)
195
211
                self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
196
212
    
224
240
            revs.extend(revision)
225
241
        if revision_info_list is not None:
226
242
            for rev in revision_info_list:
227
 
                revs.append(RevisionSpec(rev))
 
243
                revs.append(RevisionSpec.from_string(rev))
228
244
        if len(revs) == 0:
229
 
            raise BzrCommandError('You must supply a revision identifier')
 
245
            raise errors.BzrCommandError('You must supply a revision identifier')
230
246
 
231
247
        b = WorkingTree.open_containing(u'.')[0].branch
232
248
 
263
279
 
264
280
    --dry-run will show which files would be added, but not actually 
265
281
    add them.
 
282
 
 
283
    --file-ids-from will try to use the file ids from the supplied path.
 
284
    It looks up ids trying to find a matching parent directory with the
 
285
    same filename, and then by pure path.
266
286
    """
267
287
    takes_args = ['file*']
268
 
    takes_options = ['no-recurse', 'dry-run', 'verbose']
 
288
    takes_options = ['no-recurse', 'dry-run', 'verbose',
 
289
                     Option('file-ids-from', type=unicode,
 
290
                            help='Lookup file ids from here')]
269
291
    encoding_type = 'replace'
270
292
 
271
 
    def run(self, file_list, no_recurse=False, dry_run=False, verbose=False):
 
293
    def run(self, file_list, no_recurse=False, dry_run=False, verbose=False,
 
294
            file_ids_from=None):
272
295
        import bzrlib.add
273
296
 
274
 
        action = bzrlib.add.AddAction(to_file=self.outf,
275
 
            should_print=(not is_quiet()))
276
 
 
277
 
        added, ignored = bzrlib.add.smart_add(file_list, not no_recurse, 
 
297
        if file_ids_from is not None:
 
298
            try:
 
299
                base_tree, base_path = WorkingTree.open_containing(
 
300
                                            file_ids_from)
 
301
            except errors.NoWorkingTree:
 
302
                base_branch, base_path = Branch.open_containing(
 
303
                                            file_ids_from)
 
304
                base_tree = base_branch.basis_tree()
 
305
 
 
306
            action = bzrlib.add.AddFromBaseAction(base_tree, base_path,
 
307
                          to_file=self.outf, should_print=(not is_quiet()))
 
308
        else:
 
309
            action = bzrlib.add.AddAction(to_file=self.outf,
 
310
                should_print=(not is_quiet()))
 
311
 
 
312
        added, ignored = bzrlib.add.smart_add(file_list, not no_recurse,
278
313
                                              action=action, save=not dry_run)
279
314
        if len(ignored) > 0:
280
315
            if verbose:
327
362
    """Show inventory of the current working copy or a revision.
328
363
 
329
364
    It is possible to limit the output to a particular entry
330
 
    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
331
369
    """
332
370
 
333
371
    takes_options = ['revision', 'show-ids', 'kind']
334
 
    
 
372
    takes_args = ['file*']
 
373
 
335
374
    @display_command
336
 
    def run(self, revision=None, show_ids=False, kind=None):
 
375
    def run(self, revision=None, show_ids=False, kind=None, file_list=None):
337
376
        if kind and kind not in ['file', 'directory', 'symlink']:
338
 
            raise BzrCommandError('invalid kind specified')
339
 
        tree = WorkingTree.open_containing(u'.')[0]
340
 
        if revision is None:
341
 
            inv = tree.read_working_inventory()
342
 
        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:
343
382
            if len(revision) > 1:
344
 
                raise BzrCommandError('bzr inventory --revision takes'
345
 
                    ' exactly one revision identifier')
346
 
            inv = tree.branch.repository.get_revision_inventory(
347
 
                revision[0].in_history(tree.branch).rev_id)
348
 
 
349
 
        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:
350
408
            if kind and kind != entry.kind:
351
409
                continue
352
410
            if show_ids:
379
437
            names_list = []
380
438
 
381
439
        if len(names_list) < 2:
382
 
            raise BzrCommandError("missing file argument")
 
440
            raise errors.BzrCommandError("missing file argument")
383
441
        tree, rel_names = tree_files(names_list)
384
442
        
385
443
        if os.path.isdir(names_list[-1]):
388
446
                self.outf.write("%s => %s\n" % pair)
389
447
        else:
390
448
            if len(names_list) != 2:
391
 
                raise BzrCommandError('to mv multiple files the destination '
392
 
                                      'must be a versioned directory')
 
449
                raise errors.BzrCommandError('to mv multiple files the destination '
 
450
                                             'must be a versioned directory')
393
451
            tree.rename_one(rel_names[0], rel_names[1])
394
452
            self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
395
453
            
423
481
        try:
424
482
            tree_to = WorkingTree.open_containing(u'.')[0]
425
483
            branch_to = tree_to.branch
426
 
        except NoWorkingTree:
 
484
        except errors.NoWorkingTree:
427
485
            tree_to = None
428
486
            branch_to = Branch.open_containing(u'.')[0]
429
487
 
431
489
        if location is not None:
432
490
            try:
433
491
                reader = bundle.read_bundle_from_url(location)
434
 
            except NotABundle:
 
492
            except errors.NotABundle:
435
493
                pass # Continue on considering this url a Branch
436
494
 
437
495
        stored_loc = branch_to.get_parent()
438
496
        if location is None:
439
497
            if stored_loc is None:
440
 
                raise BzrCommandError("No pull location known or specified.")
 
498
                raise errors.BzrCommandError("No pull location known or"
 
499
                                             " specified.")
441
500
            else:
442
501
                display_url = urlutils.unescape_for_display(stored_loc,
443
502
                        self.outf.encoding)
461
520
        elif len(revision) == 1:
462
521
            rev_id = revision[0].in_history(branch_from).rev_id
463
522
        else:
464
 
            raise BzrCommandError('bzr pull --revision takes one value.')
 
523
            raise errors.BzrCommandError('bzr pull --revision takes one value.')
465
524
 
466
525
        old_rh = branch_to.revision_history()
467
526
        if tree_to is not None:
516
575
            create_prefix=False, verbose=False):
517
576
        # FIXME: Way too big!  Put this into a function called from the
518
577
        # command.
519
 
        from bzrlib.transport import get_transport
520
578
        
521
579
        br_from = Branch.open_containing('.')[0]
522
580
        stored_loc = br_from.get_push_location()
523
581
        if location is None:
524
582
            if stored_loc is None:
525
 
                raise BzrCommandError("No push location known or specified.")
 
583
                raise errors.BzrCommandError("No push location known or specified.")
526
584
            else:
527
585
                display_url = urlutils.unescape_for_display(stored_loc,
528
586
                        self.outf.encoding)
529
587
                self.outf.write("Using saved location: %s\n" % display_url)
530
588
                location = stored_loc
531
589
 
532
 
        transport = get_transport(location)
533
 
        location_url = transport.base
 
590
        to_transport = transport.get_transport(location)
 
591
        location_url = to_transport.base
534
592
 
535
593
        old_rh = []
536
594
        try:
537
595
            dir_to = bzrdir.BzrDir.open(location_url)
538
596
            br_to = dir_to.open_branch()
539
 
        except NotBranchError:
 
597
        except errors.NotBranchError:
540
598
            # create a branch.
541
 
            transport = transport.clone('..')
 
599
            to_transport = to_transport.clone('..')
542
600
            if not create_prefix:
543
601
                try:
544
 
                    relurl = transport.relpath(location_url)
 
602
                    relurl = to_transport.relpath(location_url)
545
603
                    mutter('creating directory %s => %s', location_url, relurl)
546
 
                    transport.mkdir(relurl)
547
 
                except NoSuchFile:
548
 
                    raise BzrCommandError("Parent directory of %s "
549
 
                                          "does not exist." % location)
 
604
                    to_transport.mkdir(relurl)
 
605
                except errors.NoSuchFile:
 
606
                    raise errors.BzrCommandError("Parent directory of %s "
 
607
                                                 "does not exist." % location)
550
608
            else:
551
 
                current = transport.base
552
 
                needed = [(transport, transport.relpath(location_url))]
 
609
                current = to_transport.base
 
610
                needed = [(to_transport, to_transport.relpath(location_url))]
553
611
                while needed:
554
612
                    try:
555
 
                        transport, relpath = needed[-1]
556
 
                        transport.mkdir(relpath)
 
613
                        to_transport, relpath = needed[-1]
 
614
                        to_transport.mkdir(relpath)
557
615
                        needed.pop()
558
 
                    except NoSuchFile:
559
 
                        new_transport = transport.clone('..')
 
616
                    except errors.NoSuchFile:
 
617
                        new_transport = to_transport.clone('..')
560
618
                        needed.append((new_transport,
561
 
                                       new_transport.relpath(transport.base)))
562
 
                        if new_transport.base == transport.base:
563
 
                            raise BzrCommandError("Could not create "
564
 
                                                  "path prefix.")
 
619
                                       new_transport.relpath(to_transport.base)))
 
620
                        if new_transport.base == to_transport.base:
 
621
                            raise errors.BzrCommandError("Could not create "
 
622
                                                         "path prefix.")
565
623
            dir_to = br_from.bzrdir.clone(location_url,
566
624
                revision_id=br_from.last_revision())
567
625
            br_to = dir_to.open_branch()
582
640
                    warning('This transport does not update the working '
583
641
                            'tree of: %s' % (br_to.base,))
584
642
                    count = br_to.pull(br_from, overwrite)
585
 
                except NoWorkingTree:
 
643
                except errors.NoWorkingTree:
586
644
                    count = br_to.pull(br_from, overwrite)
587
645
                else:
588
646
                    count = tree_to.pull(br_from, overwrite)
589
 
            except DivergedBranches:
590
 
                raise BzrCommandError("These branches have diverged."
591
 
                                      "  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".')
592
650
        note('%d revision(s) pushed.' % (count,))
593
651
 
594
652
        if verbose:
618
676
    aliases = ['get', 'clone']
619
677
 
620
678
    def run(self, from_location, to_location=None, revision=None, basis=None):
621
 
        from bzrlib.transport import get_transport
622
679
        if revision is None:
623
680
            revision = [None]
624
681
        elif len(revision) > 1:
625
 
            raise BzrCommandError(
 
682
            raise errors.BzrCommandError(
626
683
                'bzr branch --revision takes exactly 1 revision value')
627
684
        try:
628
685
            br_from = Branch.open(from_location)
629
686
        except OSError, e:
630
687
            if e.errno == errno.ENOENT:
631
 
                raise BzrCommandError('Source location "%s" does not'
632
 
                                      ' exist.' % to_location)
 
688
                raise errors.BzrCommandError('Source location "%s" does not'
 
689
                                             ' exist.' % to_location)
633
690
            else:
634
691
                raise
635
692
        br_from.lock_read()
651
708
            else:
652
709
                name = os.path.basename(to_location) + '\n'
653
710
 
654
 
            to_transport = get_transport(to_location)
 
711
            to_transport = transport.get_transport(to_location)
655
712
            try:
656
713
                to_transport.mkdir('.')
657
714
            except errors.FileExists:
658
 
                raise BzrCommandError('Target directory "%s" already'
659
 
                                      ' exists.' % to_location)
 
715
                raise errors.BzrCommandError('Target directory "%s" already'
 
716
                                             ' exists.' % to_location)
660
717
            except errors.NoSuchFile:
661
 
                raise BzrCommandError('Parent of "%s" does not exist.' %
662
 
                                      to_location)
 
718
                raise errors.BzrCommandError('Parent of "%s" does not exist.'
 
719
                                             % to_location)
663
720
            try:
664
721
                # preserve whatever source format we have.
665
722
                dir = br_from.bzrdir.sprout(to_transport.base,
668
725
            except errors.NoSuchRevision:
669
726
                to_transport.delete_tree('.')
670
727
                msg = "The branch %s has no revision %s." % (from_location, revision[0])
671
 
                raise BzrCommandError(msg)
 
728
                raise errors.BzrCommandError(msg)
672
729
            except errors.UnlistableBranch:
673
730
                osutils.rmtree(to_location)
674
731
                msg = "The branch %s cannot be used as a --basis" % (basis,)
675
 
                raise BzrCommandError(msg)
 
732
                raise errors.BzrCommandError(msg)
676
733
            if name:
677
734
                branch.control_files.put_utf8('branch-name', name)
678
735
            note('Branched %d revision(s).' % branch.revno())
717
774
        if revision is None:
718
775
            revision = [None]
719
776
        elif len(revision) > 1:
720
 
            raise BzrCommandError(
 
777
            raise errors.BzrCommandError(
721
778
                'bzr checkout --revision takes exactly 1 revision value')
722
779
        if branch_location is None:
723
780
            branch_location = osutils.getcwd()
732
789
        # if the source and to_location are the same, 
733
790
        # and there is no working tree,
734
791
        # then reconstitute a branch
735
 
        if (osutils.abspath(to_location) == 
 
792
        if (osutils.abspath(to_location) ==
736
793
            osutils.abspath(branch_location)):
737
794
            try:
738
795
                source.bzrdir.open_workingtree()
743
800
            os.mkdir(to_location)
744
801
        except OSError, e:
745
802
            if e.errno == errno.EEXIST:
746
 
                raise BzrCommandError('Target directory "%s" already'
747
 
                                      ' exists.' % to_location)
 
803
                raise errors.BzrCommandError('Target directory "%s" already'
 
804
                                             ' exists.' % to_location)
748
805
            if e.errno == errno.ENOENT:
749
 
                raise BzrCommandError('Parent of "%s" does not exist.' %
750
 
                                      to_location)
 
806
                raise errors.BzrCommandError('Parent of "%s" does not exist.'
 
807
                                             % to_location)
751
808
            else:
752
809
                raise
753
810
        old_format = bzrdir.BzrDirFormat.get_default_format()
754
811
        bzrdir.BzrDirFormat.set_default_format(bzrdir.BzrDirMetaFormat1())
755
812
        try:
756
 
            if lightweight:
757
 
                checkout = bzrdir.BzrDirMetaFormat1().initialize(to_location)
758
 
                branch.BranchReferenceFormat().initialize(checkout, source)
759
 
            else:
760
 
                checkout_branch =  bzrdir.BzrDir.create_branch_convenience(
761
 
                    to_location, force_new_tree=False)
762
 
                checkout = checkout_branch.bzrdir
763
 
                checkout_branch.bind(source)
764
 
                if revision_id is not None:
765
 
                    rh = checkout_branch.revision_history()
766
 
                    checkout_branch.set_revision_history(rh[:rh.index(revision_id) + 1])
767
 
            checkout.create_workingtree(revision_id)
 
813
            source.create_checkout(to_location, revision_id, lightweight)
768
814
        finally:
769
815
            bzrdir.BzrDirFormat.set_default_format(old_format)
770
816
 
779
825
 
780
826
    @display_command
781
827
    def run(self, dir=u'.'):
782
 
        from bzrlib.tree import find_renames
783
828
        tree = WorkingTree.open_containing(dir)[0]
784
829
        old_inv = tree.basis_tree().inventory
785
830
        new_inv = tree.read_working_inventory()
786
 
        renames = list(find_renames(old_inv, new_inv))
 
831
        renames = list(_mod_tree.find_renames(old_inv, new_inv))
787
832
        renames.sort()
788
833
        for old_name, new_name in renames:
789
834
            self.outf.write("%s => %s\n" % (old_name, new_name))
800
845
    'bzr revert' instead of 'bzr commit' after the update.
801
846
    """
802
847
    takes_args = ['dir?']
 
848
    aliases = ['up']
803
849
 
804
850
    def run(self, dir='.'):
805
851
        tree = WorkingTree.open_containing(dir)[0]
806
852
        tree.lock_write()
807
853
        try:
808
 
            last_rev = tree.last_revision() 
 
854
            existing_pending_merges = tree.get_parent_ids()[1:]
 
855
            last_rev = tree.last_revision()
809
856
            if last_rev == tree.branch.last_revision():
810
857
                # may be up to date, check master too.
811
858
                master = tree.branch.get_master_branch()
816
863
            conflicts = tree.update()
817
864
            revno = tree.branch.revision_id_to_revno(tree.last_revision())
818
865
            note('Updated to revision %d.' % (revno,))
 
866
            if tree.get_parent_ids()[1:] != existing_pending_merges:
 
867
                note('Your local commits will now show as pending merges with '
 
868
                     "'bzr status', and can be committed with 'bzr commit'.")
819
869
            if conflicts != 0:
820
870
                return 1
821
871
            else:
863
913
        tree, file_list = tree_files(file_list)
864
914
        if new is False:
865
915
            if file_list is None:
866
 
                raise BzrCommandError('Specify one or more files to remove, or'
867
 
                                      ' use --new.')
 
916
                raise errors.BzrCommandError('Specify one or more files to'
 
917
                                             ' remove, or use --new.')
868
918
        else:
869
 
            from bzrlib.delta import compare_trees
870
 
            added = [compare_trees(tree.basis_tree(), tree,
871
 
                                   specific_files=file_list).added]
872
 
            file_list = sorted([f[0] for f in added[0]], reverse=True)
 
919
            added = tree.changes_from(tree.basis_tree(),
 
920
                specific_files=file_list).added
 
921
            file_list = sorted([f[0] for f in added], reverse=True)
873
922
            if len(file_list) == 0:
874
 
                raise BzrCommandError('No matching files.')
 
923
                raise errors.BzrCommandError('No matching files.')
875
924
        tree.remove(file_list, verbose=verbose, to_file=self.outf)
876
925
 
877
926
 
890
939
    def run(self, filename):
891
940
        tree, relpath = WorkingTree.open_containing(filename)
892
941
        i = tree.inventory.path2id(relpath)
893
 
        if i == None:
894
 
            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)
895
944
        else:
896
945
            self.outf.write(i + '\n')
897
946
 
911
960
        tree, relpath = WorkingTree.open_containing(filename)
912
961
        inv = tree.inventory
913
962
        fid = inv.path2id(relpath)
914
 
        if fid == None:
915
 
            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)
916
965
        for fip in inv.get_idpath(fid):
917
966
            self.outf.write(fip + '\n')
918
967
 
975
1024
            last_revision = wt.last_revision()
976
1025
 
977
1026
        revision_ids = b.repository.get_ancestry(last_revision)
978
 
        assert revision_ids[0] == None
 
1027
        assert revision_ids[0] is None
979
1028
        revision_ids.pop(0)
980
1029
        for revision_id in revision_ids:
981
1030
            self.outf.write(revision_id + '\n')
1016
1065
            format = get_format_type('default')
1017
1066
        if location is None:
1018
1067
            location = u'.'
1019
 
        else:
1020
 
            # The path has to exist to initialize a
1021
 
            # branch inside of it.
1022
 
            # Just using os.mkdir, since I don't
1023
 
            # believe that we want to create a bunch of
1024
 
            # locations if the user supplies an extended path
1025
 
            if not os.path.exists(location):
1026
 
                os.mkdir(location)
 
1068
 
 
1069
        to_transport = transport.get_transport(location)
 
1070
 
 
1071
        # The path has to exist to initialize a
 
1072
        # branch inside of it.
 
1073
        # Just using os.mkdir, since I don't
 
1074
        # believe that we want to create a bunch of
 
1075
        # locations if the user supplies an extended path
 
1076
        # TODO: create-prefix
 
1077
        try:
 
1078
            to_transport.mkdir('.')
 
1079
        except errors.FileExists:
 
1080
            pass
 
1081
                    
1027
1082
        try:
1028
1083
            existing_bzrdir = bzrdir.BzrDir.open(location)
1029
 
        except NotBranchError:
 
1084
        except errors.NotBranchError:
1030
1085
            # really a NotBzrDir error...
1031
1086
            bzrdir.BzrDir.create_branch_convenience(location, format=format)
1032
1087
        else:
 
1088
            from bzrlib.transport.local import LocalTransport
1033
1089
            if existing_bzrdir.has_branch():
1034
 
                if existing_bzrdir.has_workingtree():
1035
 
                    raise errors.AlreadyBranchError(location)
1036
 
                else:
1037
 
                    raise errors.BranchExistsWithoutWorkingTree(location)
 
1090
                if (isinstance(to_transport, LocalTransport)
 
1091
                    and not existing_bzrdir.has_workingtree()):
 
1092
                        raise errors.BranchExistsWithoutWorkingTree(location)
 
1093
                raise errors.AlreadyBranchError(location)
1038
1094
            else:
1039
1095
                existing_bzrdir.create_branch()
1040
1096
                existing_bzrdir.create_workingtree()
1066
1122
                             ' a working tree')]
1067
1123
    aliases = ["init-repo"]
1068
1124
    def run(self, location, format=None, trees=False):
1069
 
        from bzrlib.transport import get_transport
1070
1125
        if format is None:
1071
1126
            format = get_format_type('default')
1072
 
        transport = get_transport(location)
1073
 
        if not transport.has('.'):
1074
 
            transport.mkdir('')
1075
 
        newdir = format.initialize_on_transport(transport)
 
1127
 
 
1128
        if location is None:
 
1129
            location = '.'
 
1130
 
 
1131
        to_transport = transport.get_transport(location)
 
1132
        try:
 
1133
            to_transport.mkdir('.')
 
1134
        except errors.FileExists:
 
1135
            pass
 
1136
 
 
1137
        newdir = format.initialize_on_transport(to_transport)
1076
1138
        repo = newdir.create_repository(shared=True)
1077
1139
        repo.set_make_working_trees(trees)
1078
1140
 
1130
1192
            new_label = 'new/'
1131
1193
        else:
1132
1194
            if not ':' in prefix:
1133
 
                 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")
1134
1197
            old_label, new_label = prefix.split(":")
1135
1198
        
1136
1199
        try:
1138
1201
            tree2 = None
1139
1202
            b = None
1140
1203
            b2 = None
1141
 
        except FileInWrongBranch:
 
1204
        except errors.FileInWrongBranch:
1142
1205
            if len(file_list) != 2:
1143
 
                raise BzrCommandError("Files are in different branches")
 
1206
                raise errors.BzrCommandError("Files are in different branches")
1144
1207
 
1145
1208
            tree1, file1 = WorkingTree.open_containing(file_list[0])
1146
1209
            tree2, file2 = WorkingTree.open_containing(file_list[1])
1147
1210
            if file1 != "" or file2 != "":
1148
1211
                # FIXME diff those two files. rbc 20051123
1149
 
                raise BzrCommandError("Files are in different branches")
 
1212
                raise errors.BzrCommandError("Files are in different branches")
1150
1213
            file_list = None
1151
 
        except NotBranchError:
1152
 
            # Don't raise an error when bzr diff is called from
1153
 
            # outside a working tree.
1154
 
            tree1, tree2 = None, None
 
1214
        except errors.NotBranchError:
 
1215
            if (revision is not None and len(revision) == 2
 
1216
                and not revision[0].needs_branch()
 
1217
                and not revision[1].needs_branch()):
 
1218
                # If both revision specs include a branch, we can
 
1219
                # diff them without needing a local working tree
 
1220
                tree1, tree2 = None, None
 
1221
            else:
 
1222
                raise
1155
1223
        if revision is not None:
1156
1224
            if tree2 is not None:
1157
 
                raise BzrCommandError("Can't specify -r with two branches")
 
1225
                raise errors.BzrCommandError("Can't specify -r with two branches")
1158
1226
            if (len(revision) == 1) or (revision[1].spec is None):
1159
1227
                return diff_cmd_helper(tree1, file_list, diff_options,
1160
1228
                                       revision[0], 
1164
1232
                                       revision[0], revision[1],
1165
1233
                                       old_label=old_label, new_label=new_label)
1166
1234
            else:
1167
 
                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')
1168
1237
        else:
1169
1238
            if tree2 is not None:
1170
1239
                return show_diff_trees(tree1, tree2, sys.stdout, 
1205
1274
    hidden = True
1206
1275
    @display_command
1207
1276
    def run(self):
1208
 
        from bzrlib.delta import compare_trees
1209
 
 
1210
1277
        tree = WorkingTree.open_containing(u'.')[0]
1211
 
        td = compare_trees(tree.basis_tree(), tree)
1212
 
 
 
1278
        td = tree.changes_from(tree.basis_tree())
1213
1279
        for path, id, kind, text_modified, meta_modified in td.modified:
1214
1280
            self.outf.write(path + '\n')
1215
1281
 
1311
1377
        else:
1312
1378
            # local dir only
1313
1379
            # FIXME ? log the current subdir only RBC 20060203 
1314
 
            dir, relpath = bzrdir.BzrDir.open_containing('.')
 
1380
            if revision is not None \
 
1381
                    and len(revision) > 0 and revision[0].get_branch():
 
1382
                location = revision[0].get_branch()
 
1383
            else:
 
1384
                location = '.'
 
1385
            dir, relpath = bzrdir.BzrDir.open_containing(location)
1315
1386
            b = dir.open_branch()
1316
1387
 
1317
1388
        if revision is None:
1320
1391
        elif len(revision) == 1:
1321
1392
            rev1 = rev2 = revision[0].in_history(b).revno
1322
1393
        elif len(revision) == 2:
 
1394
            if revision[1].get_branch() != revision[0].get_branch():
 
1395
                # b is taken from revision[0].get_branch(), and
 
1396
                # show_log will use its revision_history. Having
 
1397
                # different branches will lead to weird behaviors.
 
1398
                raise errors.BzrCommandError(
 
1399
                    "Log doesn't accept two revisions in different branches.")
1323
1400
            if revision[0].spec is None:
1324
1401
                # missing begin-range means first revision
1325
1402
                rev1 = 1
1332
1409
            else:
1333
1410
                rev2 = revision[1].in_history(b).revno
1334
1411
        else:
1335
 
            raise BzrCommandError('bzr log --revision takes one or two values.')
 
1412
            raise errors.BzrCommandError('bzr log --revision takes one or two values.')
1336
1413
 
1337
1414
        # By this point, the revision numbers are converted to the +ve
1338
1415
        # form if they were supplied in the -ve form, so we can do
1340
1417
        if rev1 > rev2:
1341
1418
            (rev2, rev1) = (rev1, rev2)
1342
1419
 
1343
 
        if (log_format == None):
 
1420
        if (log_format is None):
1344
1421
            default = b.get_config().log_format()
1345
1422
            log_format = get_log_format(long=long, short=short, line=line, 
1346
1423
                                        default=default)
1412
1489
            null=False):
1413
1490
 
1414
1491
        if verbose and null:
1415
 
            raise BzrCommandError('Cannot set both --verbose and --null')
 
1492
            raise errors.BzrCommandError('Cannot set both --verbose and --null')
1416
1493
        all = not (unknown or versioned or ignored)
1417
1494
 
1418
1495
        selection = {'I':ignored, '?':unknown, 'V':versioned}
1480
1557
        from bzrlib.atomicfile import AtomicFile
1481
1558
        if old_default_rules is not None:
1482
1559
            # dump the rules and exit
1483
 
            for pattern in bzrlib.DEFAULT_IGNORE:
 
1560
            for pattern in ignores.OLD_DEFAULTS:
1484
1561
                print pattern
1485
1562
            return
1486
1563
        if name_pattern is None:
1487
 
            raise BzrCommandError("ignore requires a NAME_PATTERN")
 
1564
            raise errors.BzrCommandError("ignore requires a NAME_PATTERN")
1488
1565
        tree, relpath = WorkingTree.open_containing(u'.')
1489
1566
        ifn = tree.abspath('.bzrignore')
1490
1567
        if os.path.exists(ifn):
1547
1624
        try:
1548
1625
            revno = int(revno)
1549
1626
        except ValueError:
1550
 
            raise BzrCommandError("not a valid revision-number: %r" % revno)
 
1627
            raise errors.BzrCommandError("not a valid revision-number: %r" % revno)
1551
1628
 
1552
1629
        print WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
1553
1630
 
1585
1662
            rev_id = b.last_revision()
1586
1663
        else:
1587
1664
            if len(revision) != 1:
1588
 
                raise BzrError('bzr export --revision takes exactly 1 argument')
 
1665
                raise errors.BzrError('bzr export --revision takes exactly'
 
1666
                                      ' 1 argument')
1589
1667
            rev_id = revision[0].in_history(b).rev_id
1590
1668
        t = b.repository.revision_tree(rev_id)
1591
1669
        try:
1592
1670
            export(t, dest, format, root)
1593
1671
        except errors.NoSuchExportFormat, e:
1594
 
            raise BzrCommandError('Unsupported export format: %s' % e.format)
 
1672
            raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
1595
1673
 
1596
1674
 
1597
1675
class cmd_cat(Command):
1603
1681
    @display_command
1604
1682
    def run(self, filename, revision=None):
1605
1683
        if revision is not None and len(revision) != 1:
1606
 
            raise BzrCommandError("bzr cat --revision takes exactly one number")
 
1684
            raise errors.BzrCommandError("bzr cat --revision takes exactly one number")
1607
1685
        tree = None
1608
1686
        try:
1609
1687
            tree, relpath = WorkingTree.open_containing(filename)
1610
1688
            b = tree.branch
1611
 
        except NotBranchError:
 
1689
        except errors.NotBranchError:
1612
1690
            pass
1613
1691
 
1614
1692
        if tree is None:
1615
1693
            b, relpath = Branch.open_containing(filename)
 
1694
        if revision is not None and revision[0].get_branch() is not None:
 
1695
            b = Branch.open(revision[0].get_branch())
1616
1696
        if revision is None:
1617
1697
            revision_id = b.last_revision()
1618
1698
        else:
1700
1780
            template = make_commit_message_template(tree, selected_list)
1701
1781
            message = edit_commit_message(template)
1702
1782
            if message is None:
1703
 
                raise BzrCommandError("please specify a commit message"
1704
 
                                      " with either --message or --file")
 
1783
                raise errors.BzrCommandError("please specify a commit message"
 
1784
                                             " with either --message or --file")
1705
1785
        elif message and file:
1706
 
            raise BzrCommandError("please specify either --message or --file")
 
1786
            raise errors.BzrCommandError("please specify either --message or --file")
1707
1787
        
1708
1788
        if file:
1709
1789
            message = codecs.open(file, 'rt', bzrlib.user_encoding).read()
1710
1790
 
1711
1791
        if message == "":
1712
 
            raise BzrCommandError("empty commit message specified")
 
1792
            raise errors.BzrCommandError("empty commit message specified")
1713
1793
        
1714
1794
        if verbose:
1715
1795
            reporter = ReportCommitToLog()
1723
1803
        except PointlessCommit:
1724
1804
            # FIXME: This should really happen before the file is read in;
1725
1805
            # perhaps prepare the commit; get the message; then actually commit
1726
 
            raise BzrCommandError("no changes to commit."
1727
 
                                  " use --unchanged to commit anyhow")
 
1806
            raise errors.BzrCommandError("no changes to commit."
 
1807
                                         " use --unchanged to commit anyhow")
1728
1808
        except ConflictsInTree:
1729
 
            raise BzrCommandError("Conflicts detected in working tree.  "
 
1809
            raise errors.BzrCommandError("Conflicts detected in working tree.  "
1730
1810
                'Use "bzr conflicts" to list, "bzr resolve FILE" to resolve.')
1731
1811
        except StrictCommitFailed:
1732
 
            raise BzrCommandError("Commit refused because there are unknown "
1733
 
                                  "files in the working tree.")
 
1812
            raise errors.BzrCommandError("Commit refused because there are unknown "
 
1813
                                         "files in the working tree.")
1734
1814
        except errors.BoundBranchOutOfDate, e:
1735
 
            raise BzrCommandError(str(e)
1736
 
                                  + ' Either unbind, update, or'
1737
 
                                    ' pass --local to commit.')
1738
 
 
 
1815
            raise errors.BzrCommandError(str(e) + "\n"
 
1816
                'To commit to master branch, run update and then commit.\n'
 
1817
                'You can also pass --local to commit to continue working '
 
1818
                'disconnected.')
1739
1819
 
1740
1820
class cmd_check(Command):
1741
1821
    """Validate consistency of branch history.
1822
1902
            # use branch if we're inside one; otherwise global config
1823
1903
            try:
1824
1904
                c = Branch.open_containing('.')[0].get_config()
1825
 
            except NotBranchError:
 
1905
            except errors.NotBranchError:
1826
1906
                c = config.GlobalConfig()
1827
1907
            if email:
1828
1908
                self.outf.write(c.user_email() + '\n')
1833
1913
        # display a warning if an email address isn't included in the given name.
1834
1914
        try:
1835
1915
            config.extract_email_address(name)
1836
 
        except BzrError, e:
 
1916
        except errors.NoEmailInUsername, e:
1837
1917
            warning('"%s" does not seem to contain an email address.  '
1838
1918
                    'This is allowed, but not recommended.', name)
1839
1919
        
1901
1981
            return FakeNFSServer
1902
1982
        msg = "No known transport type %s. Supported types are: sftp\n" %\
1903
1983
            (typestring)
1904
 
        raise BzrCommandError(msg)
 
1984
        raise errors.BzrCommandError(msg)
1905
1985
 
1906
1986
    hidden = True
1907
1987
    takes_args = ['testspecs*']
1917
1997
                     Option('lsprof-timed',
1918
1998
                            help='generate lsprof output for benchmarked'
1919
1999
                                 ' sections of code.'),
 
2000
                     Option('cache-dir', type=str,
 
2001
                            help='a directory to cache intermediate'
 
2002
                                 ' benchmark steps'),
1920
2003
                     ]
1921
2004
 
1922
2005
    def run(self, testspecs_list=None, verbose=None, one=False,
1923
2006
            keep_output=False, transport=None, benchmark=None,
1924
 
            lsprof_timed=None):
 
2007
            lsprof_timed=None, cache_dir=None):
1925
2008
        import bzrlib.ui
1926
2009
        from bzrlib.tests import selftest
1927
2010
        import bzrlib.benchmarks as benchmarks
 
2011
        from bzrlib.benchmarks import tree_creator
 
2012
 
 
2013
        if cache_dir is not None:
 
2014
            tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
1928
2015
        # we don't want progress meters from the tests to go to the
1929
2016
        # real output; and we don't want log messages cluttering up
1930
2017
        # the real logs.
1943
2030
                test_suite_factory = benchmarks.test_suite
1944
2031
                if verbose is None:
1945
2032
                    verbose = True
 
2033
                # TODO: should possibly lock the history file...
 
2034
                benchfile = open(".perf_history", "at")
1946
2035
            else:
1947
2036
                test_suite_factory = None
1948
2037
                if verbose is None:
1949
2038
                    verbose = False
1950
 
            result = selftest(verbose=verbose, 
1951
 
                              pattern=pattern,
1952
 
                              stop_on_failure=one, 
1953
 
                              keep_output=keep_output,
1954
 
                              transport=transport,
1955
 
                              test_suite_factory=test_suite_factory,
1956
 
                              lsprof_timed=lsprof_timed)
 
2039
                benchfile = None
 
2040
            try:
 
2041
                result = selftest(verbose=verbose, 
 
2042
                                  pattern=pattern,
 
2043
                                  stop_on_failure=one, 
 
2044
                                  keep_output=keep_output,
 
2045
                                  transport=transport,
 
2046
                                  test_suite_factory=test_suite_factory,
 
2047
                                  lsprof_timed=lsprof_timed,
 
2048
                                  bench_history=benchfile)
 
2049
            finally:
 
2050
                if benchfile is not None:
 
2051
                    benchfile.close()
1957
2052
            if result:
1958
2053
                info('tests passed')
1959
2054
            else:
1963
2058
            ui.ui_factory = save_ui
1964
2059
 
1965
2060
 
1966
 
def _get_bzr_branch():
1967
 
    """If bzr is run from a branch, return Branch or None"""
1968
 
    from os.path import dirname
1969
 
    
1970
 
    try:
1971
 
        branch = Branch.open(dirname(osutils.abspath(dirname(__file__))))
1972
 
        return branch
1973
 
    except errors.BzrError:
1974
 
        return None
1975
 
    
1976
 
 
1977
 
def show_version():
1978
 
    import bzrlib
1979
 
    print "bzr (bazaar-ng) %s" % bzrlib.__version__
1980
 
    # is bzrlib itself in a branch?
1981
 
    branch = _get_bzr_branch()
1982
 
    if branch:
1983
 
        rh = branch.revision_history()
1984
 
        revno = len(rh)
1985
 
        print "  bzr checkout, revision %d" % (revno,)
1986
 
        print "  nick: %s" % (branch.nick,)
1987
 
        if rh:
1988
 
            print "  revid: %s" % (rh[-1],)
1989
 
    print "Using python interpreter:", sys.executable
1990
 
    import site
1991
 
    print "Using python standard library:", os.path.dirname(site.__file__)
1992
 
    print "Using bzrlib:",
1993
 
    if len(bzrlib.__path__) > 1:
1994
 
        # print repr, which is a good enough way of making it clear it's
1995
 
        # more than one element (eg ['/foo/bar', '/foo/bzr'])
1996
 
        print repr(bzrlib.__path__)
1997
 
    else:
1998
 
        print bzrlib.__path__[0]
1999
 
 
2000
 
    print
2001
 
    print bzrlib.__copyright__
2002
 
    print "http://bazaar-vcs.org/"
2003
 
    print
2004
 
    print "bzr comes with ABSOLUTELY NO WARRANTY.  bzr is free software, and"
2005
 
    print "you may use, modify and redistribute it under the terms of the GNU"
2006
 
    print "General Public License version 2 or later."
2007
 
 
2008
 
 
2009
2061
class cmd_version(Command):
2010
2062
    """Show version of bzr."""
 
2063
 
2011
2064
    @display_command
2012
2065
    def run(self):
 
2066
        from bzrlib.version import show_version
2013
2067
        show_version()
2014
2068
 
 
2069
 
2015
2070
class cmd_rocks(Command):
2016
2071
    """Statement of optimism."""
 
2072
 
2017
2073
    hidden = True
 
2074
 
2018
2075
    @display_command
2019
2076
    def run(self):
2020
2077
        print "it sure does!"
2021
2078
 
2022
2079
 
2023
2080
class cmd_find_merge_base(Command):
2024
 
    """Find and print a base revision for merging two branches.
2025
 
    """
 
2081
    """Find and print a base revision for merging two branches."""
2026
2082
    # TODO: Options to specify revisions on either side, as if
2027
2083
    #       merging only part of the history.
2028
2084
    takes_args = ['branch', 'other']
2030
2086
    
2031
2087
    @display_command
2032
2088
    def run(self, branch, other):
2033
 
        from bzrlib.revision import common_ancestor, MultipleRevisionSources
 
2089
        from bzrlib.revision import MultipleRevisionSources
2034
2090
        
2035
2091
        branch1 = Branch.open_containing(branch)[0]
2036
2092
        branch2 = Branch.open_containing(other)[0]
2093
2149
    takes_args = ['branch?']
2094
2150
    takes_options = ['revision', 'force', 'merge-type', 'reprocess', 'remember',
2095
2151
                     Option('show-base', help="Show base revision text in "
2096
 
                            "conflicts")]
 
2152
                            "conflicts"), 
 
2153
                     Option('uncommitted', help='Apply uncommitted changes'
 
2154
                            ' from a working copy, instead of branch changes')]
2097
2155
 
2098
2156
    def help(self):
2099
 
        from merge import merge_type_help
2100
2157
        from inspect import getdoc
2101
 
        return getdoc(self) + '\n' + merge_type_help() 
 
2158
        return getdoc(self) + '\n' + _mod_merge.merge_type_help()
2102
2159
 
2103
2160
    def run(self, branch=None, revision=None, force=False, merge_type=None,
2104
 
            show_base=False, reprocess=False, remember=False):
 
2161
            show_base=False, reprocess=False, remember=False, 
 
2162
            uncommitted=False):
2105
2163
        if merge_type is None:
2106
 
            merge_type = Merge3Merger
 
2164
            merge_type = _mod_merge.Merge3Merger
2107
2165
 
2108
2166
        tree = WorkingTree.open_containing(u'.')[0]
2109
2167
 
2110
2168
        if branch is not None:
2111
2169
            try:
2112
2170
                reader = bundle.read_bundle_from_url(branch)
2113
 
            except NotABundle:
 
2171
            except errors.NotABundle:
2114
2172
                pass # Continue on considering this url a Branch
2115
2173
            else:
2116
2174
                conflicts = merge_bundle(reader, tree, not force, merge_type,
2120
2178
                else:
2121
2179
                    return 1
2122
2180
 
2123
 
        branch = self._get_remembered_parent(tree, branch, 'Merging from')
 
2181
        if revision is None \
 
2182
                or len(revision) < 1 or revision[0].needs_branch():
 
2183
            branch = self._get_remembered_parent(tree, branch, 'Merging from')
2124
2184
 
2125
2185
        if revision is None or len(revision) < 1:
2126
 
            base = [None, None]
2127
 
            other = [branch, -1]
 
2186
            if uncommitted:
 
2187
                base = [branch, -1]
 
2188
                other = [branch, None]
 
2189
            else:
 
2190
                base = [None, None]
 
2191
                other = [branch, -1]
2128
2192
            other_branch, path = Branch.open_containing(branch)
2129
2193
        else:
 
2194
            if uncommitted:
 
2195
                raise errors.BzrCommandError('Cannot use --uncommitted and'
 
2196
                                             ' --revision at the same time.')
 
2197
            branch = revision[0].get_branch() or branch
2130
2198
            if len(revision) == 1:
2131
2199
                base = [None, None]
2132
2200
                other_branch, path = Branch.open_containing(branch)
2135
2203
            else:
2136
2204
                assert len(revision) == 2
2137
2205
                if None in revision:
2138
 
                    raise BzrCommandError(
2139
 
                        "Merge doesn't permit that revision specifier.")
2140
 
                other_branch, path = Branch.open_containing(branch)
 
2206
                    raise errors.BzrCommandError(
 
2207
                        "Merge doesn't permit empty revision specifier.")
 
2208
                base_branch, path = Branch.open_containing(branch)
 
2209
                branch1 = revision[1].get_branch() or branch
 
2210
                other_branch, path1 = Branch.open_containing(branch1)
 
2211
                if revision[0].get_branch() is not None:
 
2212
                    # then path was obtained from it, and is None.
 
2213
                    path = path1
2141
2214
 
2142
 
                base = [branch, revision[0].in_history(other_branch).revno]
2143
 
                other = [branch, revision[1].in_history(other_branch).revno]
 
2215
                base = [branch, revision[0].in_history(base_branch).revno]
 
2216
                other = [branch1, revision[1].in_history(other_branch).revno]
2144
2217
 
2145
2218
        if tree.branch.get_parent() is None or remember:
2146
2219
            tree.branch.set_parent(other_branch.base)
2152
2225
        pb = ui.ui_factory.nested_progress_bar()
2153
2226
        try:
2154
2227
            try:
2155
 
                conflict_count = merge(other, base, check_clean=(not force),
2156
 
                                       merge_type=merge_type,
2157
 
                                       reprocess=reprocess,
2158
 
                                       show_base=show_base,
2159
 
                                       pb=pb, file_list=interesting_files)
 
2228
                conflict_count = _merge_helper(
 
2229
                    other, base, check_clean=(not force),
 
2230
                    merge_type=merge_type,
 
2231
                    reprocess=reprocess,
 
2232
                    show_base=show_base,
 
2233
                    pb=pb, file_list=interesting_files)
2160
2234
            finally:
2161
2235
                pb.finished()
2162
2236
            if conflict_count != 0:
2183
2257
        stored_location = tree.branch.get_parent()
2184
2258
        mutter("%s", stored_location)
2185
2259
        if stored_location is None:
2186
 
            raise BzrCommandError("No location specified or remembered")
 
2260
            raise errors.BzrCommandError("No location specified or remembered")
2187
2261
        display_url = urlutils.unescape_for_display(stored_location, self.outf.encoding)
2188
2262
        self.outf.write("%s remembered location %s\n" % (verb_string, display_url))
2189
2263
        return stored_location
2216
2290
                            "conflicts")]
2217
2291
 
2218
2292
    def help(self):
2219
 
        from merge import merge_type_help
2220
2293
        from inspect import getdoc
2221
 
        return getdoc(self) + '\n' + merge_type_help() 
 
2294
        return getdoc(self) + '\n' + _mod_merge.merge_type_help()
2222
2295
 
2223
2296
    def run(self, file_list=None, merge_type=None, show_base=False,
2224
2297
            reprocess=False):
2225
 
        from bzrlib.merge import merge_inner, transform_tree
2226
2298
        if merge_type is None:
2227
 
            merge_type = Merge3Merger
 
2299
            merge_type = _mod_merge.Merge3Merger
2228
2300
        tree, file_list = tree_files(file_list)
2229
2301
        tree.lock_write()
2230
2302
        try:
2231
 
            pending_merges = tree.pending_merges() 
2232
 
            if len(pending_merges) != 1:
2233
 
                raise BzrCommandError("Sorry, remerge only works after normal"
2234
 
                                      " merges.  Not cherrypicking or"
2235
 
                                      " multi-merges.")
 
2303
            parents = tree.get_parent_ids()
 
2304
            if len(parents) != 2:
 
2305
                raise errors.BzrCommandError("Sorry, remerge only works after normal"
 
2306
                                             " merges.  Not cherrypicking or"
 
2307
                                             " multi-merges.")
2236
2308
            repository = tree.branch.repository
2237
 
            base_revision = common_ancestor(tree.branch.last_revision(), 
2238
 
                                            pending_merges[0], repository)
 
2309
            base_revision = common_ancestor(parents[0],
 
2310
                                            parents[1], repository)
2239
2311
            base_tree = repository.revision_tree(base_revision)
2240
 
            other_tree = repository.revision_tree(pending_merges[0])
 
2312
            other_tree = repository.revision_tree(parents[1])
2241
2313
            interesting_ids = None
2242
2314
            new_conflicts = []
2243
2315
            conflicts = tree.conflicts()
2246
2318
                for filename in file_list:
2247
2319
                    file_id = tree.path2id(filename)
2248
2320
                    if file_id is None:
2249
 
                        raise NotVersionedError(filename)
 
2321
                        raise errors.NotVersionedError(filename)
2250
2322
                    interesting_ids.add(file_id)
2251
2323
                    if tree.kind(file_id) != "directory":
2252
2324
                        continue
2254
2326
                    for name, ie in tree.inventory.iter_entries(file_id):
2255
2327
                        interesting_ids.add(ie.file_id)
2256
2328
                new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
2257
 
            transform_tree(tree, tree.basis_tree(), interesting_ids)
 
2329
            _mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
2258
2330
            tree.set_conflicts(ConflictList(new_conflicts))
2259
2331
            if file_list is None:
2260
2332
                restore_files = list(tree.iter_conflicts())
2263
2335
            for filename in restore_files:
2264
2336
                try:
2265
2337
                    restore(tree.abspath(filename))
2266
 
                except NotConflicted:
 
2338
                except errors.NotConflicted:
2267
2339
                    pass
2268
 
            conflicts = merge_inner(tree.branch, other_tree, base_tree,
2269
 
                                    this_tree=tree,
2270
 
                                    interesting_ids=interesting_ids, 
2271
 
                                    other_rev_id=pending_merges[0], 
2272
 
                                    merge_type=merge_type, 
2273
 
                                    show_base=show_base,
2274
 
                                    reprocess=reprocess)
 
2340
            conflicts = _mod_merge.merge_inner(
 
2341
                                      tree.branch, other_tree, base_tree,
 
2342
                                      this_tree=tree,
 
2343
                                      interesting_ids=interesting_ids,
 
2344
                                      other_rev_id=parents[1],
 
2345
                                      merge_type=merge_type,
 
2346
                                      show_base=show_base,
 
2347
                                      reprocess=reprocess)
2275
2348
        finally:
2276
2349
            tree.unlock()
2277
2350
        if conflicts > 0:
2280
2353
            return 0
2281
2354
 
2282
2355
class cmd_revert(Command):
2283
 
    """Reverse all changes since the last commit.
2284
 
 
2285
 
    Only versioned files are affected.  Specify filenames to revert only 
2286
 
    those files.  By default, any files that are changed will be backed up
2287
 
    first.  Backup files have a '~' appended to their name.
 
2356
    """Revert files to a previous revision.
 
2357
 
 
2358
    Giving a list of files will revert only those files.  Otherwise, all files
 
2359
    will be reverted.  If the revision is not specified with '--revision', the
 
2360
    last committed revision is used.
 
2361
 
 
2362
    To remove only some changes, without reverting to a prior version, use
 
2363
    merge instead.  For example, "merge . --r-2..-3" will remove the changes
 
2364
    introduced by -2, without affecting the changes introduced by -1.  Or
 
2365
    to remove certain changes on a hunk-by-hunk basis, see the Shelf plugin.
 
2366
    
 
2367
    By default, any files that have been manually changed will be backed up
 
2368
    first.  (Files changed only by merge are not backed up.)  Backup files have
 
2369
    '.~#~' appended to their name, where # is a number.
 
2370
 
 
2371
    When you provide files, you can use their current pathname or the pathname
 
2372
    from the target revision.  So you can use revert to "undelete" a file by
 
2373
    name.  If you name a directory, all the contents of that directory will be
 
2374
    reverted.
2288
2375
    """
2289
2376
    takes_options = ['revision', 'no-backup']
2290
2377
    takes_args = ['file*']
2291
2378
    aliases = ['merge-revert']
2292
2379
 
2293
2380
    def run(self, revision=None, no_backup=False, file_list=None):
2294
 
        from bzrlib.commands import parse_spec
2295
2381
        if file_list is not None:
2296
2382
            if len(file_list) == 0:
2297
 
                raise BzrCommandError("No files specified")
 
2383
                raise errors.BzrCommandError("No files specified")
2298
2384
        else:
2299
2385
            file_list = []
2300
2386
        
2303
2389
            # FIXME should be tree.last_revision
2304
2390
            rev_id = tree.last_revision()
2305
2391
        elif len(revision) != 1:
2306
 
            raise BzrCommandError('bzr revert --revision takes exactly 1 argument')
 
2392
            raise errors.BzrCommandError('bzr revert --revision takes exactly 1 argument')
2307
2393
        else:
2308
2394
            rev_id = revision[0].in_history(tree.branch).rev_id
2309
2395
        pb = ui.ui_factory.nested_progress_bar()
2395
2481
        if other_branch is None:
2396
2482
            other_branch = parent
2397
2483
            if other_branch is None:
2398
 
                raise BzrCommandError("No missing location known or specified.")
 
2484
                raise errors.BzrCommandError("No peer location known or specified.")
2399
2485
            print "Using last location: " + local_branch.get_parent()
2400
2486
        remote_branch = Branch.open(other_branch)
2401
2487
        if remote_branch.base == local_branch.base:
2405
2491
            remote_branch.lock_read()
2406
2492
            try:
2407
2493
                local_extra, remote_extra = find_unmerged(local_branch, remote_branch)
2408
 
                if (log_format == None):
 
2494
                if (log_format is None):
2409
2495
                    default = local_branch.get_config().log_format()
2410
2496
                    log_format = get_log_format(long=long, short=short, 
2411
2497
                                                line=line, default=default)
2459
2545
        import bzrlib.plugin
2460
2546
        from inspect import getdoc
2461
2547
        for name, plugin in bzrlib.plugin.all_plugins().items():
2462
 
            if hasattr(plugin, '__path__'):
 
2548
            if getattr(plugin, '__path__', None) is not None:
2463
2549
                print plugin.__path__[0]
2464
 
            elif hasattr(plugin, '__file__'):
 
2550
            elif getattr(plugin, '__file__', None) is not None:
2465
2551
                print plugin.__file__
2466
2552
            else:
2467
 
                print `plugin`
 
2553
                print repr(plugin)
2468
2554
                
2469
2555
            d = getdoc(plugin)
2470
2556
            if d:
2473
2559
 
2474
2560
class cmd_testament(Command):
2475
2561
    """Show testament (signing-form) of a revision."""
2476
 
    takes_options = ['revision', 'long', 
 
2562
    takes_options = ['revision', 
 
2563
                     Option('long', help='Produce long-format testament'), 
2477
2564
                     Option('strict', help='Produce a strict-format'
2478
2565
                            ' testament')]
2479
2566
    takes_args = ['branch?']
2529
2616
            if revision is None:
2530
2617
                revision_id = branch.last_revision()
2531
2618
            elif len(revision) != 1:
2532
 
                raise BzrCommandError('bzr annotate --revision takes exactly 1 argument')
 
2619
                raise errors.BzrCommandError('bzr annotate --revision takes exactly 1 argument')
2533
2620
            else:
2534
2621
                revision_id = revision[0].in_history(branch).rev_id
2535
2622
            file_id = tree.inventory.path2id(relpath)
2551
2638
    def run(self, revision_id_list=None, revision=None):
2552
2639
        import bzrlib.gpg as gpg
2553
2640
        if revision_id_list is not None and revision is not None:
2554
 
            raise BzrCommandError('You can only supply one of revision_id or --revision')
 
2641
            raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
2555
2642
        if revision_id_list is None and revision is None:
2556
 
            raise BzrCommandError('You must supply either --revision or a revision_id')
 
2643
            raise errors.BzrCommandError('You must supply either --revision or a revision_id')
2557
2644
        b = WorkingTree.open_containing(u'.')[0].branch
2558
2645
        gpg_strategy = gpg.GPGStrategy(b.get_config())
2559
2646
        if revision_id_list is not None:
2572
2659
                if to_revid is None:
2573
2660
                    to_revno = b.revno()
2574
2661
                if from_revno is None or to_revno is None:
2575
 
                    raise BzrCommandError('Cannot sign a range of non-revision-history revisions')
 
2662
                    raise errors.BzrCommandError('Cannot sign a range of non-revision-history revisions')
2576
2663
                for revno in range(from_revno, to_revno + 1):
2577
2664
                    b.repository.sign_revision(b.get_rev_id(revno), 
2578
2665
                                               gpg_strategy)
2579
2666
            else:
2580
 
                raise BzrCommandError('Please supply either one revision, or a range.')
 
2667
                raise errors.BzrCommandError('Please supply either one revision, or a range.')
2581
2668
 
2582
2669
 
2583
2670
class cmd_bind(Command):
2595
2682
        b_other = Branch.open(location)
2596
2683
        try:
2597
2684
            b.bind(b_other)
2598
 
        except DivergedBranches:
2599
 
            raise BzrCommandError('These branches have diverged.'
2600
 
                                  ' Try merging, and then bind again.')
 
2685
        except errors.DivergedBranches:
 
2686
            raise errors.BzrCommandError('These branches have diverged.'
 
2687
                                         ' Try merging, and then bind again.')
2601
2688
 
2602
2689
 
2603
2690
class cmd_unbind(Command):
2613
2700
    def run(self):
2614
2701
        b, relpath = Branch.open_containing(u'.')
2615
2702
        if not b.unbind():
2616
 
            raise BzrCommandError('Local branch is not bound')
 
2703
            raise errors.BzrCommandError('Local branch is not bound')
2617
2704
 
2618
2705
 
2619
2706
class cmd_uncommit(Command):
2721
2808
            pass
2722
2809
        
2723
2810
 
 
2811
class cmd_wait_until_signalled(Command):
 
2812
    """Test helper for test_start_and_stop_bzr_subprocess_send_signal.
 
2813
 
 
2814
    This just prints a line to signal when it is ready, then blocks on stdin.
 
2815
    """
 
2816
 
 
2817
    hidden = True
 
2818
 
 
2819
    def run(self):
 
2820
        sys.stdout.write("running\n")
 
2821
        sys.stdout.flush()
 
2822
        sys.stdin.readline()
 
2823
 
 
2824
 
 
2825
class cmd_serve(Command):
 
2826
    """Run the bzr server."""
 
2827
 
 
2828
    aliases = ['server']
 
2829
 
 
2830
    takes_options = [
 
2831
        Option('inet',
 
2832
               help='serve on stdin/out for use from inetd or sshd'),
 
2833
        Option('port',
 
2834
               help='listen for connections on nominated port of the form '
 
2835
                    '[hostname:]portnumber. Passing 0 as the port number will '
 
2836
                    'result in a dynamically allocated port.',
 
2837
               type=str),
 
2838
        Option('directory',
 
2839
               help='serve contents of directory',
 
2840
               type=unicode),
 
2841
        Option('allow-writes',
 
2842
               help='By default the server is a readonly server. Supplying '
 
2843
                    '--allow-writes enables write access to the contents of '
 
2844
                    'the served directory and below. '
 
2845
                ),
 
2846
        ]
 
2847
 
 
2848
    def run(self, port=None, inet=False, directory=None, allow_writes=False):
 
2849
        from bzrlib.transport import smart
 
2850
        from bzrlib.transport import get_transport
 
2851
        if directory is None:
 
2852
            directory = os.getcwd()
 
2853
        url = urlutils.local_path_to_url(directory)
 
2854
        if not allow_writes:
 
2855
            url = 'readonly+' + url
 
2856
        t = get_transport(url)
 
2857
        if inet:
 
2858
            server = smart.SmartStreamServer(sys.stdin, sys.stdout, t)
 
2859
        elif port is not None:
 
2860
            if ':' in port:
 
2861
                host, port = port.split(':')
 
2862
            else:
 
2863
                host = '127.0.0.1'
 
2864
            server = smart.SmartTCPServer(t, host=host, port=int(port))
 
2865
            print 'listening on port: ', server.port
 
2866
            sys.stdout.flush()
 
2867
        else:
 
2868
            raise errors.BzrCommandError("bzr serve requires one of --inet or --port")
 
2869
        server.serve()
 
2870
 
2724
2871
 
2725
2872
# command-line interpretation helper for merge-related commands
2726
 
def merge(other_revision, base_revision,
2727
 
          check_clean=True, ignore_zero=False,
2728
 
          this_dir=None, backup_files=False, merge_type=Merge3Merger,
2729
 
          file_list=None, show_base=False, reprocess=False,
2730
 
          pb=DummyProgress()):
 
2873
def _merge_helper(other_revision, base_revision,
 
2874
                  check_clean=True, ignore_zero=False,
 
2875
                  this_dir=None, backup_files=False,
 
2876
                  merge_type=None,
 
2877
                  file_list=None, show_base=False, reprocess=False,
 
2878
                  pb=DummyProgress()):
2731
2879
    """Merge changes into a tree.
2732
2880
 
2733
2881
    base_revision
2755
2903
    clients might prefer to call merge.merge_inner(), which has less magic 
2756
2904
    behavior.
2757
2905
    """
2758
 
    from bzrlib.merge import Merger
 
2906
    # Loading it late, so that we don't always have to import bzrlib.merge
 
2907
    if merge_type is None:
 
2908
        merge_type = _mod_merge.Merge3Merger
2759
2909
    if this_dir is None:
2760
2910
        this_dir = u'.'
2761
2911
    this_tree = WorkingTree.open_containing(this_dir)[0]
2762
 
    if show_base and not merge_type is Merge3Merger:
2763
 
        raise BzrCommandError("Show-base is not supported for this merge"
2764
 
                              " type. %s" % merge_type)
 
2912
    if show_base and not merge_type is _mod_merge.Merge3Merger:
 
2913
        raise errors.BzrCommandError("Show-base is not supported for this merge"
 
2914
                                     " type. %s" % merge_type)
2765
2915
    if reprocess and not merge_type.supports_reprocess:
2766
 
        raise BzrCommandError("Conflict reduction is not supported for merge"
2767
 
                              " type %s." % merge_type)
 
2916
        raise errors.BzrCommandError("Conflict reduction is not supported for merge"
 
2917
                                     " type %s." % merge_type)
2768
2918
    if reprocess and show_base:
2769
 
        raise BzrCommandError("Cannot do conflict reduction and show base.")
 
2919
        raise errors.BzrCommandError("Cannot do conflict reduction and show base.")
2770
2920
    try:
2771
 
        merger = Merger(this_tree.branch, this_tree=this_tree, pb=pb)
 
2921
        merger = _mod_merge.Merger(this_tree.branch, this_tree=this_tree,
 
2922
                                   pb=pb)
2772
2923
        merger.pp = ProgressPhase("Merge phase", 5, pb)
2773
2924
        merger.pp.next_phase()
2774
2925
        merger.check_basis(check_clean)
2791
2942
    return conflicts
2792
2943
 
2793
2944
 
 
2945
# Compatibility
 
2946
merge = _merge_helper
 
2947
 
 
2948
 
2794
2949
# these get imported and then picked up by the scan for cmd_*
2795
2950
# TODO: Some more consistent way to split command definitions across files;
2796
2951
# we do need to load at least some information about them to know of 
2797
2952
# aliases.  ideally we would avoid loading the implementation until the
2798
2953
# details were needed.
 
2954
from bzrlib.cmd_version_info import cmd_version_info
2799
2955
from bzrlib.conflicts import cmd_resolve, cmd_conflicts, restore
2800
2956
from bzrlib.bundle.commands import cmd_bundle_revisions
2801
2957
from bzrlib.sign_my_commits import cmd_sign_my_commits