/brz/remove-bazaar

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

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Jonathan Lange
  • Date: 2009-12-09 09:20:42 UTC
  • mfrom: (4881 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4907.
  • Revision ID: jml@canonical.com-20091209092042-s2zgqcf8f39yzxpj
Merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
43
43
    reconfigure,
44
44
    rename_map,
45
45
    revision as _mod_revision,
 
46
    static_tuple,
46
47
    symbol_versioning,
 
48
    timestamp,
47
49
    transport,
48
50
    ui,
49
51
    urlutils,
120
122
 
121
123
 
122
124
def _get_one_revision_tree(command_name, revisions, branch=None, tree=None):
 
125
    """Get a revision tree. Not suitable for commands that change the tree.
 
126
    
 
127
    Specifically, the basis tree in dirstate trees is coupled to the dirstate
 
128
    and doing a commit/uncommit/pull will at best fail due to changing the
 
129
    basis revision data.
 
130
 
 
131
    If tree is passed in, it should be already locked, for lifetime management
 
132
    of the trees internal cached state.
 
133
    """
123
134
    if branch is None:
124
135
        branch = tree.branch
125
136
    if revisions is None:
248
259
    unknown
249
260
        Not versioned and not matching an ignore pattern.
250
261
 
 
262
    Additionally for directories, symlinks and files with an executable
 
263
    bit, Bazaar indicates their type using a trailing character: '/', '@'
 
264
    or '*' respectively.
 
265
 
251
266
    To see ignored files use 'bzr ignored'.  For details on the
252
267
    changes to file texts, use 'bzr diff'.
253
268
 
422
437
        for node in bt.iter_all_entries():
423
438
            # Node is made up of:
424
439
            # (index, key, value, [references])
425
 
            self.outf.write('%s\n' % (node[1:],))
 
440
            refs_as_tuples = static_tuple.as_tuples(node[3])
 
441
            as_tuple = (tuple(node[1]), node[2], refs_as_tuples)
 
442
            self.outf.write('%s\n' % (as_tuple,))
426
443
 
427
444
 
428
445
class cmd_remove_tree(Command):
449
466
        except errors.NoWorkingTree:
450
467
            raise errors.BzrCommandError("No working tree to remove")
451
468
        except errors.NotLocalUrl:
452
 
            raise errors.BzrCommandError("You cannot remove the working tree of a "
453
 
                                         "remote path")
 
469
            raise errors.BzrCommandError("You cannot remove the working tree"
 
470
                                         " of a remote path")
454
471
        if not force:
455
 
            changes = working.changes_from(working.basis_tree())
456
 
            if changes.has_changed():
 
472
            if (working.has_changes()):
457
473
                raise errors.UncommittedChanges(working)
458
474
 
459
475
        working_path = working.bzrdir.root_transport.base
460
476
        branch_path = working.branch.bzrdir.root_transport.base
461
477
        if working_path != branch_path:
462
 
            raise errors.BzrCommandError("You cannot remove the working tree from "
463
 
                                         "a lightweight checkout")
 
478
            raise errors.BzrCommandError("You cannot remove the working tree"
 
479
                                         " from a lightweight checkout")
464
480
 
465
481
        d.destroy_workingtree()
466
482
 
603
619
    branches that will be merged later (without showing the two different
604
620
    adds as a conflict). It is also useful when merging another project
605
621
    into a subdirectory of this one.
 
622
    
 
623
    Any files matching patterns in the ignore list will not be added
 
624
    unless they are explicitly mentioned.
606
625
    """
607
626
    takes_args = ['file*']
608
627
    takes_options = [
616
635
               help='Lookup file ids from this tree.'),
617
636
        ]
618
637
    encoding_type = 'replace'
619
 
    _see_also = ['remove']
 
638
    _see_also = ['remove', 'ignore']
620
639
 
621
640
    def run(self, file_list, no_recurse=False, dry_run=False, verbose=False,
622
641
            file_ids_from=None):
641
660
        if base_tree:
642
661
            base_tree.lock_read()
643
662
        try:
644
 
            file_list = self._maybe_expand_globs(file_list)
645
663
            tree, file_list = tree_files_for_add(file_list)
646
664
            added, ignored = tree.smart_add(file_list, not
647
665
                no_recurse, action=action, save=not dry_run)
654
672
                    for path in ignored[glob]:
655
673
                        self.outf.write("ignored %s matching \"%s\"\n"
656
674
                                        % (path, glob))
657
 
            else:
658
 
                match_len = 0
659
 
                for glob, paths in ignored.items():
660
 
                    match_len += len(paths)
661
 
                self.outf.write("ignored %d file(s).\n" % match_len)
662
 
            self.outf.write("If you wish to add ignored files, "
663
 
                            "please add them explicitly by name. "
664
 
                            "(\"bzr ignored\" gives a list)\n")
665
675
 
666
676
 
667
677
class cmd_mkdir(Command):
799
809
        if len(names_list) < 2:
800
810
            raise errors.BzrCommandError("missing file argument")
801
811
        tree, rel_names = tree_files(names_list, canonicalize=False)
802
 
        tree.lock_write()
 
812
        tree.lock_tree_write()
803
813
        try:
804
814
            self._run(tree, names_list, rel_names, after)
805
815
        finally:
813
823
            raise errors.BzrCommandError('--after cannot be specified with'
814
824
                                         ' --auto.')
815
825
        work_tree, file_list = tree_files(names_list, default_branch='.')
816
 
        work_tree.lock_write()
 
826
        work_tree.lock_tree_write()
817
827
        try:
818
828
            rename_map.RenameMap.guess_renames(work_tree, dry_run)
819
829
        finally:
844
854
            # All entries reference existing inventory items, so fix them up
845
855
            # for cicp file-systems.
846
856
            rel_names = tree.get_canonical_inventory_paths(rel_names)
847
 
            for pair in tree.move(rel_names[:-1], rel_names[-1], after=after):
848
 
                self.outf.write("%s => %s\n" % pair)
 
857
            for src, dest in tree.move(rel_names[:-1], rel_names[-1], after=after):
 
858
                if not is_quiet():
 
859
                    self.outf.write("%s => %s\n" % (src, dest))
849
860
        else:
850
861
            if len(names_list) != 2:
851
862
                raise errors.BzrCommandError('to mv multiple files the'
895
906
            dest = osutils.pathjoin(dest_parent, dest_tail)
896
907
            mutter("attempting to move %s => %s", src, dest)
897
908
            tree.rename_one(src, dest, after=after)
898
 
            self.outf.write("%s => %s\n" % (src, dest))
 
909
            if not is_quiet():
 
910
                self.outf.write("%s => %s\n" % (src, dest))
899
911
 
900
912
 
901
913
class cmd_pull(Command):
902
914
    """Turn this branch into a mirror of another branch.
903
915
 
904
 
    This command only works on branches that have not diverged.  Branches are
905
 
    considered diverged if the destination branch's most recent commit is one
906
 
    that has not been merged (directly or indirectly) into the parent.
 
916
    By default, this command only works on branches that have not diverged.
 
917
    Branches are considered diverged if the destination branch's most recent 
 
918
    commit is one that has not been merged (directly or indirectly) into the 
 
919
    parent.
907
920
 
908
921
    If branches have diverged, you can use 'bzr merge' to integrate the changes
909
922
    from one into the other.  Once one branch has merged, the other should
910
923
    be able to pull it again.
911
924
 
912
 
    If you want to forget your local changes and just update your branch to
913
 
    match the remote one, use pull --overwrite.
 
925
    If you want to replace your local changes and just want your branch to
 
926
    match the remote one, use pull --overwrite. This will work even if the two
 
927
    branches have diverged.
914
928
 
915
929
    If there is no default location set, the first pull will set it.  After
916
930
    that, you can omit the location to use the default.  To change the
1096
1110
        (tree, br_from,
1097
1111
         _unused) = bzrdir.BzrDir.open_containing_tree_or_branch(directory)
1098
1112
        if strict is None:
1099
 
            strict = br_from.get_config().get_user_option('push_strict')
1100
 
            if strict is not None:
1101
 
                # FIXME: This should be better supported by config
1102
 
                # -- vila 20090611
1103
 
                bools = dict(yes=True, no=False, on=True, off=False,
1104
 
                             true=True, false=False)
1105
 
                try:
1106
 
                    strict = bools[strict.lower()]
1107
 
                except KeyError:
1108
 
                    strict = None
 
1113
            strict = br_from.get_config().get_user_option_as_bool('push_strict')
 
1114
        if strict is None: strict = True # default value
1109
1115
        # Get the tip's revision_id
1110
1116
        revision = _get_one_revision('push', revision)
1111
1117
        if revision is not None:
1112
1118
            revision_id = revision.in_history(br_from).rev_id
1113
1119
        else:
1114
1120
            revision_id = None
1115
 
        if (tree is not None and revision_id is None
1116
 
            and (strict is None or strict)): # Default to True:
1117
 
            changes = tree.changes_from(tree.basis_tree())
1118
 
            if changes.has_changed() or len(tree.get_parent_ids()) > 1:
 
1121
        if strict and tree is not None and revision_id is None:
 
1122
            if (tree.has_changes()):
1119
1123
                raise errors.UncommittedChanges(
1120
1124
                    tree, more='Use --no-strict to force the push.')
1121
1125
            if tree.last_revision() != tree.branch.last_revision():
1181
1185
        help='Hard-link working tree files where possible.'),
