~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

  • Committer: Martin Pool
  • Date: 2010-07-21 09:58:42 UTC
  • mfrom: (4797.58.7 2.1)
  • mto: (5050.3.13 2.2)
  • mto: This revision was merged to the branch mainline in revision 5365.
  • Revision ID: mbp@canonical.com-20100721095842-hz0obu8gl0x05nty
merge up 2.1 to 2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
 
21
21
from bzrlib.lazy_import import lazy_import
22
22
lazy_import(globals(), """
 
23
import codecs
23
24
import cStringIO
24
25
import sys
25
26
import time
32
33
    bzrdir,
33
34
    directory_service,
34
35
    delta,
35
 
    config as _mod_config,
 
36
    config,
36
37
    errors,
37
38
    globbing,
38
39
    hooks,
74
75
from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
75
76
 
76
77
 
77
 
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
78
78
def tree_files(file_list, default_branch=u'.', canonicalize=True,
79
79
    apply_view=True):
80
 
    return internal_tree_files(file_list, default_branch, canonicalize,
81
 
        apply_view)
 
80
    try:
 
81
        return internal_tree_files(file_list, default_branch, canonicalize,
 
82
            apply_view)
 
83
    except errors.FileInWrongBranch, e:
 
84
        raise errors.BzrCommandError("%s is not in the same branch as %s" %
 
85
                                     (e.path, file_list[0]))
82
86
 
83
87
 
84
88
def tree_files_for_add(file_list):
148
152
 
149
153
# XXX: Bad function name; should possibly also be a class method of
150
154
# WorkingTree rather than a function.
151
 
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
152
155
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True,
153
156
    apply_view=True):
154
157
    """Convert command-line paths to a WorkingTree and relative paths.
155
158
 
156
 
    Deprecated: use WorkingTree.open_containing_paths instead.
157
 
 
158
159
    This is typically used for command-line processors that take one or
159
160
    more filenames, and infer the workingtree that contains them.
160
161
 
170
171
 
171
172
    :return: workingtree, [relative_paths]
172
173
    """
173
 
    return WorkingTree.open_containing_paths(
174
 
        file_list, default_directory='.',
175
 
        canonicalize=True,
176
 
        apply_view=True)
 
174
    if file_list is None or len(file_list) == 0:
 
175
        tree = WorkingTree.open_containing(default_branch)[0]
 
176
        if tree.supports_views() and apply_view:
 
177
            view_files = tree.views.lookup_view()
 
178
            if view_files:
 
179
                file_list = view_files
 
180
                view_str = views.view_display_str(view_files)
 
181
                note("Ignoring files outside view. View is %s" % view_str)
 
182
        return tree, file_list
 
183
    tree = WorkingTree.open_containing(file_list[0])[0]
 
184
    return tree, safe_relpath_files(tree, file_list, canonicalize,
 
185
        apply_view=apply_view)
 
186
 
 
187
 
 
188
def safe_relpath_files(tree, file_list, canonicalize=True, apply_view=True):
 
189
    """Convert file_list into a list of relpaths in tree.
 
190
 
 
191
    :param tree: A tree to operate on.
 
192
    :param file_list: A list of user provided paths or None.
 
193
    :param apply_view: if True and a view is set, apply it or check that
 
194
        specified files are within it
 
195
    :return: A list of relative paths.
 
196
    :raises errors.PathNotChild: When a provided path is in a different tree
 
197
        than tree.
 
198
    """
 
199
    if file_list is None:
 
200
        return None
 
201
    if tree.supports_views() and apply_view:
 
202
        view_files = tree.views.lookup_view()
 
203
    else:
 
204
        view_files = []
 
205
    new_list = []
 
206
    # tree.relpath exists as a "thunk" to osutils, but canonical_relpath
 
207
    # doesn't - fix that up here before we enter the loop.
 
208
    if canonicalize:
 
209
        fixer = lambda p: osutils.canonical_relpath(tree.basedir, p)
 
210
    else:
 
211
        fixer = tree.relpath
 
212
    for filename in file_list:
 
213
        try:
 
214
            relpath = fixer(osutils.dereference_path(filename))
 
215
            if  view_files and not osutils.is_inside_any(view_files, relpath):
 
216
                raise errors.FileOutsideView(filename, view_files)
 
217
            new_list.append(relpath)
 
218
        except errors.PathNotChild:
 
219
            raise errors.FileInWrongBranch(tree.branch, filename)
 
220
    return new_list
177
221
 
178
222
 
179
223
def _get_view_info_for_change_reporter(tree):
279
323
            raise errors.BzrCommandError('bzr status --revision takes exactly'
280
324
                                         ' one or two revision specifiers')
281
325
 
282
 
        tree, relfile_list = WorkingTree.open_containing_paths(file_list)
 
326
        tree, relfile_list = tree_files(file_list)
283
327
        # Avoid asking for specific files when that is not needed.
284
328
        if relfile_list == ['']:
285
329
            relfile_list = None
717
761
            raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
718
762
 
719
763
        revision = _get_one_revision('inventory', revision)
720
 
        work_tree, file_list = WorkingTree.open_containing_paths(file_list)
 
764
        work_tree, file_list = tree_files(file_list)
721
765
        self.add_cleanup(work_tree.lock_read().unlock)
722
766
        if revision is not None:
723
767
            tree = revision.as_tree(work_tree.branch)
788
832
            names_list = []
789
833
        if len(names_list) < 2:
790
834
            raise errors.BzrCommandError("missing file argument")
791
 
        tree, rel_names = WorkingTree.open_containing_paths(names_list, canonicalize=False)
 
835
        tree, rel_names = tree_files(names_list, canonicalize=False)
792
836
        self.add_cleanup(tree.lock_tree_write().unlock)
793
837
        self._run(tree, names_list, rel_names, after)
794
838
 
799
843
        if after:
800
844
            raise errors.BzrCommandError('--after cannot be specified with'
801
845
                                         ' --auto.')
802
 
        work_tree, file_list = WorkingTree.open_containing_paths(
803
 
            names_list, default_directory='.')
 
846
        work_tree, file_list = tree_files(names_list, default_branch='.')
804
847
        self.add_cleanup(work_tree.lock_tree_write().unlock)
805
848
        rename_map.RenameMap.guess_renames(work_tree, dry_run)
806
849
 
1134
1177
 
1135
1178
    _see_also = ['checkout']
1136
1179
    takes_args = ['from_location', 'to_location?']
1137
 
    takes_options = ['revision',
1138
 
        Option('hardlink', help='Hard-link working tree files where possible.'),
1139
 
        Option('files-from', type=str,
1140
 
               help="Get file contents from this tree."),
 
1180
    takes_options = ['revision', Option('hardlink',
 
1181
        help='Hard-link working tree files where possible.'),
1141
1182
        Option('no-tree',
1142
1183
            help="Create a branch without a working-tree."),
1143
1184
        Option('switch',
1161
1202
 
1162
1203
    def run(self, from_location, to_location=None, revision=None,
1163
1204
            hardlink=False, stacked=False, standalone=False, no_tree=False,
1164
 
            use_existing_dir=False, switch=False, bind=False,
1165
 
            files_from=None):
 
1205
            use_existing_dir=False, switch=False, bind=False):
1166
1206
        from bzrlib import switch as _mod_switch
1167
1207
        from bzrlib.tag import _merge_tags_if_possible
1168
1208
        accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1169
1209
            from_location)
1170
 
        if not (hardlink or files_from):
1171
 
            # accelerator_tree is usually slower because you have to read N
1172
 
            # files (no readahead, lots of seeks, etc), but allow the user to
1173
 
            # explicitly request it
1174
 
            accelerator_tree = None
1175
 
        if files_from is not None and files_from != from_location:
1176
 
            accelerator_tree = WorkingTree.open(files_from)
1177
1210
        revision = _get_one_revision('branch', revision)
1178
1211
        self.add_cleanup(br_from.lock_read().unlock)
1179
1212
        if revision is not None:
1286
1319
            to_location = branch_location
1287
1320
        accelerator_tree, source = bzrdir.BzrDir.open_tree_or_branch(
1288
1321
            branch_location)
1289
 
        if not (hardlink or files_from):
1290
 
            # accelerator_tree is usually slower because you have to read N
1291
 
            # files (no readahead, lots of seeks, etc), but allow the user to
1292
 
            # explicitly request it
1293
 
            accelerator_tree = None
1294
1322
        revision = _get_one_revision('checkout', revision)
1295
 
        if files_from is not None and files_from != branch_location:
 
1323
        if files_from is not None:
1296
1324
            accelerator_tree = WorkingTree.open(files_from)
1297
1325
        if revision is not None:
1298
1326
            revision_id = revision.as_revision_id(source)
1477
1505
class cmd_remove(Command):
1478
1506
    __doc__ = """Remove files or directories.
1479
1507
 
1480
 
    This makes Bazaar stop tracking changes to the specified files. Bazaar will
1481
 
    delete them if they can easily be recovered using revert otherwise they
1482
 
    will be backed up (adding an extention of the form .~#~). If no options or
1483
 
    parameters are given Bazaar will scan for files that are being tracked by
1484
 
    Bazaar but missing in your tree and stop tracking them for you.
 
1508
    This makes bzr stop tracking changes to the specified files. bzr will delete
 
1509
    them if they can easily be recovered using revert. If no options or
 
1510
    parameters are given bzr will scan for files that are being tracked by bzr
 
1511
    but missing in your tree and stop tracking them for you.
1485
1512
    """
1486
1513
    takes_args = ['file*']
1487
1514
    takes_options = ['verbose',
1489
1516
        RegistryOption.from_kwargs('file-deletion-strategy',
1490
1517
            'The file deletion mode to be used.',
1491
1518
            title='Deletion Strategy', value_switches=True, enum_switch=False,
1492
 
            safe='Backup changed files (default).',
 
1519
            safe='Only delete files if they can be'
 
1520
                 ' safely recovered (default).',
1493
1521
            keep='Delete from bzr but leave the working copy.',
1494
1522
            force='Delete all the specified files, even if they can not be '
1495
1523
                'recovered and even if they are non-empty directories.')]
1498
1526
 
1499
1527
    def run(self, file_list, verbose=False, new=False,
1500
1528
        file_deletion_strategy='safe'):
1501
 
        tree, file_list = WorkingTree.open_containing_paths(file_list)
 
1529
        tree, file_list = tree_files(file_list)
1502
1530
 
1503
1531
        if file_list is not None:
1504
1532
            file_list = [f for f in file_list]
1592
1620
 
1593
1621
    _see_also = ['check']
1594
1622
    takes_args = ['branch?']
1595
 
    takes_options = [
1596
 
        Option('canonicalize-chks',
1597
 
               help='Make sure CHKs are in canonical form (repairs '
1598
 
                    'bug 522637).',
1599
 
               hidden=True),
1600
 
        ]
1601
1623
 
1602
 
    def run(self, branch=".", canonicalize_chks=False):
 
1624
    def run(self, branch="."):
1603
1625
        from bzrlib.reconcile import reconcile
1604
1626
        dir = bzrdir.BzrDir.open(branch)
1605
 
        reconcile(dir, canonicalize_chks=canonicalize_chks)
 
1627
        reconcile(dir)
1606
1628
 
1607
1629
 
1608
1630
class cmd_revision_history(Command):
1884
1906
        Same as 'bzr diff' but prefix paths with old/ and new/::
1885
1907
 
1886
1908
            bzr diff --prefix old/:new/
1887
 
            
1888
 
        Show the differences using a custom diff program with options::
1889
 
        
1890
 
            bzr diff --using /usr/bin/diff --diff-options -wu
1891
1909
    """
1892
1910
    _see_also = ['status']
1893
1911
    takes_args = ['file*']
2694
2712
                "NAME_PATTERN or --default-rules.")
2695
2713
        name_pattern_list = [globbing.normalize_pattern(p)
2696
2714
                             for p in name_pattern_list]
2697
 
        bad_patterns = ''
2698
 
        for p in name_pattern_list:
2699
 
            if not globbing.Globster.is_pattern_valid(p):
2700
 
                bad_patterns += ('\n  %s' % p)
2701
 
        if bad_patterns:
2702
 
            msg = ('Invalid ignore pattern(s) found. %s' % bad_patterns)
2703
 
            ui.ui_factory.show_error(msg)
2704
 
            raise errors.InvalidPattern('')
2705
2715
        for name_pattern in name_pattern_list:
2706
2716
            if (name_pattern[0] == '/' or
2707
2717
                (len(name_pattern) > 1 and name_pattern[1] == ':')):
3099
3109
 
3100
3110
        properties = {}
3101
3111
 
3102
 
        tree, selected_list = WorkingTree.open_containing_paths(selected_list)
 
3112
        tree, selected_list = tree_files(selected_list)
3103
3113
        if selected_list == ['']:
3104
3114
            # workaround - commit of root of tree should be exactly the same
3105
3115
            # as just default commit in that tree, and succeed even though
3140
3150
        def get_message(commit_obj):
3141
3151
            """Callback to get commit message"""
3142
3152
            if file:
3143
 
                f = open(file)
 
3153
                f = codecs.open(file, 'rt', osutils.get_user_encoding())
3144
3154
                try:
3145
 
                    my_message = f.read().decode(osutils.get_user_encoding())
 
3155
                    my_message = f.read()
3146
3156
                finally:
3147
3157
                    f.close()
3148
3158
            elif message is not None:
3179
3189
                        reporter=None, verbose=verbose, revprops=properties,
3180
3190
                        authors=author, timestamp=commit_stamp,
3181
3191
                        timezone=offset,
3182
 
                        exclude=tree.safe_relpath_files(exclude))
 
