~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Matt Nordhoff
  • Date: 2009-06-23 05:12:07 UTC
  • mto: This revision was merged to the branch mainline in revision 4474.
  • Revision ID: mnordhoff@mattnordhoff.com-20090623051207-fksdtbzkwtnrw9dd
Update _add_text docstrings that still referred to add_text.

Show diffs side-by-side

added added

removed removed

Lines of Context:
45
45
    revision as _mod_revision,
46
46
    symbol_versioning,
47
47
    transport,
 
48
    tree as _mod_tree,
48
49
    ui,
49
50
    urlutils,
50
51
    views,
120
121
 
121
122
 
122
123
def _get_one_revision_tree(command_name, revisions, branch=None, tree=None):
123
 
    """Get a revision tree. Not suitable for commands that change the tree.
124
 
    
125
 
    Specifically, the basis tree in dirstate trees is coupled to the dirstate
126
 
    and doing a commit/uncommit/pull will at best fail due to changing the
127
 
    basis revision data.
128
 
 
129
 
    If tree is passed in, it should be already locked, for lifetime management
130
 
    of the trees internal cached state.
131
 
    """
132
124
    if branch is None:
133
125
        branch = tree.branch
134
126
    if revisions is None:
458
450
        except errors.NoWorkingTree:
459
451
            raise errors.BzrCommandError("No working tree to remove")
460
452
        except errors.NotLocalUrl:
461
 
            raise errors.BzrCommandError("You cannot remove the working tree"
462
 
                                         " of a remote path")
 
453
            raise errors.BzrCommandError("You cannot remove the working tree of a "
 
454
                                         "remote path")
463
455
        if not force:
464
 
            # XXX: What about pending merges ? -- vila 20090629
465
 
            if working.has_changes(working.basis_tree()):
 
456
            changes = working.changes_from(working.basis_tree())
 
457
            if changes.has_changed():
466
458
                raise errors.UncommittedChanges(working)
467
459
 
468
460
        working_path = working.bzrdir.root_transport.base
469
461
        branch_path = working.branch.bzrdir.root_transport.base
470
462
        if working_path != branch_path:
471
 
            raise errors.BzrCommandError("You cannot remove the working tree"
472
 
                                         " from a lightweight checkout")
 
463
            raise errors.BzrCommandError("You cannot remove the working tree from "
 
464
                                         "a lightweight checkout")
473
465
 
474
466
        d.destroy_workingtree()
475
467
 
482
474
 
483
475
    _see_also = ['info']
484
476
    takes_args = ['location?']
485
 
    takes_options = [
486
 
        Option('tree', help='Show revno of working tree'),
487
 
        ]
488
477
 
489
478
    @display_command
490
 
    def run(self, tree=False, location=u'.'):
491
 
        if tree:
492
 
            try:
493
 
                wt = WorkingTree.open_containing(location)[0]
494
 
                wt.lock_read()
495
 
            except (errors.NoWorkingTree, errors.NotLocalUrl):
496
 
                raise errors.NoWorkingTree(location)
497
 
            try:
498
 
                revid = wt.last_revision()
499
 
                try:
500
 
                    revno_t = wt.branch.revision_id_to_dotted_revno(revid)
501
 
                except errors.NoSuchRevision:
502
 
                    revno_t = ('???',)
503
 
                revno = ".".join(str(n) for n in revno_t)
504
 
            finally:
505
 
                wt.unlock()
506
 
        else:
507
 
            b = Branch.open_containing(location)[0]
508
 
            b.lock_read()
509
 
            try:
510
 
                revno = b.revno()
511
 
            finally:
512
 
                b.unlock()
513
 
 
514
 
        self.outf.write(str(revno) + '\n')
 
479
    def run(self, location=u'.'):
 
480
        self.outf.write(str(Branch.open_containing(location)[0].revno()))
 
481
        self.outf.write('\n')
515
482
 
516
483
 
517
484
class cmd_revision_info(Command):
527
494
            short_name='d',
528
495
            type=unicode,
529
496
            ),
530
 
        Option('tree', help='Show revno of working tree'),
531
497
        ]
532
498
 
533
499
    @display_command
534
 
    def run(self, revision=None, directory=u'.', tree=False,
535
 
            revision_info_list=[]):
536
 
 
537
 
        try:
538
 
            wt = WorkingTree.open_containing(directory)[0]
539
 
            b = wt.branch
540
 
            wt.lock_read()
541
 
        except (errors.NoWorkingTree, errors.NotLocalUrl):
542
 
            wt = None
543
 
            b = Branch.open_containing(directory)[0]
544
 
            b.lock_read()
545
 
        try:
546
 
            revision_ids = []
547
 
            if revision is not None:
548
 
                revision_ids.extend(rev.as_revision_id(b) for rev in revision)
549
 
            if revision_info_list is not None:
550
 
                for rev_str in revision_info_list:
551
 
                    rev_spec = RevisionSpec.from_string(rev_str)
552
 
                    revision_ids.append(rev_spec.as_revision_id(b))
553
 
            # No arguments supplied, default to the last revision
554
 
            if len(revision_ids) == 0:
555
 
                if tree:
556
 
                    if wt is None:
557
 
                        raise errors.NoWorkingTree(directory)
558
 
                    revision_ids.append(wt.last_revision())
559
 
                else:
560
 
                    revision_ids.append(b.last_revision())
561
 
 
562
 
            revinfos = []
563
 
            maxlen = 0
564
 
            for revision_id in revision_ids:
565
 
                try:
566
 
                    dotted_revno = b.revision_id_to_dotted_revno(revision_id)
567
 
                    revno = '.'.join(str(i) for i in dotted_revno)
568
 
                except errors.NoSuchRevision:
569
 
                    revno = '???'
570
 
                maxlen = max(maxlen, len(revno))
571
 
                revinfos.append([revno, revision_id])
572
 
        finally:
573
 
            if wt is None:
574
 
                b.unlock()
575
 
            else:
576
 
                wt.unlock()
577
 
 
578
 
        for ri in revinfos:
579
 
            self.outf.write('%*s %s\n' % (maxlen, ri[0], ri[1]))
 
500
    def run(self, revision=None, directory=u'.', revision_info_list=[]):
 
501
 
 
502
        revs = []
 
503
        if revision is not None:
 
504
            revs.extend(revision)
 
505
        if revision_info_list is not None:
 
506
            for rev in revision_info_list:
 
507
                revs.append(RevisionSpec.from_string(rev))
 
508
 
 
509
        b = Branch.open_containing(directory)[0]
 
510
 
 
511
        if len(revs) == 0:
 
512
            revs.append(RevisionSpec.from_string('-1'))
 
513
 
 
514
        for rev in revs:
 
515
            revision_id = rev.as_revision_id(b)
 
516
            try:
 
517
                revno = '%4d' % (b.revision_id_to_revno(revision_id))
 
518
            except errors.NoSuchRevision:
 
519
                dotted_map = b.get_revision_id_to_revno_map()
 
520
                revno = '.'.join(str(i) for i in dotted_map[revision_id])
 
521
            print '%s %s' % (revno, revision_id)
580
522
 
581
523
 
582
524
class cmd_add(Command):
612
554
    branches that will be merged later (without showing the two different
613
555
    adds as a conflict). It is also useful when merging another project
614
556
    into a subdirectory of this one.
615
 
    
616
 
    Any files matching patterns in the ignore list will not be added
617
 
    unless they are explicitly mentioned.
618
557
    """
619
558
    takes_args = ['file*']
620
559
    takes_options = [
628
567
               help='Lookup file ids from this tree.'),
629
568
        ]
630
569
    encoding_type = 'replace'
631
 
    _see_also = ['remove', 'ignore']
 
570
    _see_also = ['remove']
632
571
 
633
572
    def run(self, file_list, no_recurse=False, dry_run=False, verbose=False,
634
573
            file_ids_from=None):
666
605
                    for path in ignored[glob]:
667
606
                        self.outf.write("ignored %s matching \"%s\"\n"
668
607
                                        % (path, glob))
 
608
            else:
 
609
                match_len = 0
 
610
                for glob, paths in ignored.items():
 
611
                    match_len += len(paths)
 
612
                self.outf.write("ignored %d file(s).\n" % match_len)
 
613
            self.outf.write("If you wish to add ignored files, "
 
614
                            "please add them explicitly by name. "
 
615
                            "(\"bzr ignored\" gives a list)\n")
669
616
 
670
617
 
671
618
class cmd_mkdir(Command):
803
750
        if len(names_list) < 2:
804
751
            raise errors.BzrCommandError("missing file argument")
805
752
        tree, rel_names = tree_files(names_list, canonicalize=False)
806
 
        tree.lock_tree_write()
 
753
        tree.lock_write()
807
754
        try:
808
755
            self._run(tree, names_list, rel_names, after)
809
756
        finally:
817
764
            raise errors.BzrCommandError('--after cannot be specified with'
818
765
                                         ' --auto.')
819
766
        work_tree, file_list = tree_files(names_list, default_branch='.')
820
 
        work_tree.lock_tree_write()
 
767
        work_tree.lock_write()
821
768
        try:
822
769
            rename_map.RenameMap.guess_renames(work_tree, dry_run)
823
770
        finally:
999
946
            if branch_to.get_parent() is None or remember:
1000
947
                branch_to.set_parent(branch_from.base)
1001
948
 
1002
 
        if branch_from is not branch_to:
1003
 
            branch_from.lock_read()
 
949
        if revision is not None:
 
950
            revision_id = revision.as_revision_id(branch_from)
 
951
 
 
952
        branch_to.lock_write()
1004
953
        try:
1005
 
            if revision is not None:
1006
 
                revision_id = revision.as_revision_id(branch_from)
1007
 
 
1008
 
            branch_to.lock_write()
1009
 
            try:
1010
 
                if tree_to is not None:
1011
 
                    view_info = _get_view_info_for_change_reporter(tree_to)
1012
 
                    change_reporter = delta._ChangeReporter(
1013
 
                        unversioned_filter=tree_to.is_ignored,
1014
 
                        view_info=view_info)
1015
 
                    result = tree_to.pull(
1016
 
                        branch_from, overwrite, revision_id, change_reporter,
1017
 
                        possible_transports=possible_transports, local=local)
1018
 
                else:
1019
 
                    result = branch_to.pull(
1020
 
                        branch_from, overwrite, revision_id, local=local)
1021
 
 
1022
 
                result.report(self.outf)
1023
 
                if verbose and result.old_revid != result.new_revid:
1024
 
                    log.show_branch_change(
1025
 
                        branch_to, self.outf, result.old_revno,
1026
 
                        result.old_revid)
1027
 
            finally:
1028
 
                branch_to.unlock()
 
954
            if tree_to is not None:
 
955
                view_info = _get_view_info_for_change_reporter(tree_to)
 
956
                change_reporter = delta._ChangeReporter(
 
957
                    unversioned_filter=tree_to.is_ignored, view_info=view_info)
 
958
                result = tree_to.pull(branch_from, overwrite, revision_id,
 
959
                                      change_reporter,
 
960
                                      possible_transports=possible_transports,
 
961
                                      local=local)
 
962
            else:
 
963
                result = branch_to.pull(branch_from, overwrite, revision_id,
 
964
                                      local=local)
 
965
 
 
966
            result.report(self.outf)
 
967
            if verbose and result.old_revid != result.new_revid:
 
968
                log.show_branch_change(branch_to, self.outf, result.old_revno,
 
969
                                       result.old_revid)
1029
970
        finally:
1030
 
            if branch_from is not branch_to:
1031
 
                branch_from.unlock()
 
971
            branch_to.unlock()
1032
972
 
1033
973
 
1034
974
class cmd_push(Command):
1081
1021
                'for the commit history. Only the work not present in the '
1082
1022
                'referenced branch is included in the branch created.',
1083
1023
            type=unicode),
1084
 
        Option('strict',
1085
 
               help='Refuse to push if there are uncommitted changes in'
1086
 
               ' the working tree, --no-strict disables the check.'),
1087
1024
        ]
1088
1025
    takes_args = ['location?']
1089
1026
    encoding_type = 'replace'
1091
1028
    def run(self, location=None, remember=False, overwrite=False,
1092
1029
        create_prefix=False, verbose=False, revision=None,
1093
1030
        use_existing_dir=False, directory=None, stacked_on=None,
1094
 
        stacked=False, strict=None):
 
1031
        stacked=False):
1095
1032
        from bzrlib.push import _show_push_branch
1096
1033
 
 
1034
        # Get the source branch and revision_id
1097
1035
        if directory is None:
1098
1036
            directory = '.'
1099
 
        # Get the source branch
1100
 
        (tree, br_from,
1101
 
         _unused) = bzrdir.BzrDir.open_containing_tree_or_branch(directory)
1102
 
        if strict is None:
1103
 
            strict = br_from.get_config().get_user_option_as_bool('push_strict')
1104
 
        if strict is None: strict = True # default value
1105
 
        # Get the tip's revision_id
 
1037
        br_from = Branch.open_containing(directory)[0]
1106
1038
        revision = _get_one_revision('push', revision)
1107
1039
        if revision is not None:
1108
1040
            revision_id = revision.in_history(br_from).rev_id
1109
1041
        else:
1110
1042
            revision_id = None
1111
 
        if strict and tree is not None and revision_id is None:
1112
 
            if (tree.has_changes(tree.basis_tree())
1113
 
                or len(tree.get_parent_ids()) > 1):
1114
 
                raise errors.UncommittedChanges(
1115
 
                    tree, more='Use --no-strict to force the push.')
1116
 
            if tree.last_revision() != tree.branch.last_revision():
1117
 
                # The tree has lost sync with its branch, there is little
1118
 
                # chance that the user is aware of it but he can still force
1119
 
                # the push with --no-strict
1120
 
                raise errors.OutOfDateTree(
1121
 
                    tree, more='Use --no-strict to force the push.')
1122
1043
 
1123
1044
        # Get the stacked_on branch, if any
1124
1045
        if stacked_on is not None:
1157
1078
 
1158
1079
 
1159
1080
class cmd_branch(Command):
1160
 
    """Create a new branch that is a copy of an existing branch.
 