1182
1186
        Option('no-tree',
1183
1187
            help="Create a branch without a working-tree."),
 
1188
        Option('switch',
 
1189
            help="Switch the checkout in the current directory "
 
1190
                 "to the new branch."),
1184
1191
        Option('stacked',
1185
1192
            help='Create a stacked branch referring to the source branch. '
1186
1193
                'The new branch will depend on the availability of the source '
1197
1204
 
1198
1205
    def run(self, from_location, to_location=None, revision=None,
1199
1206
            hardlink=False, stacked=False, standalone=False, no_tree=False,
1200
 
            use_existing_dir=False):
 
1207
            use_existing_dir=False, switch=False):
 
1208
        from bzrlib import switch as _mod_switch
1201
1209
        from bzrlib.tag import _merge_tags_if_possible
1202
 
 
1203
1210
        accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1204
1211
            from_location)
1205
 
        if (accelerator_tree is not None and
1206
 
            accelerator_tree.supports_content_filtering()):
1207
 
            accelerator_tree = None
1208
1212
        revision = _get_one_revision('branch', revision)
1209
1213
        br_from.lock_read()
1210
1214
        try:
1259
1263
            except (errors.NotStacked, errors.UnstackableBranchFormat,
1260
1264
                errors.UnstackableRepositoryFormat), e:
1261
1265
                note('Branched %d revision(s).' % branch.revno())
 
1266
            if switch:
 
1267
                # Switch to the new branch
 
1268
                wt, _ = WorkingTree.open_containing('.')
 
1269
                _mod_switch.switch(wt.bzrdir, branch)
 
1270
                note('Switched to branch: %s',
 
1271
                    urlutils.unescape_for_display(branch.base, 'utf-8'))
1262
1272
        finally:
1263
1273
            br_from.unlock()
1264
1274
 
1481
1491
            title='Deletion Strategy', value_switches=True, enum_switch=False,
1482
1492
            safe='Only delete files if they can be'
1483
1493
                 ' safely recovered (default).',