3192
                        exclude=safe_relpath_files(tree, exclude))
3183
3193
        except PointlessCommit:
3184
3194
            raise errors.BzrCommandError("No changes to commit."
3185
3195
                              " Use --unchanged to commit anyhow.")
3322
3332
                try:
3323
3333
                    c = Branch.open_containing(u'.')[0].get_config()
3324
3334
                except errors.NotBranchError:
3325
 
                    c = _mod_config.GlobalConfig()
 
3335
                    c = config.GlobalConfig()
3326
3336
            else:
3327
3337
                c = Branch.open(directory).get_config()
3328
3338
            if email:
3333
3343
 
3334
3344
        # display a warning if an email address isn't included in the given name.
3335
3345
        try:
3336
 
            _mod_config.extract_email_address(name)
 
3346
            config.extract_email_address(name)
3337
3347
        except errors.NoEmailInUsername, e:
3338
3348
            warning('"%s" does not seem to contain an email address.  '
3339
3349
                    'This is allowed, but not recommended.', name)
3345
3355
            else:
3346
3356
                c = Branch.open(directory).get_config()
3347
3357
        else:
3348
 
            c = _mod_config.GlobalConfig()
 
3358
            c = config.GlobalConfig()
3349
3359
        c.set_user_option('email', name)
3350
3360
 