1081
    """Create a new copy of a branch.
1161
1082
 
1162
1083
    If the TO_LOCATION is omitted, the last component of the FROM_LOCATION will
1163
1084
    be used.  In other words, "branch ../foo/bar" will attempt to create ./bar.
1176
1097
        help='Hard-link working tree files where possible.'),
1177
1098
        Option('no-tree',
1178
1099
            help="Create a branch without a working-tree."),
1179
 
        Option('switch',
1180
 
            help="Switch the checkout in the current directory "
1181
 
                 "to the new branch."),
1182
1100
        Option('stacked',
1183
1101
            help='Create a stacked branch referring to the source branch. '
1184
1102
                'The new branch will depend on the availability of the source '
1185
1103
                'branch for all operations.'),
1186
1104
        Option('standalone',
1187
1105
               help='Do not use a shared repository, even if available.'),
1188
 
        Option('use-existing-dir',
1189
 
               help='By default branch will fail if the target'
1190
 
                    ' directory exists, but does not already'
1191
 
                    ' have a control directory.  This flag will'
1192
 
                    ' allow branch to proceed.'),
1193
1106
        ]
1194
1107
    aliases = ['get', 'clone']
1195
1108
 
1196
1109
    def run(self, from_location, to_location=None, revision=None,
1197
 
            hardlink=False, stacked=False, standalone=False, no_tree=False,
1198
 
            use_existing_dir=False, switch=False):
1199
 
        from bzrlib import switch as _mod_switch
 
1110
            hardlink=False, stacked=False, standalone=False, no_tree=False):
1200
1111
        from bzrlib.tag import _merge_tags_if_possible
 
1112
 
1201
1113
        accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1202
1114
            from_location)
1203
 
        if (accelerator_tree is not None and
1204
 
            accelerator_tree.supports_content_filtering()):
1205
 
            accelerator_tree = None
1206
1115
        revision = _get_one_revision('branch', revision)
1207
1116
        br_from.lock_read()
1208
1117
        try:
1219
1128
            try:
1220
1129
                to_transport.mkdir('.')
1221
1130
            except errors.FileExists:
1222
 
                if not use_existing_dir:
1223
 
                    raise errors.BzrCommandError('Target directory "%s" '
1224
 
                        'already exists.' % to_location)
1225
 
                else:
1226
 
                    try:
1227
 
                        bzrdir.BzrDir.open_from_transport(to_transport)
1228
 
                    except errors.NotBranchError:
1229
 
                        pass
1230
 
                    else:
1231
 
                        raise errors.AlreadyBranchError(to_location)
 
1131
                raise errors.BzrCommandError('Target directory "%s" already'
 
1132
                                             ' exists.' % to_location)
1232
1133
            except errors.NoSuchFile:
1233
1134
                raise errors.BzrCommandError('Parent of "%s" does not exist.'
1234
1135
                                             % to_location)
1257
1158
            except (errors.NotStacked, errors.UnstackableBranchFormat,
1258
1159
                errors.UnstackableRepositoryFormat), e:
1259
1160
                note('Branched %d revision(s).' % branch.revno())
1260
 
            if switch:
1261
 
                # Switch to the new branch
1262
 
                wt, _ = WorkingTree.open_containing('.')
1263
 
                _mod_switch.switch(wt.bzrdir, branch)
1264
 
                note('Switched to branch: %s',
1265
 
                    urlutils.unescape_for_display(branch.base, 'utf-8'))
1266
1161
        finally:
1267
1162
            br_from.unlock()
1268
1163
 
1485
1380
            title='Deletion Strategy', value_switches=True, enum_switch=False,
1486
1381
            safe='Only delete files if they can be'
1487
1382
                 ' safely recovered (default).',
1488
 
            keep='Delete from bzr but leave the working copy.',
 
1383
            keep="Don't delete any files.",
1489
1384
            force='Delete all the specified files, even if they can not be '
1490
1385
                'recovered and even if they are non-empty directories.')]
1491
1386
    aliases = ['rm', 'del']
1726
1621
                branch.set_append_revisions_only(True)
1727
1622
            except errors.UpgradeRequired:
1728
1623
                raise errors.BzrCommandError('This branch format cannot be set'
1729
 
                    ' to append-revisions-only.  Try --default.')
 
1624
                    ' to append-revisions-only.  Try --experimental-branch6')
1730
1625
        if not is_quiet():
1731
1626
            from bzrlib.info import describe_layout, describe_format
1732
1627
            try:
2471
2366
 
2472
2367
        if path is None:
2473
2368
            fs_path = '.'
 
2369
            prefix = ''
2474
2370
        else:
2475
2371
            if from_root:
2476
2372
                raise errors.BzrCommandError('cannot specify both --from-root'
2477
2373
                                             ' and PATH')
2478
2374
            fs_path = path
 
2375
            prefix = path
2479
2376
        tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
2480
2377
            fs_path)
2481
 
 
2482
 
        # Calculate the prefix to use
2483
 
        prefix = None
2484
2378
        if from_root:
2485
 
            if relpath:
2486
 
                prefix = relpath + '/'
2487
 
        elif fs_path != '.':
2488
 
            prefix = fs_path + '/'
2489
 
 
 
2379
            relpath = u''
 
2380
        elif relpath:
 
2381
            relpath += '/'
2490
2382
        if revision is not None or tree is None:
2491
2383
            tree = _get_one_revision_tree('ls', revision, branch=branch)
2492
2384
 
2500
2392
 
2501
2393
        tree.lock_read()
2502
2394
        try:
2503
 
            for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
2504
 
                from_dir=relpath, recursive=recursive):
2505
 
                # Apply additional masking
2506
 
                if not all and not selection[fc]:
2507
 
                    continue
2508
 
                if kind is not None and fkind != kind:
2509
 
                    continue
2510
 
                if apply_view:
2511
 
                    try:
2512
 
                        if relpath:
2513
 
                            fullpath = osutils.pathjoin(relpath, fp)
2514
 
                        else:
2515
 
                            fullpath = fp
2516
 
                        views.check_path_in_view(tree, fullpath)
2517
 
                    except errors.FileOutsideView:
2518
 
                        continue
2519
 
 
2520
 
                # Output the entry
2521
 
                if prefix:
2522
 
                    fp = osutils.pathjoin(prefix, fp)
2523
 
                kindch = entry.kind_character()
2524
 
                outstring = fp + kindch
2525
 
                ui.ui_factory.clear_term()
2526
 
                if verbose:
2527
 
                    outstring = '%-8s %s' % (fc, outstring)
2528
 
                    if show_ids and fid is not None:
2529
 
                        outstring = "%-50s %s" % (outstring, fid)
2530
 
                    self.outf.write(outstring + '\n')
2531
 
                elif null:
2532
 
                    self.outf.write(fp + '\0')
2533
 
                    if show_ids:
2534
 
                        if fid is not None:
2535
 
                            self.outf.write(fid)
2536
 
                        self.outf.write('\0')
2537
 
                    self.outf.flush()
2538
 
                else:
2539
 
                    if show_ids:
 
2395
            for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
 
2396
                if fp.startswith(relpath):
 
2397
                    rp = fp[len(relpath):]
 
2398
                    fp = osutils.pathjoin(prefix, rp)
 
2399
                    if not recursive and '/' in rp:
 
2400
                        continue
 
2401
                    if not all and not selection[fc]:
 
2402
                        continue
 
2403
                    if kind is not None and fkind != kind:
 
2404
                        continue
 
2405
                    if apply_view:
 
2406
                        try:
 
2407
                            views.check_path_in_view(tree, fp)
 
2408
                        except errors.FileOutsideView:
 
2409
                            continue
 
2410
                    kindch = entry.kind_character()
 
2411
                    outstring = fp + kindch
 
2412
                    ui.ui_factory.clear_term()
 
2413
                    if verbose:
 
2414
                        outstring = '%-8s %s' % (fc, outstring)
 
2415
                        if show_ids and fid is not None:
 
2416
                            outstring = "%-50s %s" % (outstring, fid)
 
2417
                        self.outf.write(outstring + '\n')
 
2418
                    elif null:
 
2419
                        self.outf.write(fp + '\0')
 
2420
                        if show_ids:
 
2421
                            if fid is not None:
 
2422
                                self.outf.write(fid)
 
2423
                            self.outf.write('\0')
 
2424
                        self.outf.flush()
 
2425
                    else:
2540
2426
                        if fid is not None:
2541
2427
                            my_id = fid
2542
2428
                        else:
2543
2429
                            my_id = ''
2544
 
                        self.outf.write('%-50s %s\n' % (outstring, my_id))
2545
 
                    else:
2546
 
                        self.outf.write(outstring + '\n')
 
2430
                        if show_ids:
 
2431
                            self.outf.write('%-50s %s\n' % (outstring, my_id))
 
2432
                        else:
 
2433
                            self.outf.write(outstring + '\n')
2547
2434
        finally:
2548
2435
            tree.unlock()
2549
2436
 
3038
2925
                raise errors.BzrCommandError("empty commit message specified")
3039
2926
            return my_message
3040
2927
 
3041
 
        # The API permits a commit with a filter of [] to mean 'select nothing'
3042
 
        # but the command line should not do that.
3043
 
        if not selected_list:
3044
 
            selected_list = None
3045
2928
        try:
3046
2929
            tree.commit(message_callback=get_message,
3047
2930
                        specific_files=selected_list,
3077
2960
    The working tree and branch checks will only give output if a problem is
3078
2961
    detected. The output fields of the repository check are:
3079
2962
 
3080
 
    revisions
3081
 
        This is just the number of revisions checked.  It doesn't
3082
 
        indicate a problem.
3083
 
 
3084
 
    versionedfiles
3085
 
        This is just the number of versionedfiles checked.  It
3086
 
        doesn't indicate a problem.
3087
 
 
3088
 
    unreferenced ancestors
3089
 
        Texts that are ancestors of other texts, but
3090
 
        are not properly referenced by the revision ancestry.  This is a
3091
 
        subtle problem that Bazaar can work around.
3092
 
 
3093
 
    unique file texts
3094
 
        This is the total number of unique file contents
3095
 
        seen in the checked revisions.  It does not indicate a problem.
3096
 
 
3097
 
    repeated file texts
3098
 
        This is the total number of repeated texts seen
3099
 
        in the checked revisions.  Texts can be repeated when their file
3100
 
        entries are modified, but the file contents are not.  It does not
3101
 
        indicate a problem.
 
2963
        revisions: This is just the number of revisions checked.  It doesn't
 
2964
            indicate a problem.
 
2965
        versionedfiles: This is just the number of versionedfiles checked.  It
 
2966
            doesn't indicate a problem.
 
2967
        unreferenced ancestors: Texts that are ancestors of other texts, but
 
2968
            are not properly referenced by the revision ancestry.  This is a
 
2969
            subtle problem that Bazaar can work around.
 
2970
        unique file texts: This is the total number of unique file contents
 
2971
            seen in the checked revisions.  It does not indicate a problem.
 
2972
        repeated file texts: This is the total number of repeated texts seen
 
2973
            in the checked revisions.  Texts can be repeated when their file
 
2974
            entries are modified, but the file contents are not.  It does not
 
2975
            indicate a problem.
3102
2976
 
3103
2977
    If no restrictions are specified, all Bazaar data that is found at the given
3104
2978
    location will be checked.
3382
3256
                     Option('lsprof-timed',
3383
3257
                            help='Generate lsprof output for benchmarked'
3384
3258
                                 ' sections of code.'),
3385
 
                     Option('lsprof-tests',
3386
 
                            help='Generate lsprof output for each test.'),
3387
3259
                     Option('cache-dir', type=str,
3388
3260
                            help='Cache intermediate benchmark output in this '
3389
3261
                                 'directory.'),
3430
3302
            first=False, list_only=False,
3431
3303
            randomize=None, exclude=None, strict=False,
3432
3304
            load_list=None, debugflag=None, starting_with=None, subunit=False,
3433
 
            parallel=None, lsprof_tests=False):
 
3305
            parallel=None):
3434
3306
        from bzrlib.tests import selftest
3435
3307
        import bzrlib.benchmarks as benchmarks
3436
3308
        from bzrlib.benchmarks import tree_creator
3470
3342
                              "transport": transport,
3471
3343
                              "test_suite_factory": test_suite_factory,
3472
3344
                              "lsprof_timed": lsprof_timed,
3473
 
                              "lsprof_tests": lsprof_tests,
3474
3345
                              "bench_history": benchfile,
3475
3346
                              "matching_tests_first": first,
3476
3347
                              "list_only": list_only,
3584
3455
    merge refuses to run if there are any uncommitted changes, unless
3585
3456
    --force is given.
3586
3457
 
3587
 
    To select only some changes to merge, use "merge -i", which will prompt
3588
 
    you to apply each diff hunk and file change, similar to "shelve".
3589
 
 
3590
3458
    :Examples:
3591
3459
        To merge the latest revision from bzr.dev::
3592
3460
 
3630
3498
               short_name='d',
3631
3499
               type=unicode,
3632
3500
               ),
3633
 
        Option('preview', help='Instead of merging, show a diff of the'
3634
 
               ' merge.'),
3635
 
        Option('interactive', help='Select changes interactively.',
3636
 
            short_name='i')
 
3501
        Option('preview', help='Instead of merging, show a diff of the merge.')
3637
3502
    ]
3638
3503
 
3639
3504
    def run(self, location=None, revision=None, force=False,
3641
3506
            uncommitted=False, pull=False,
3642
3507
            directory=None,
3643
3508
            preview=False,
3644
 
            interactive=False,
3645
3509
            ):
3646
3510
        if merge_type is None:
3647
3511
            merge_type = _mod_merge.Merge3Merger
3659
3523
        except errors.NoSuchRevision:
3660
3524
            basis_tree = tree.basis_tree()
3661
3525
        if not force:
3662
 
            if tree.has_changes(basis_tree):
 
3526
            changes = tree.changes_from(basis_tree)
 
3527
            if changes.has_changed():
3663
3528
                raise errors.UncommittedChanges(tree)
3664
3529
 
3665
3530
        view_info = _get_view_info_for_change_reporter(tree)
3692
3557
                if revision is not None and len(revision) > 0:
3693
3558
                    raise errors.BzrCommandError('Cannot use --uncommitted and'
3694
3559
                        ' --revision at the same time.')
3695
 
                merger = self.get_merger_from_uncommitted(tree, location, pb,
3696
 
                                                          cleanups)
 
3560
                location = self._select_branch_location(tree, location)[0]
 
3561
                other_tree, other_path = WorkingTree.open_containing(location)
 
3562
                merger = _mod_merge.Merger.from_uncommitted(tree, other_tree,
 
3563
                    pb)
3697
3564
                allow_pending = False
 
3565
                if other_path != '':
 
3566
                    merger.interesting_files = [other_path]
3698
3567
 
3699
3568
            if merger is None:
3700
3569
                merger, allow_pending = self._get_merger_from_branch(tree,
3718
3587
                    return 0
3719
3588
            merger.check_basis(False)
3720
3589
            if preview:
3721
 
                return self._do_preview(merger, cleanups)
3722
 
            elif interactive:
3723
 
                return self._do_interactive(merger, cleanups)
 
3590
                return self._do_preview(merger)
3724
3591
            else:
3725
3592
                return self._do_merge(merger, change_reporter, allow_pending,
3726
3593
                                      verified)
3728
3595
            for cleanup in reversed(cleanups):
3729
3596
                cleanup()
3730
3597
 
3731
 
    def _get_preview(self, merger, cleanups):
 
3598
    def _do_preview(self, merger):
 
3599
        from bzrlib.diff import show_diff_trees
3732
3600
        tree_merger = merger.make_merger()
3733
3601
        tt = tree_merger.make_preview_transform()
3734
 
        cleanups.append(tt.finalize)
3735
 
        result_tree = tt.get_preview_tree()
3736
 
        return result_tree
3737
 
 
3738
 
    def _do_preview(self, merger, cleanups):
3739
 
        from bzrlib.diff import show_diff_trees
3740
 
        result_tree = self._get_preview(merger, cleanups)
3741
 
        show_diff_trees(merger.this_tree, result_tree, self.outf,
3742
 
                        old_label='', new_label='')
 
3602
        try:
 
3603
            result_tree = tt.get_preview_tree()
 
3604
            show_diff_trees(merger.this_tree, result_tree, self.outf,
 
3605
                            old_label='', new_label='')
 
3606
        finally:
 
3607
            tt.finalize()
3743
3608
 
3744
3609
    def _do_merge(self, merger, change_reporter, allow_pending, verified):
3745
3610
        merger.change_reporter = change_reporter
3753
3618
        else:
3754
3619
            return 0
3755
3620
 
3756
 
    def _do_interactive(self, merger, cleanups):
3757
 
        """Perform an interactive merge.