1484
 
            keep="Don't delete any files.",
 
1494
            keep='Delete from bzr but leave the working copy.',
1485
1495
            force='Delete all the specified files, even if they can not be '
1486
1496
                'recovered and even if they are non-empty directories.')]
1487
1497
    aliases = ['rm', 'del']
1669
1679
                lazy_registry=('bzrlib.bzrdir', 'format_registry'),
1670
1680
                converter=lambda name: bzrdir.format_registry.make_bzrdir(name),
1671
1681
                value_switches=True,
1672
 
                title="Branch Format",
 
1682
                title="Branch format",
1673
1683
                ),
1674
1684
         Option('append-revisions-only',
1675
1685
                help='Never change revnos or the existing log.'
1744
1754
 
1745
1755
 
1746
1756
class cmd_init_repository(Command):
1747
 
    """Create a shared repository to hold branches.
 
1757
    """Create a shared repository for branches to share storage space.
1748
1758
 
1749
1759
    New branches created under the repository directory will store their
1750
 
    revisions in the repository, not in the branch directory.
 
1760
    revisions in the repository, not in the branch directory.  For branches
 
1761
    with shared history, this reduces the amount of storage needed and 
 
1762
    speeds up the creation of new branches.
1751
1763
 
1752
 
    If the --no-trees option is used then the branches in the repository
1753
 
    will not have working trees by default.
 
1764
    If the --no-trees option is given then the branches in the repository
 
1765
    will not have working trees by default.  They will still exist as 
 
1766
    directories on disk, but they will not have separate copies of the 
 
1767
    files at a certain revision.  This can be useful for repositories that
 
1768
    store branches which are interacted with through checkouts or remote
 
1769
    branches, such as on a server.
1754
1770
 
1755
1771
    :Examples:
1756
 
        Create a shared repositories holding just branches::
 
1772
        Create a shared repository holding just branches::
1757
1773
 
1758
1774
            bzr init-repo --no-trees repo
1759
1775
            bzr init repo/trunk
1825
1841
 
1826
1842
            bzr diff -r1
1827
1843
 
1828
 
        Difference between revision 2 and revision 1::
1829
 
 
1830
 
            bzr diff -r1..2
1831
 
 
1832
 
        Difference between revision 2 and revision 1 for branch xxx::
1833
 
 
1834
 
            bzr diff -r1..2 xxx
 
1844
        Difference between revision 3 and revision 1::
 
1845
 
 
1846
            bzr diff -r1..3
 
1847
 
 
1848
        Difference between revision 3 and revision 1 for branch xxx::
 
1849
 
 
1850
            bzr diff -r1..3 xxx
 
1851
 
 
1852
        To see the changes introduced in revision X::
 
1853
        
 
1854
            bzr diff -cX
 
1855
 
 
1856
        Note that in the case of a merge, the -c option shows the changes
 
1857
        compared to the left hand parent. To see the changes against
 
1858
        another parent, use::
 
1859
 
 
1860
            bzr diff -r<chosen_parent>..X
 
1861
 
 
1862
        The changes introduced by revision 2 (equivalent to -r1..2)::
 
1863
 
 
1864
            bzr diff -c2
1835
1865
 
1836
1866
        Show just the differences for file NEWS::
1837
1867
 
1883
1913
    @display_command
1884
1914
    def run(self, revision=None, file_list=None, diff_options=None,
1885
1915
            prefix=None, old=None, new=None, using=None):
1886
 
        from bzrlib.diff import _get_trees_to_diff, show_diff_trees
 
1916
        from bzrlib.diff import get_trees_and_branches_to_diff, show_diff_trees
1887
1917
 
1888
1918
        if (prefix is None) or (prefix == '0'):
1889
1919
            # diff -p0 format
1903
1933
            raise errors.BzrCommandError('bzr diff --revision takes exactly'
1904
1934
                                         ' one or two revision specifiers')
1905
1935
 
1906
 
        old_tree, new_tree, specific_files, extra_trees = \
1907
 
                _get_trees_to_diff(file_list, revision, old, new,
1908
 
                apply_view=True)
 
1936
        (old_tree, new_tree,
 
1937
         old_branch, new_branch,
 
1938
         specific_files, extra_trees) = get_trees_and_branches_to_diff(
 
1939
            file_list, revision, old, new, apply_view=True)
1909
1940
        return show_diff_trees(old_tree, new_tree, sys.stdout,
1910
1941
                               specific_files=specific_files,
1911
1942
                               external_diff_options=diff_options,
2270
2301
 
2271
2302
        file_ids = []
2272
2303
        filter_by_dir = False
2273
 
        if file_list:
2274
 
            # find the file ids to log and check for directory filtering
2275
 
            b, file_info_list, rev1, rev2 = _get_info_for_log_files(revision,
2276
 
                file_list)
2277
 
            for relpath, file_id, kind in file_info_list:
2278
 
                if file_id is None:
2279
 
                    raise errors.BzrCommandError(
2280
 
                        "Path unknown at end or start of revision range: %s" %
2281
 
                        relpath)
2282
 
                # If the relpath is the top of the tree, we log everything
2283
 
                if relpath == '':
2284
 
                    file_ids = []
2285
 
                    break
 
2304
        b = None
 
2305
        try:
 
2306
            if file_list:
 
2307
                # find the file ids to log and check for directory filtering
 
2308
                b, file_info_list, rev1, rev2 = _get_info_for_log_files(
 
2309
                    revision, file_list)
 
2310
                for relpath, file_id, kind in file_info_list:
 
2311
                    if file_id is None:
 
2312
                        raise errors.BzrCommandError(
 
2313
                            "Path unknown at end or start of revision range: %s" %
 
2314
                            relpath)
 
2315
                    # If the relpath is the top of the tree, we log everything
 
2316
                    if relpath == '':
 
2317
                        file_ids = []
 
2318
                        break
 
2319
                    else:
 
2320
                        file_ids.append(file_id)
 
2321
                    filter_by_dir = filter_by_dir or (
 
2322
                        kind in ['directory', 'tree-reference'])
 
2323
            else:
 
2324
                # log everything
 
2325
                # FIXME ? log the current subdir only RBC 20060203
 
2326
                if revision is not None \
 
2327
                        and len(revision) > 0 and revision[0].get_branch():
 
2328
                    location = revision[0].get_branch()
2286
2329
                else:
2287
 
                    file_ids.append(file_id)
2288
 
                filter_by_dir = filter_by_dir or (
2289
 
                    kind in ['directory', 'tree-reference'])
2290
 
        else:
2291
 
            # log everything
2292
 
            # FIXME ? log the current subdir only RBC 20060203
2293
 
            if revision is not None \
2294
 
                    and len(revision) > 0 and revision[0].get_branch():
2295
 
                location = revision[0].get_branch()
2296
 
            else:
2297
 
                location = '.'
2298
 
            dir, relpath = bzrdir.BzrDir.open_containing(location)
2299
 
            b = dir.open_branch()
2300
 
            rev1, rev2 = _get_revision_range(revision, b, self.name())
2301
 
 
2302
 
        # Decide on the type of delta & diff filtering to use
2303
 
        # TODO: add an --all-files option to make this configurable & consistent
2304
 
        if not verbose:
2305
 
            delta_type = None
2306
 
        else:
2307
 
            delta_type = 'full'
2308
 
        if not show_diff:
2309
 
            diff_type = None
2310
 
        elif file_ids:
2311
 
            diff_type = 'partial'
2312
 
        else:
2313
 
            diff_type = 'full'
2314
 
 
2315
 
        b.lock_read()
2316
 
        try:
 
2330
                    location = '.'
 
2331
                dir, relpath = bzrdir.BzrDir.open_containing(location)
 
2332
                b = dir.open_branch()
 
2333
                b.lock_read()
 
2334
                rev1, rev2 = _get_revision_range(revision, b, self.name())
 
2335
 
 
2336
            # Decide on the type of delta & diff filtering to use
 
2337
            # TODO: add an --all-files option to make this configurable & consistent
 
2338
            if not verbose:
 
2339
                delta_type = None
 
2340
            else:
 
2341
                delta_type = 'full'
 
2342
            if not show_diff:
 
2343
                diff_type = None
 
2344
            elif file_ids:
 
2345
                diff_type = 'partial'
 
2346
            else:
 
2347
                diff_type = 'full'
 
2348
 
2317
2349
            # Build the log formatter
2318
2350
            if log_format is None:
2319
2351
                log_format = log.log_formatter_registry.get_default(b)
 
2352
            # Make a non-encoding output to include the diffs - bug 328007
 
2353
            unencoded_output = ui.ui_factory.make_output_stream(encoding_type='exact')
2320
2354
            lf = log_format(show_ids=show_ids, to_file=self.outf,
 
2355
                            to_exact_file=unencoded_output,
2321
2356
                            show_timezone=timezone,
2322
2357
                            delta_format=get_verbosity_level(),
2323
2358
                            levels=levels,
2349
2384
                diff_type=diff_type, _match_using_deltas=match_using_deltas)
2350
2385
            Logger(b, rqst).show(lf)
2351
2386
        finally:
2352
 
            b.unlock()
 
2387
            if b is not None:
 
2388
                b.unlock()
2353
2389
 
2354
2390
 
2355
2391
def _get_revision_range(revisionspec_list, branch, command_name):
2419
2455
    @display_command
2420
2456
    def run(self, filename):
2421
2457
        tree, relpath = WorkingTree.open_containing(filename)
 
2458
        file_id = tree.path2id(relpath)
2422
2459
        b = tree.branch
2423
 
        file_id = tree.path2id(relpath)
2424
 
        for revno, revision_id, what in log.find_touching_revisions(b, file_id):
2425
 
            self.outf.write("%6d %s\n" % (revno, what))
 
2460
        b.lock_read()
 
2461
        try:
 
2462
            touching_revs = log.find_touching_revisions(b, file_id)
 
2463
            for revno, revision_id, what in touching_revs:
 
2464
                self.outf.write("%6d %s\n" % (revno, what))
 
2465
        finally:
 
2466
            b.unlock()
2426
2467
 
2427
2468
 
2428
2469
class cmd_ls(Command):
2480
2521
        if from_root:
2481
2522
            if relpath:
2482
2523
                prefix = relpath + '/'
2483
 
        elif fs_path != '.':
 
2524
        elif fs_path != '.' and not fs_path.endswith('/'):
2484
2525
            prefix = fs_path + '/'
2485
2526
 
2486
2527
        if revision is not None or tree is None:
2562
2603
 
2563
2604
    See ``bzr help patterns`` for details on the syntax of patterns.
2564
2605
 
 
2606
    If a .bzrignore file does not exist, the ignore command
 
2607
    will create one and add the specified files or patterns to the newly
 
2608
    created file. The ignore command will also automatically add the 
 
2609
    .bzrignore file to be versioned. Creating a .bzrignore file without
 
2610
    the use of the ignore command will require an explicit add command.
 
2611
 
2565
2612
    To remove patterns from the ignore list, edit the .bzrignore file.
2566
2613
    After adding, editing or deleting that file either indirectly by
2567
2614
    using this command or directly by using an editor, be sure to commit
2935
2982
             Option('strict',
2936
2983
                    help="Refuse to commit if there are unknown "
2937
2984
                    "files in the working tree."),
 
2985
             Option('commit-time', type=str,
 
2986
                    help="Manually set a commit time using commit date "
 
2987
                    "format, e.g. '2009-10-10 08:00:00 +0100'."),
2938
2988
             ListOption('fixes', type=str,
2939
2989
                    help="Mark a bug as being fixed by this revision "
2940
2990
                         "(see \"bzr help bugs\")."),
2947
2997
                         "the master branch until a normal commit "
2948
2998
                         "is performed."
2949
2999
                    ),
2950
 
              Option('show-diff',
2951
 
                     help='When no message is supplied, show the diff along'
2952
 
                     ' with the status summary in the message editor.'),
 
3000
             Option('show-diff',
 
3001
                    help='When no message is supplied, show the diff along'
 
3002
                    ' with the status summary in the message editor.'),
2953
3003
             ]