3351
3361
 
3418
3428
                'bzr alias --remove expects an alias to remove.')
3419
3429
        # If alias is not found, print something like:
3420
3430
        # unalias: foo: not found
3421
 
        c = _mod_config.GlobalConfig()
 
3431
        c = config.GlobalConfig()
3422
3432
        c.unset_alias(alias_name)
3423
3433
 
3424
3434
    @display_command
3425
3435
    def print_aliases(self):
3426
3436
        """Print out the defined aliases in a similar format to bash."""
3427
 
        aliases = _mod_config.GlobalConfig().get_aliases()
 
3437
        aliases = config.GlobalConfig().get_aliases()
3428
3438
        for key, value in sorted(aliases.iteritems()):
3429
3439
            self.outf.write('bzr alias %s="%s"\n' % (key, value))
3430
3440
 
3440
3450
 
3441
3451
    def set_alias(self, alias_name, alias_command):
3442
3452
        """Save the alias in the global config."""
3443
 
        c = _mod_config.GlobalConfig()
 
3453
        c = config.GlobalConfig()
3444
3454
        c.set_alias(alias_name, alias_command)
3445
3455
 
3446
3456
 
3570
3580
            randomize=None, exclude=None, strict=False,
3571
3581
            load_list=None, debugflag=None, starting_with=None, subunit=False,