3758
 
 
3759
 
        This works by generating a preview tree of the merge, then using
3760
 
        Shelver to selectively remove the differences between the working tree
3761
 
        and the preview tree.
3762
 
        """
3763
 
        from bzrlib import shelf_ui
3764
 
        result_tree = self._get_preview(merger, cleanups)
3765
 
        writer = bzrlib.option.diff_writer_registry.get()
3766
 
        shelver = shelf_ui.Shelver(merger.this_tree, result_tree, destroy=True,
3767
 
                                   reporter=shelf_ui.ApplyReporter(),
3768
 
                                   diff_writer=writer(sys.stdout))
3769
 
        shelver.run()
3770
 
 
3771
3621
    def sanity_check_merger(self, merger):
3772
3622
        if (merger.show_base and
3773
3623
            not merger.merge_type is _mod_merge.Merge3Merger):
3808
3658
            base_branch, base_path = Branch.open_containing(base_loc,
3809
3659
                possible_transports)
3810
3660
        # Find the revision ids
3811
 
        other_revision_id = None
3812
 
        base_revision_id = None
3813
 
        if revision is not None:
3814
 
            if len(revision) >= 1:
3815
 
                other_revision_id = revision[-1].as_revision_id(other_branch)
3816
 
            if len(revision) == 2:
3817
 
                base_revision_id = revision[0].as_revision_id(base_branch)
3818
 
        if other_revision_id is None:
 
3661
        if revision is None or len(revision) < 1 or revision[-1] is None:
3819
3662
            other_revision_id = _mod_revision.ensure_null(
3820
3663
                other_branch.last_revision())
 
3664
        else:
 
3665
            other_revision_id = revision[-1].as_revision_id(other_branch)
 
3666
        if (revision is not None and len(revision) == 2
 
3667
            and revision[0] is not None):
 
3668
            base_revision_id = revision[0].as_revision_id(base_branch)
 
3669
        else:
 
3670
            base_revision_id = None
3821
3671
        # Remember where we merge from
3822
3672
        if ((remember or tree.branch.get_submit_branch() is None) and
3823
3673
             user_location is not None):
3832
3682
            allow_pending = True
3833
3683
        return merger, allow_pending
3834
3684
 
3835
 
    def get_merger_from_uncommitted(self, tree, location, pb, cleanups):
3836
 
        """Get a merger for uncommitted changes.