2954
3004
    aliases = ['ci', 'checkin']
2955
3005
 
2974
3024
 
2975
3025
    def run(self, message=None, file=None, verbose=False, selected_list=None,
2976
3026
            unchanged=False, strict=False, local=False, fixes=None,
2977
 
            author=None, show_diff=False, exclude=None):
 
3027
            author=None, show_diff=False, exclude=None, commit_time=None):
2978
3028
        from bzrlib.errors import (
2979
3029
            PointlessCommit,
2980
3030
            ConflictsInTree,
2986
3036
            make_commit_message_template_encoded
2987
3037
        )
2988
3038
 
 
3039
        commit_stamp = offset = None
 
3040
        if commit_time is not None:
 
3041
            try:
 
3042
                commit_stamp, offset = timestamp.parse_patch_date(commit_time)
 
3043
            except ValueError, e:
 
3044
                raise errors.BzrCommandError(
 
3045
                    "Could not parse --commit-time: " + str(e))
 
3046
 
2989
3047
        # TODO: Need a blackbox test for invoking the external editor; may be
2990
3048
        # slightly problematic to run this cross-platform.
2991
3049
 
3011
3069
        if local and not tree.branch.get_bound_location():
3012
3070
            raise errors.LocalRequiresBoundBranch()
3013
3071
 
 
3072
        if message is not None:
 