3572
3582
            parallel=None, lsprof_tests=False):
3573
 
        from bzrlib import tests
 
3583
        from bzrlib.tests import selftest
 
3584
 
 
3585
        # Make deprecation warnings visible, unless -Werror is set
 
3586
        symbol_versioning.activate_deprecation_warnings(override=False)
3574
3587
 
3575
3588
        if testspecs_list is not None:
3576
3589
            pattern = '|'.join(testspecs_list)
3617
3630
                          "starting_with": starting_with
3618
3631
                          }
3619
3632
        selftest_kwargs.update(self.additional_selftest_args)
3620
 
 
3621
 
        # Make deprecation warnings visible, unless -Werror is set
3622
 
        cleanup = symbol_versioning.activate_deprecation_warnings(
3623
 
            override=False)
3624
 
        try:
3625
 
            result = tests.selftest(**selftest_kwargs)
3626
 
        finally:
3627
 
            cleanup()
 
3633
        result = selftest(**selftest_kwargs)
3628
3634
        return int(not result)
3629
3635
 
3630
3636
 
4073
4079
        from bzrlib.conflicts import restore
4074
4080
        if merge_type is None:
4075
4081
            merge_type = _mod_merge.Merge3Merger
4076
 
        tree, file_list = WorkingTree.open_containing_paths(file_list)
 