3837
 
 
3838
 
        :param tree: The tree the merger should apply to.
3839
 
        :param location: The location containing uncommitted changes.
3840
 
        :param pb: The progress bar to use for showing progress.
3841
 
        :param cleanups: A list of operations to perform to clean up the
3842
 
            temporary directories, unfinalized objects, etc.
3843
 
        """
3844
 
        location = self._select_branch_location(tree, location)[0]
3845
 
        other_tree, other_path = WorkingTree.open_containing(location)
3846
 
        merger = _mod_merge.Merger.from_uncommitted(tree, other_tree, pb)
3847
 
        if other_path != '':
3848
 
            merger.interesting_files = [other_path]
3849
 
        return merger
3850
 
 
3851
3685
    def _select_branch_location(self, tree, user_location, revision=None,
3852
3686
                                index=None):
3853
3687
        """Select a branch location, according to possible inputs.
4831
4665
        try:
4832
4666
            containing_tree.extract(sub_id)
4833
4667
        except errors.RootNotRich:
4834
 
            raise errors.RichRootUpgradeRequired(containing_tree.branch.base)
 
4668
            raise errors.UpgradeRequired(containing_tree.branch.base)
4835
4669
 
4836
4670
 
4837
4671
class cmd_merge_directive(Command):
5006
4840
               help='Write merge directive to this file; '