3073
            try:
 
3074
                file_exists = osutils.lexists(message)
 
3075
            except UnicodeError:
 
3076
                # The commit message contains unicode characters that can't be
 
3077
                # represented in the filesystem encoding, so that can't be a
 
3078
                # file.
 
3079
                file_exists = False
 
3080
            if file_exists:
 
3081
                warning_msg = (
 
3082
                    'The commit message is a file name: "%(f)s".\n'
 
3083
                    '(use --file "%(f)s" to take commit message from that file)'
 
3084
                    % { 'f': message })
 
3085
                ui.ui_factory.show_warning(warning_msg)
 
3086
 
3014
3087
        def get_message(commit_obj):
3015
3088
            """Callback to get commit message"""
3016
3089
            my_message = message
 
3090
            if my_message is not None and '\r' in my_message:
 
3091
                my_message = my_message.replace('\r\n', '\n')
 
3092
                my_message = my_message.replace('\r', '\n')
3017
3093
            if my_message is None and not file:
3018
3094
                t = make_commit_message_template_encoded(tree,
3019
3095
                        selected_list, diff=show_diff,
3034
3110
                raise errors.BzrCommandError("empty commit message specified")
3035
3111
            return my_message
3036
3112
 
 
3113
        # The API permits a commit with a filter of [] to mean 'select nothing'
 
3114
        # but the command line should not do that.
 
3115
        if not selected_list:
 
3116
            selected_list = None
3037
3117
        try:
3038
3118
            tree.commit(message_callback=get_message,
3039
3119
                        specific_files=selected_list,
3040
3120
                        allow_pointless=unchanged, strict=strict, local=local,
3041
3121
                        reporter=None, verbose=verbose, revprops=properties,
3042
 
                        authors=author,
 
3122
                        authors=author, timestamp=commit_stamp,
 
3123
                        timezone=offset,
3043
3124
                        exclude=safe_relpath_files(tree, exclude))
3044
3125
        except PointlessCommit:
3045
3126
            # FIXME: This should really happen before the file is read in;
3332
3413
    Tests that need working space on disk use a common temporary directory,
3333
3414
    typically inside $TMPDIR or /tmp.
3334
3415
 
 
3416
    If you set BZR_TEST_PDB=1 when running selftest, failing tests will drop
 
3417
    into a pdb postmortem session.
 
3418
 
3335
3419
    :Examples:
3336
3420
        Run only tests relating to 'ignore'::
3337
3421
 
3374
3458
                     Option('lsprof-timed',
3375
3459
                            help='Generate lsprof output for benchmarked'
3376
3460
                                 ' sections of code.'),
 
3461
                     Option('lsprof-tests',
 
3462
                            help='Generate lsprof output for each test.'),
3377
3463
                     Option('cache-dir', type=str,
3378
3464
                            help='Cache intermediate benchmark output in this '
3379
3465
                                 'directory.'),
3420
3506
            first=False, list_only=False,
3421
3507
            randomize=None, exclude=None, strict=False,
3422
3508
            load_list=None, debugflag=None, starting_with=None, subunit=False,
3423
 
            parallel=None):
 
3509
            parallel=None, lsprof_tests=False):
3424
3510
        from bzrlib.tests import selftest
3425
3511
        import bzrlib.benchmarks as benchmarks
3426
3512
        from bzrlib.benchmarks import tree_creator
3460
3546
                              "transport": transport,
3461
3547
                              "test_suite_factory": test_suite_factory,
3462
3548
                              "lsprof_timed": lsprof_timed,
 
3549
                              "lsprof_tests": lsprof_tests,
3463
3550
                              "bench_history": benchfile,
3464
3551
                              "matching_tests_first": first,