4082
        tree, file_list = tree_files(file_list)
4077
4083
        self.add_cleanup(tree.lock_write().unlock)
4078
4084
        parents = tree.get_parent_ids()
4079
4085
        if len(parents) != 2:
4189
4195
 
4190
4196
    def run(self, revision=None, no_backup=False, file_list=None,
4191
4197
            forget_merges=None):
4192
 
        tree, file_list = WorkingTree.open_containing_paths(file_list)
 
4198
        tree, file_list = tree_files(file_list)
4193
4199
        self.add_cleanup(tree.lock_tree_write().unlock)
4194
4200
        if forget_merges:
4195
4201
            tree.set_parent_ids(tree.get_parent_ids()[:1])
4811
4817
 
4812
4818
 
4813
4819
class cmd_break_lock(Command):
4814
 
    __doc__ = """Break a dead lock.
4815
 
 
4816
 
    This command breaks a lock on a repository, branch, working directory or
4817
 
    config file.
 
4820
    __doc__ = """Break a dead lock on a repository, branch or working directory.
4818
4821
 
4819
4822
    CAUTION: Locks should only be broken when you are sure that the process
4820
4823
    holding the lock has been stopped.
4825
4828
    :Examples:
4826
4829
        bzr break-lock
4827
4830
        bzr break-lock bzr+ssh://example.com/bzr/foo
4828
 
        bzr break-lock --conf ~/.bazaar
4829
4831
    """
4830
 
 
4831
4832
    takes_args = ['location?']
4832
 
    takes_options = [
4833
 
        Option('config',
4834
 
               help='LOCATION is the directory where the config lock is.'),
4835
 
        ]
4836
4833
 
4837
 
    def run(self, location=None, config=False):
 
4834
    def run(self, location=None, show=False):
4838
4835
        if location is None:
4839
4836
            location = u'.'
4840
 
        if config:
4841
 
            conf = _mod_config.LockableConfig(file_name=location)
4842
 
            conf.break_lock()
4843
 
        else:
4844
 
            control, relpath = bzrdir.BzrDir.open_containing(location)
4845
 
            try:
4846
 
                control.break_lock()
4847
 
            except NotImplementedError:
4848
 
                pass
 
4837
        control, relpath = bzrdir.BzrDir.open_containing(location)
 
4838
        try:
 
4839
            control.break_lock()
 
4840
        except NotImplementedError:
 
4841
            pass
4849
4842
 
4850
4843
 
4851
4844
class cmd_wait_until_signalled(Command):
5704
5697
            name=None,
5705
5698
            switch=None,
5706
5699
            ):
5707
 
        tree, file_list = WorkingTree.open_containing_paths(file_list,
5708
 
            apply_view=False)
 
5700
        tree, file_list = tree_files(file_list, apply_view=False)
5709
5701
        current_view, view_dict = tree.views.get_view_info()
5710
5702
        if name is None:
5711
5703
            name = current_view