5007
4841
                    'use - for stdout.',
5008
4842
               type=unicode),
5009
 
        Option('strict',
5010
 
               help='Refuse to send if there are uncommitted changes in'
5011
 
               ' the working tree, --no-strict disables the check.'),
5012
4843
        Option('mail-to', help='Mail the request to this address.',
5013
4844
               type=unicode),
5014
4845
        'revision',
5015
4846
        'message',
5016
4847
        Option('body', help='Body for the email.', type=unicode),
5017
4848
        RegistryOption('format',
5018
 
                       help='Use the specified output format.',
5019
 
                       lazy_registry=('bzrlib.send', 'format_registry')),
 
4849
                       help='Use the specified output format.', 
 
4850
                       lazy_registry=('bzrlib.send', 'format_registry'))
5020
4851
        ]
5021
4852
 
5022
4853
    def run(self, submit_branch=None, public_branch=None, no_bundle=False,
5023
4854
            no_patch=False, revision=None, remember=False, output=None,
5024
 
            format=None, mail_to=None, message=None, body=None,
5025
 
            strict=None, **kwargs):
 
4855
            format=None, mail_to=None, message=None, body=None, **kwargs):
5026
4856
        from bzrlib.send import send
5027
4857
        return send(submit_branch, revision, public_branch, remember,
5028
 
                    format, no_bundle, no_patch, output,
5029
 
                    kwargs.get('from', '.'), mail_to, message, body,
5030
 
                    self.outf,
5031
 
                    strict=strict)
 