3465
3552
                              "list_only": list_only,
3573
3660
    merge refuses to run if there are any uncommitted changes, unless
3574
3661
    --force is given.
3575
3662
 
 
3663
    To select only some changes to merge, use "merge -i", which will prompt
 
3664
    you to apply each diff hunk and file change, similar to "shelve".
 
3665
 
3576
3666
    :Examples:
3577
3667
        To merge the latest revision from bzr.dev::
3578
3668
 
3586
3676
 
3587
3677
            bzr merge -r 81..82 ../bzr.dev
3588
3678
 
3589
 
        To apply a merge directive contained in /tmp/merge:
 
3679
        To apply a merge directive contained in /tmp/merge::
3590
3680
 
3591
3681
            bzr merge /tmp/merge
3592
3682
    """
3616
3706
               short_name='d',
3617
3707
               type=unicode,
3618
3708
               ),
3619
 
        Option('preview', help='Instead of merging, show a diff of the merge.')
 
3709
        Option('preview', help='Instead of merging, show a diff of the'
 
3710
               ' merge.'),
 
3711
        Option('interactive', help='Select changes interactively.',
 
3712
            short_name='i')
3620
3713
    ]
3621
3714
 
3622
3715
    def run(self, location=None, revision=None, force=False,
3624
3717
            uncommitted=False, pull=False,
3625
3718
            directory=None,
3626
3719
            preview=False,
 
3720
            interactive=False,
3627
3721
            ):
3628
3722
        if merge_type is None:
3629
3723
            merge_type = _mod_merge.Merge3Merger
3635
3729
        verified = 'inapplicable'
3636
3730
        tree = WorkingTree.open_containing(directory)[0]
3637
3731
 
3638
 
        # die as quickly as possible if there are uncommitted changes
3639
3732
        try:
3640
3733
            basis_tree = tree.revision_tree(tree.last_revision())
3641
3734
        except errors.NoSuchRevision:
3642
3735
            basis_tree = tree.basis_tree()
 
3736
 
 
3737
        # die as quickly as possible if there are uncommitted changes
3643
3738
        if not force:
3644
 
            changes = tree.changes_from(basis_tree)
3645
 
            if changes.has_changed():
 
3739
            if tree.has_changes():
3646
3740
                raise errors.UncommittedChanges(tree)
3647
3741
 
3648
3742
        view_info = _get_view_info_for_change_reporter(tree)
3699
3793
                                       merger.other_rev_id)
3700
3794
                    result.report(self.outf)
3701
3795
                    return 0
3702
 
            merger.check_basis(False)
 
3796
            if merger.this_basis is None:
 
3797
                raise errors.BzrCommandError(
 
3798
                    "This branch has no commits."
 
3799
                    " (perhaps you would prefer 'bzr pull')")
3703
3800
            if preview:
3704
 
                return self._do_preview(merger)
 
3801
                return self._do_preview(merger, cleanups)
 
3802
            elif interactive:
 
3803
                return self._do_interactive(merger, cleanups)
3705
3804
            else:
3706
3805
                return self._do_merge(merger, change_reporter, allow_pending,
3707
3806
                                      verified)
3709
3808
            for cleanup in reversed(cleanups):
3710
3809
                cleanup()
3711
3810
 
3712
 
    def _do_preview(self, merger):
3713
 
        from bzrlib.diff import show_diff_trees
 
3811
    def _get_preview(self, merger, cleanups):
3714
3812
        tree_merger = merger.make_merger()
3715
3813
        tt = tree_merger.make_preview_transform()
3716
 
        try:
3717
 
            result_tree = tt.get_preview_tree()
3718
 
            show_diff_trees(merger.this_tree, result_tree, self.outf,
3719
 
                            old_label='', new_label='')
3720
 
        finally:
3721
 
            tt.finalize()
 
3814
        cleanups.append(tt.finalize)
 
3815
        result_tree = tt.get_preview_tree()
 
3816
        return result_tree
 
3817
 
 
3818
    def _do_preview(self, merger, cleanups):
 
3819
        from bzrlib.diff import show_diff_trees
 
3820
        result_tree = self._get_preview(merger, cleanups)
 
3821
        show_diff_trees(merger.this_tree, result_tree, self.outf,
 
3822
                        old_label='', new_label='')
3722
3823
 
3723
3824
    def _do_merge(self, merger, change_reporter, allow_pending, verified):
3724
3825
        merger.change_reporter = change_reporter
3732
3833
        else:
3733
3834
            return 0
3734
3835
 
 
3836
    def _do_interactive(self, merger, cleanups):
 
3837
        """Perform an interactive merge.
 
3838
 
 
3839
        This works by generating a preview tree of the merge, then using
 
3840
        Shelver to selectively remove the differences between the working tree
 
3841
        and the preview tree.
 