4858
                         format, no_bundle, no_patch, output,
 
4859
                         kwargs.get('from', '.'), mail_to, message, body,
 
4860
                         self.outf)
5032
4861
 
5033
4862
 
5034
4863
class cmd_bundle_revisions(cmd_send):
5078
4907
               type=unicode),
5079
4908
        Option('output', short_name='o', help='Write directive to this file.',
5080
4909
               type=unicode),
5081
 
        Option('strict',
5082
 
               help='Refuse to bundle revisions if there are uncommitted'
5083
 
               ' changes in the working tree, --no-strict disables the check.'),
5084
4910
        'revision',
5085
4911
        RegistryOption('format',
5086
4912
                       help='Use the specified output format.',
5094
4920
 
5095
4921
    def run(self, submit_branch=None, public_branch=None, no_bundle=False,
5096
4922
            no_patch=False, revision=None, remember=False, output=None,
5097
 
            format=None, strict=None, **kwargs):
 
4923
            format=None, **kwargs):
5098
4924
        if output is None:
5099
4925
            output = '-'
5100
4926
        from bzrlib.send import send
5101
4927
        return send(submit_branch, revision, public_branch, remember,
5102
4928
                         format, no_bundle, no_patch, output,
5103
4929
                         kwargs.get('from', '.'), None, None, None,
5104
 
                         self.outf, strict=strict)
 
4930
                         self.outf)
5105
4931
 
5106
4932
 
5107
4933
class cmd_tag(Command):
5279
5105
            ),
5280
5106
        Option('bind-to', help='Branch to bind checkout to.', type=str),
5281
5107
        Option('force',
5282
 
            help='Perform reconfiguration even if local changes'
5283
 
            ' will be lost.'),
5284
 
        Option('stacked-on',
5285
 
            help='Reconfigure a branch to be stacked on another branch.',
5286
 
            type=unicode,
5287
 
            ),