3842
        """
 
3843
        from bzrlib import shelf_ui
 
3844
        result_tree = self._get_preview(merger, cleanups)
 
3845
        writer = bzrlib.option.diff_writer_registry.get()
 
3846
        shelver = shelf_ui.Shelver(merger.this_tree, result_tree, destroy=True,
 
3847
                                   reporter=shelf_ui.ApplyReporter(),
 
3848
                                   diff_writer=writer(sys.stdout))
 
3849
        try:
 
3850
            shelver.run()
 
3851
        finally:
 
3852
            shelver.finalize()
 
3853
 
3735
3854
    def sanity_check_merger(self, merger):
3736
3855
        if (merger.show_base and
3737
3856
            not merger.merge_type is _mod_merge.Merge3Merger):
3772
3891
            base_branch, base_path = Branch.open_containing(base_loc,
3773
3892
                possible_transports)
3774
3893
        # Find the revision ids
3775
 
        if revision is None or len(revision) < 1 or revision[-1] is None:
 
3894
        other_revision_id = None
 
3895
        base_revision_id = None
 
3896
        if revision is not None:
 
3897
            if len(revision) >= 1:
 
3898
                other_revision_id = revision[-1].as_revision_id(other_branch)
 
3899
            if len(revision) == 2:
 
3900
                base_revision_id = revision[0].as_revision_id(base_branch)
 
3901
        if other_revision_id is None:
3776
3902
            other_revision_id = _mod_revision.ensure_null(
3777
3903
                other_branch.last_revision())
3778
 
        else:
3779
 
            other_revision_id = revision[-1].as_revision_id(other_branch)
3780
 
        if (revision is not None and len(revision) == 2
3781
 
            and revision[0] is not None):
3782
 
            base_revision_id = revision[0].as_revision_id(base_branch)
3783
 
        else:
3784
 
            base_revision_id = None
3785
3904
        # Remember where we merge from
3786
3905
        if ((remember or tree.branch.get_submit_branch() is None) and
3787
3906
             user_location is not None):
3980
4099
    name.  If you name a directory, all the contents of that directory will be
3981
4100
    reverted.
3982
4101
 
3983
 
    Any files that have been newly added since that revision will be deleted,
3984
 
    with a backup kept if appropriate.  Directories containing unknown files
3985
 
    will not be deleted.
 
4102
    If you have newly added files since the target revision, they will be
 
4103
    removed.  If the files to be removed have been changed, backups will be
 
4104
    created as above.  Directories containing unknown files will not be
 
4105
    deleted.
3986
4106
 
3987
4107
    The working tree contains a list of pending merged revisions, which will
3988
4108
    be included as parents in the next commit.  Normally, revert clears that
3991
4111
    revert ." in the tree root to revert all files but keep the merge record,
3992
4112
    and "bzr revert --forget-merges" to clear the pending merge list without
3993
4113
    reverting any files.
 
4114
 
 
4115
    Using "bzr revert --forget-merges", it is possible to apply the changes
 
4116
    from an arbitrary merge as a single revision.  To do this, perform the
 
4117
    merge as desired.  Then doing revert with the "--forget-merges" option will
 
4118
    keep the content of the tree as it was, but it will clear the list of
 
4119
    pending merges.  The next commit will then contain all of the changes that
 
4120
    would have been in the merge, but without any mention of the other parent
 
4121
    revisions.  Because this technique forgets where these changes originated,
 
4122
    it may cause additional conflicts on later merges involving the source and
 
4123
    target branches.
3994
4124
    """
3995
4125
 
3996
4126
    _see_also = ['cat', 'export']
4077
4207
    To filter on a range of revisions, you can use the command -r begin..end
4078
4208
    -r revision requests a specific revision, -r ..end or -r begin.. are
4079
4209
    also valid.
 
4210
            
 
4211
    :Exit values:
 
4212
        1 - some missing revisions
 
4213
        0 - no missing revisions
4080
4214
 
4081
4215
    :Examples:
4082
4216
 
4466
4600
    before they will be applied to the local branch.
4467
4601
 
4468
4602
    Bound branches use the nickname of its master branch unless it is set
4469
 
    locally, in which case binding will update the the local nickname to be
 
4603
    locally, in which case binding will update the local nickname to be
4470
4604
    that of the master.
4471
4605
    """
4472
4606
 
4672
4806
    takes_options = [
4673
4807
        Option('inet',
4674
4808
               help='Serve on stdin/out for use from inetd or sshd.'),
4675
 
        RegistryOption('protocol', 
4676
 
               help="Protocol to serve.", 
 
4809
        RegistryOption('protocol',
 
4810
               help="Protocol to serve.",
4677
4811
               lazy_registry=('bzrlib.transport', 'transport_server_registry'),
4678
4812
               value_switches=True),
4679
4813
        Option('port',
4688
4822
        Option('allow-writes',
4689
4823
               help='By default the server is a readonly server.  Supplying '
4690
4824
                    '--allow-writes enables write access to the contents of '
4691
 
                    'the served directory and below.'
 
4825
                    'the served directory and below.  Note that ``bzr serve`` '
 
4826
                    'does not perform authentication, so unless some form of '
 
4827
                    'external authentication is arranged supplying this '
 
4828
                    'option leads to global uncontrolled write access to your '
 
4829
                    'file system.'
4692
4830
                ),
4693
4831
        ]
4694
4832
 
4929
5067
 
4930
5068
    To use a specific mail program, set the mail_client configuration option.
4931
5069
    (For Thunderbird 1.5, this works around some bugs.)  Supported values for
4932
 
    specific clients are "claws", "evolution", "kmail", "mutt", and
4933
 
    "thunderbird"; generic options are "default", "editor", "emacsclient",
4934
 
    "mapi", and "xdg-email".  Plugins may also add supported clients.
 
5070
    specific clients are "claws", "evolution", "kmail", "mail.app" (MacOS X's
 
5071
    Mail.app), "mutt", and "thunderbird"; generic options are "default",
 
5072
    "editor", "emacsclient", "mapi", and "xdg-email".  Plugins may also add
 
5073
    supported clients.
4935
5074
 
4936
5075
    If mail is being sent, a to address is required.  This can be supplied
4937
5076
    either on the commandline, by setting the submit_to configuration
5243
5382
            ),
5244
5383
        Option('bind-to', help='Branch to bind checkout to.', type=str),
5245
5384
        Option('force',
5246
 
               help='Perform reconfiguration even if local changes'
5247
 
               ' will be lost.')
 
5385
            help='Perform reconfiguration even if local changes'
 
5386
            ' will be lost.'),
 
5387
        Option('stacked-on',
 
5388
            help='Reconfigure a branch to be stacked on another branch.',
 
5389
            type=unicode,
 
5390
            ),
 
5391
        Option('unstacked',
 
5392
            help='Reconfigure a branch to be unstacked.  This '
 
5393
                'may require copying substantial data into it.',
 
5394
            ),
5248
5395
        ]
5249
5396
 
5250
 
    def run(self, location=None, target_type=None, bind_to=None, force=False):
 
5397
    def run(self, location=None, target_type=None, bind_to=None, force=False,
 
5398
            stacked_on=None,
 
5399
            unstacked=None):
5251
5400
        directory = bzrdir.BzrDir.open(location)
 
5401
        if stacked_on and unstacked:
 
5402
            raise BzrCommandError("Can't use both --stacked-on and --unstacked")
 
5403
        elif stacked_on is not None:
 
5404
            reconfigure.ReconfigureStackedOn().apply(directory, stacked_on)
 
5405
        elif unstacked:
 
5406
            reconfigure.ReconfigureUnstacked().apply(directory)
 
5407
        # At the moment you can use --stacked-on and a different
 
5408
        # reconfiguration shape at the same time; there seems no good reason
 
5409
        # to ban it.
5252
5410
        if target_type is None:
5253
 
            raise errors.BzrCommandError('No target configuration specified')
 
5411
            if stacked_on or unstacked:
 
5412
                return
 
5413
            else:
 
5414
                raise errors.BzrCommandError('No target configuration '
 
5415
                    'specified')
5254
5416
        elif target_type == 'branch':
5255
5417
            reconfiguration = reconfigure.Reconfigure.to_branch(directory)
5256
5418
        elif target_type == 'tree':
5293
5455
    /path/to/newbranch.
5294
5456
 
5295
5457
    Bound branches use the nickname of its master branch unless it is set
5296
 
    locally, in which case switching will update the the local nickname to be
 
5458
    locally, in which case switching will update the local nickname to be
5297
5459
    that of the master.
5298
5460
    """