5288
 
        Option('unstacked',
5289
 
            help='Reconfigure a branch to be unstacked.  This '
5290
 
                'may require copying substantial data into it.',
5291
 
            ),
 
5108
               help='Perform reconfiguration even if local changes'
 
5109
               ' will be lost.')
5292
5110
        ]
5293
5111
 
5294
 
    def run(self, location=None, target_type=None, bind_to=None, force=False,
5295
 
            stacked_on=None,
5296
 
            unstacked=None):
 
5112
    def run(self, location=None, target_type=None, bind_to=None, force=False):
5297
5113
        directory = bzrdir.BzrDir.open(location)
5298
 
        if stacked_on and unstacked:
5299
 
            raise BzrCommandError("Can't use both --stacked-on and --unstacked")
5300
 
        elif stacked_on is not None:
5301
 
            reconfigure.ReconfigureStackedOn().apply(directory, stacked_on)
5302
 
        elif unstacked:
5303
 
            reconfigure.ReconfigureUnstacked().apply(directory)
5304
 
        # At the moment you can use --stacked-on and a different
5305
 
        # reconfiguration shape at the same time; there seems no good reason
5306
 
        # to ban it.
5307
5114
        if target_type is None:
5308
 
            if stacked_on or unstacked:
5309
 
                return
5310
 
            else:
5311
 
                raise errors.BzrCommandError('No target configuration '
5312
 
                    'specified')
 
5115
            raise errors.BzrCommandError('No target configuration specified')
5313
5116
        elif target_type == 'branch':
5314
5117
            reconfiguration = reconfigure.Reconfigure.to_branch(directory)
5315
5118
        elif target_type == 'tree':
5358
5161
 
5359
5162
    takes_args = ['to_location']
5360
5163
    takes_options = [Option('force',
5361
 
                        help='Switch even if local commits will be lost.'),
5362
 
                     Option('create-branch', short_name='b',
5363
 
                        help='Create the target branch from this one before'
5364
 
                             ' switching to it.'),
 
5164
                        help='Switch even if local commits will be lost.')
5365
5165
                     ]
5366
5166
 
5367
 
    def run(self, to_location, force=False, create_branch=False):
 
5167
    def run(self, to_location, force=False):
5368
5168
        from bzrlib import switch
5369
5169
        tree_location = '.'
5370
5170
        control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5372
5172
            branch = control_dir.open_branch()
5373
5173
            had_explicit_nick = branch.get_config().has_explicit_nickname()
5374
5174
        except errors.NotBranchError:
5375
 
            branch = None
5376
5175
            had_explicit_nick = False
5377
 
        if create_branch:
5378
 
            if branch is None:
5379
 
                raise errors.BzrCommandError('cannot create branch without'
5380
 
                                             ' source branch')
5381
 
            if '/' not in to_location and '\\' not in to_location:
5382
 
                # This path is meant to be relative to the existing branch
5383
 
                this_url = self._get_branch_location(control_dir)
5384
 
                to_location = urlutils.join(this_url, '..', to_location)
5385
 
            to_branch = branch.bzrdir.sprout(to_location,
5386
 
                                 possible_transports=[branch.bzrdir.root_transport],
5387
 
                                 source_branch=branch).open_branch()
5388
 
            # try:
5389
 
            #     from_branch = control_dir.open_branch()
5390
 
            # except errors.NotBranchError:
5391
 
            #     raise BzrCommandError('Cannot create a branch from this'
5392
 
            #         ' location when we cannot open this branch')
5393
 
            # from_branch.bzrdir.sprout(
5394
 
            pass
5395
 
        else:
5396
 
            try:
5397
 
                to_branch = Branch.open(to_location)
5398
 
            except errors.NotBranchError:
5399
 
                this_url = self._get_branch_location(control_dir)
5400
 
                to_branch = Branch.open(
5401
 
                    urlutils.join(this_url, '..', to_location))
 
5176
        try:
 
5177
            to_branch = Branch.open(to_location)
 
5178
        except errors.NotBranchError:
 
5179
            this_url = self._get_branch_location(control_dir)
 
5180
            to_branch = Branch.open(
 
5181
                urlutils.join(this_url, '..', to_location))
5402
5182
        switch.switch(control_dir, to_branch, force)
5403
5183
        if had_explicit_nick:
5404
5184
            branch = control_dir.open_branch() #get the new branch!
5647
5427
        if writer is None:
5648
5428
            writer = bzrlib.option.diff_writer_registry.get()
5649
5429
        try:
5650
 
            shelver = Shelver.from_args(writer(sys.stdout), revision, all,
5651
 
                file_list, message, destroy=destroy)
5652
 
            try:
5653
 
                shelver.run()
5654
 
            finally:
5655
 
                shelver.work_tree.unlock()
 
5430
            Shelver.from_args(writer(sys.stdout), revision, all, file_list,
 
5431
                              message, destroy=destroy).run()
5656
5432
        except errors.UserAbort:
5657
5433
            return 0
5658
5434
 
5697
5473
 
5698
5474
    def run(self, shelf_id=None, action='apply'):
5699
5475
        from bzrlib.shelf_ui import Unshelver
5700
 
        unshelver = Unshelver.from_args(shelf_id, action)
5701
 
        try:
5702
 
            unshelver.run()
5703
 
        finally:
5704
 
            unshelver.tree.unlock()
 
5476
        Unshelver.from_args(shelf_id, action).run()
5705
5477
 
5706
5478
 
5707
5479
class cmd_clean_tree(Command):