5299
5461
 
5300
5462
    takes_args = ['to_location']
5301
5463
    takes_options = [Option('force',
5302
 
                        help='Switch even if local commits will be lost.')
 
5464
                        help='Switch even if local commits will be lost.'),
 
5465
                     Option('create-branch', short_name='b',
 
5466
                        help='Create the target branch from this one before'
 
5467
                             ' switching to it.'),
5303
5468
                     ]
5304
5469
 
5305
 
    def run(self, to_location, force=False):
 
5470
    def run(self, to_location, force=False, create_branch=False):
5306
5471
        from bzrlib import switch
5307
5472
        tree_location = '.'
5308
5473
        control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5310
5475
            branch = control_dir.open_branch()
5311
5476
            had_explicit_nick = branch.get_config().has_explicit_nickname()
5312
5477
        except errors.NotBranchError:
 
5478
            branch = None
5313
5479
            had_explicit_nick = False
5314
 
        try:
5315
 
            to_branch = Branch.open(to_location)
5316
 
        except errors.NotBranchError:
5317
 
            this_url = self._get_branch_location(control_dir)
5318
 
            to_branch = Branch.open(
5319
 
                urlutils.join(this_url, '..', to_location))
 
5480
        if create_branch:
 
5481
            if branch is None:
 
5482
                raise errors.BzrCommandError('cannot create branch without'
 
5483
                                             ' source branch')
 
5484
            if '/' not in to_location and '\\' not in to_location:
 
5485
                # This path is meant to be relative to the existing branch
 
5486
                this_url = self._get_branch_location(control_dir)
 
5487
                to_location = urlutils.join(this_url, '..', to_location)
 
5488
            to_branch = branch.bzrdir.sprout(to_location,
 
5489
                                 possible_transports=[branch.bzrdir.root_transport],
 
5490
                                 source_branch=branch).open_branch()
 
5491
            # try:
 
5492
            #     from_branch = control_dir.open_branch()
 
5493
            # except errors.NotBranchError:
 
5494
            #     raise BzrCommandError('Cannot create a branch from this'
 
5495
            #         ' location when we cannot open this branch')
 
5496
            # from_branch.bzrdir.sprout(
 
5497
            pass
 
5498
        else:
 
5499
            try:
 
5500
                to_branch = Branch.open(to_location)
 
5501
            except errors.NotBranchError:
 
5502
                this_url = self._get_branch_location(control_dir)
 
5503
                to_branch = Branch.open(
 
5504
                    urlutils.join(this_url, '..', to_location))
5320
5505
        switch.switch(control_dir, to_branch, force)
5321
5506
        if had_explicit_nick:
5322
5507
            branch = control_dir.open_branch() #get the new branch!
5565
5750
        if writer is None:
5566
5751
            writer = bzrlib.option.diff_writer_registry.get()
5567
5752
        try:
5568
 
            Shelver.from_args(writer(sys.stdout), revision, all, file_list,
5569
 
                              message, destroy=destroy).run()
 
5753
            shelver = Shelver.from_args(writer(sys.stdout), revision, all,
 
5754
                file_list, message, destroy=destroy)
 
5755
            try:
 
5756
                shelver.run()
 
5757
            finally:
 
5758
                shelver.finalize()
5570
5759
        except errors.UserAbort:
5571
5760
            return 0
5572
5761
 
5611
5800
 
5612
5801
    def run(self, shelf_id=None, action='apply'):
5613
5802
        from bzrlib.shelf_ui import Unshelver
5614
 
        Unshelver.from_args(shelf_id, action).run()
 
5803
        unshelver = Unshelver.from_args(shelf_id, action)
 
5804
        try:
 
5805
            unshelver.run()
 
5806
        finally:
 
5807
            unshelver.tree.unlock()
5615
5808
 
5616
5809
 
5617
5810
class cmd_clean_tree(Command):