~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/builtins.py

Merge lockable-config-files into remove-gratuitous-ensure-config-dir-exist-calls resolving conflicts

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
24
23
import cStringIO
25
24
import sys
26
25
import time
33
32
    bzrdir,
34
33
    directory_service,
35
34
    delta,
36
 
    config,
 
35
    config as _mod_config,
37
36
    errors,
38
37
    globbing,
39
38
    hooks,
75
74
from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
76
75
 
77
76
 
 
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
 
    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]))
 
80
    return internal_tree_files(file_list, default_branch, canonicalize,
 
81
        apply_view)
86
82
 
87
83
 
88
84
def tree_files_for_add(file_list):
152
148
 
153
149
# XXX: Bad function name; should possibly also be a class method of
154
150
# WorkingTree rather than a function.
 
151
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
155
152
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True,
156
153
    apply_view=True):
157
154
    """Convert command-line paths to a WorkingTree and relative paths.
158
155
 
 
156
    Deprecated: use WorkingTree.open_containing_paths instead.
 
157
 
159
158
    This is typically used for command-line processors that take one or
160
159
    more filenames, and infer the workingtree that contains them.
161
160
 
171
170
 
172
171
    :return: workingtree, [relative_paths]
173
172
    """
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(osutils.realpath(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
 
173
    return WorkingTree.open_containing_paths(
 
174
        file_list, default_directory='.',
 
175
        canonicalize=True,
 
176
        apply_view=True)
221
177
 
222
178
 
223
179
def _get_view_info_for_change_reporter(tree):
323
279
            raise errors.BzrCommandError('bzr status --revision takes exactly'
324
280
                                         ' one or two revision specifiers')
325
281
 
326
 
        tree, relfile_list = tree_files(file_list)
 
282
        tree, relfile_list = WorkingTree.open_containing_paths(file_list)
327
283
        # Avoid asking for specific files when that is not needed.
328
284
        if relfile_list == ['']:
329
285
            relfile_list = None
761
717
            raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
762
718
 
763
719
        revision = _get_one_revision('inventory', revision)
764
 
        work_tree, file_list = tree_files(file_list)
 
720
        work_tree, file_list = WorkingTree.open_containing_paths(file_list)
765
721
        self.add_cleanup(work_tree.lock_read().unlock)
766
722
        if revision is not None:
767
723
            tree = revision.as_tree(work_tree.branch)
832
788
            names_list = []
833
789
        if len(names_list) < 2:
834
790
            raise errors.BzrCommandError("missing file argument")
835
 
        tree, rel_names = tree_files(names_list, canonicalize=False)
 
791
        tree, rel_names = WorkingTree.open_containing_paths(names_list, canonicalize=False)
836
792
        self.add_cleanup(tree.lock_tree_write().unlock)
837
793
        self._run(tree, names_list, rel_names, after)
838
794
 
843
799
        if after:
844
800
            raise errors.BzrCommandError('--after cannot be specified with'
845
801
                                         ' --auto.')
846
 
        work_tree, file_list = tree_files(names_list, default_branch='.')
 
802
        work_tree, file_list = WorkingTree.open_containing_paths(
 
803
            names_list, default_directory='.')
847
804
        self.add_cleanup(work_tree.lock_tree_write().unlock)
848
805
        rename_map.RenameMap.guess_renames(work_tree, dry_run)
849
806
 
1177
1134
 
1178
1135
    _see_also = ['checkout']
1179
1136
    takes_args = ['from_location', 'to_location?']
1180
 
    takes_options = ['revision', Option('hardlink',
1181
 
        help='Hard-link working tree files where possible.'),
 
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."),
1182
1141
        Option('no-tree',
1183
1142
            help="Create a branch without a working-tree."),
1184
1143
        Option('switch',
1202
1161
 
1203
1162
    def run(self, from_location, to_location=None, revision=None,
1204
1163
            hardlink=False, stacked=False, standalone=False, no_tree=False,
1205
 
            use_existing_dir=False, switch=False, bind=False):
 
1164
            use_existing_dir=False, switch=False, bind=False,
 
1165
            files_from=None):
1206
1166
        from bzrlib import switch as _mod_switch
1207
1167
        from bzrlib.tag import _merge_tags_if_possible
1208
1168
        accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1209
1169
            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)
1210
1177
        revision = _get_one_revision('branch', revision)
1211
1178
        self.add_cleanup(br_from.lock_read().unlock)
1212
1179
        if revision is not None:
1319
1286
            to_location = branch_location
1320
1287
        accelerator_tree, source = bzrdir.BzrDir.open_tree_or_branch(
1321
1288
            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
1322
1294
        revision = _get_one_revision('checkout', revision)
1323
 
        if files_from is not None:
 
1295
        if files_from is not None and files_from != branch_location:
1324
1296
            accelerator_tree = WorkingTree.open(files_from)
1325
1297
        if revision is not None:
1326
1298
            revision_id = revision.as_revision_id(source)
1505
1477
class cmd_remove(Command):
1506
1478
    __doc__ = """Remove files or directories.
1507
1479
 
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.
 
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.
1512
1485
    """
1513
1486
    takes_args = ['file*']
1514
1487
    takes_options = ['verbose',
1516
1489
        RegistryOption.from_kwargs('file-deletion-strategy',
1517
1490
            'The file deletion mode to be used.',
1518
1491
            title='Deletion Strategy', value_switches=True, enum_switch=False,
1519
 
            safe='Only delete files if they can be'
1520
 
                 ' safely recovered (default).',
 
1492
            safe='Backup changed files (default).',
1521
1493
            keep='Delete from bzr but leave the working copy.',
1522
1494
            force='Delete all the specified files, even if they can not be '
1523
1495
                'recovered and even if they are non-empty directories.')]
1526
1498
 
1527
1499
    def run(self, file_list, verbose=False, new=False,
1528
1500
        file_deletion_strategy='safe'):
1529
 
        tree, file_list = tree_files(file_list)
 
1501
        tree, file_list = WorkingTree.open_containing_paths(file_list)
1530
1502
 
1531
1503
        if file_list is not None:
1532
1504
            file_list = [f for f in file_list]
1620
1592
 
1621
1593
    _see_also = ['check']
1622
1594
    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
        ]
1623
1601
 
1624
 
    def run(self, branch="."):
 
1602
    def run(self, branch=".", canonicalize_chks=False):
1625
1603
        from bzrlib.reconcile import reconcile
1626
1604
        dir = bzrdir.BzrDir.open(branch)
1627
 
        reconcile(dir)
 
1605
        reconcile(dir, canonicalize_chks=canonicalize_chks)
1628
1606
 
1629
1607
 
1630
1608
class cmd_revision_history(Command):
1906
1884
        Same as 'bzr diff' but prefix paths with old/ and new/::
1907
1885
 
1908
1886
            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
1909
1891
    """
1910
1892
    _see_also = ['status']
1911
1893
    takes_args = ['file*']
3117
3099
 
3118
3100
        properties = {}
3119
3101
 
3120
 
        tree, selected_list = tree_files(selected_list)
 
3102
        tree, selected_list = WorkingTree.open_containing_paths(selected_list)
3121
3103
        if selected_list == ['']:
3122
3104
            # workaround - commit of root of tree should be exactly the same
3123
3105
            # as just default commit in that tree, and succeed even though
3158
3140
        def get_message(commit_obj):
3159
3141
            """Callback to get commit message"""
3160
3142
            if file:
3161
 
                f = codecs.open(file, 'rt', osutils.get_user_encoding())
 
3143
                f = open(file)
3162
3144
                try:
3163
 
                    my_message = f.read()
 
3145
                    my_message = f.read().decode(osutils.get_user_encoding())
3164
3146
                finally:
3165
3147
                    f.close()
3166
3148
            elif message is not None:
3197
3179
                        reporter=None, verbose=verbose, revprops=properties,
3198
3180
                        authors=author, timestamp=commit_stamp,
3199
3181
                        timezone=offset,
3200
 
                        exclude=safe_relpath_files(tree, exclude))
 
3182
                        exclude=tree.safe_relpath_files(exclude))
3201
3183
        except PointlessCommit:
3202
3184
            raise errors.BzrCommandError("No changes to commit."
3203
3185
                              " Use --unchanged to commit anyhow.")
3340
3322
                try:
3341
3323
                    c = Branch.open_containing(u'.')[0].get_config()
3342
3324
                except errors.NotBranchError:
3343
 
                    c = config.GlobalConfig()
 
3325
                    c = _mod_config.GlobalConfig()
3344
3326
            else:
3345
3327
                c = Branch.open(directory).get_config()
3346
3328
            if email:
3351
3333
 
3352
3334
        # display a warning if an email address isn't included in the given name.
3353
3335
        try:
3354
 
            config.extract_email_address(name)
 
3336
            _mod_config.extract_email_address(name)
3355
3337
        except errors.NoEmailInUsername, e:
3356
3338
            warning('"%s" does not seem to contain an email address.  '
3357
3339
                    'This is allowed, but not recommended.', name)
3363
3345
            else:
3364
3346
                c = Branch.open(directory).get_config()
3365
3347
        else:
3366
 
            c = config.GlobalConfig()
 
3348
            c = _mod_config.GlobalConfig()
3367
3349
        c.set_user_option('email', name)
3368
3350
 
3369
3351
 
3436
3418
                'bzr alias --remove expects an alias to remove.')
3437
3419
        # If alias is not found, print something like:
3438
3420
        # unalias: foo: not found
3439
 
        c = config.GlobalConfig()
 
3421
        c = _mod_config.GlobalConfig()
3440
3422
        c.unset_alias(alias_name)
3441
3423
 
3442
3424
    @display_command
3443
3425
    def print_aliases(self):
3444
3426
        """Print out the defined aliases in a similar format to bash."""
3445
 
        aliases = config.GlobalConfig().get_aliases()
 
3427
        aliases = _mod_config.GlobalConfig().get_aliases()
3446
3428
        for key, value in sorted(aliases.iteritems()):
3447
3429
            self.outf.write('bzr alias %s="%s"\n' % (key, value))
3448
3430
 
3458
3440
 
3459
3441
    def set_alias(self, alias_name, alias_command):
3460
3442
        """Save the alias in the global config."""
3461
 
        c = config.GlobalConfig()
 
3443
        c = _mod_config.GlobalConfig()
3462
3444
        c.set_alias(alias_name, alias_command)
3463
3445
 
3464
3446
 
3537
3519
                                 'throughout the test suite.',
3538
3520
                            type=get_transport_type),
3539
3521
                     Option('benchmark',
3540
 
                            help='Run the benchmarks rather than selftests.'),
 
3522
                            help='Run the benchmarks rather than selftests.',
 
3523
                            hidden=True),
3541
3524
                     Option('lsprof-timed',
3542
3525
                            help='Generate lsprof output for benchmarked'
3543
3526
                                 ' sections of code.'),
3544
3527
                     Option('lsprof-tests',
3545
3528
                            help='Generate lsprof output for each test.'),
3546
 
                     Option('cache-dir', type=str,
3547
 
                            help='Cache intermediate benchmark output in this '
3548
 
                                 'directory.'),
3549
3529
                     Option('first',
3550
3530
                            help='Run all tests, but run specified tests first.',
3551
3531
                            short_name='f',
3585
3565
 
3586
3566
    def run(self, testspecs_list=None, verbose=False, one=False,
3587
3567
            transport=None, benchmark=None,
3588
 
            lsprof_timed=None, cache_dir=None,
 
3568
            lsprof_timed=None,
3589
3569
            first=False, list_only=False,
3590
3570
            randomize=None, exclude=None, strict=False,
3591
3571
            load_list=None, debugflag=None, starting_with=None, subunit=False,
3592
3572
            parallel=None, lsprof_tests=False):
3593
3573
        from bzrlib.tests import selftest
3594
 
        import bzrlib.benchmarks as benchmarks
3595
 
        from bzrlib.benchmarks import tree_creator
3596
3574
 
3597
3575
        # Make deprecation warnings visible, unless -Werror is set
3598
3576
        symbol_versioning.activate_deprecation_warnings(override=False)
3599
3577
 
3600
 
        if cache_dir is not None:
3601
 
            tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
3602
3578
        if testspecs_list is not None:
3603
3579
            pattern = '|'.join(testspecs_list)
3604
3580
        else:
3623
3599
            self.additional_selftest_args.setdefault(
3624
3600
                'suite_decorators', []).append(parallel)
3625
3601
        if benchmark:
3626
 
            test_suite_factory = benchmarks.test_suite
3627
 
            # Unless user explicitly asks for quiet, be verbose in benchmarks
3628
 
            verbose = not is_quiet()
3629
 
            # TODO: should possibly lock the history file...
3630
 
            benchfile = open(".perf_history", "at", buffering=1)
3631
 
            self.add_cleanup(benchfile.close)
3632
 
        else:
3633
 
            test_suite_factory = None
3634
 
            benchfile = None
 
3602
            raise errors.BzrCommandError(
 
3603
                "--benchmark is no longer supported from bzr 2.2; "
 
3604
                "use bzr-usertest instead")
 
3605
        test_suite_factory = None
3635
3606
        selftest_kwargs = {"verbose": verbose,
3636
3607
                          "pattern": pattern,
3637
3608
                          "stop_on_failure": one,
3639
3610
                          "test_suite_factory": test_suite_factory,
3640
3611
                          "lsprof_timed": lsprof_timed,
3641
3612
                          "lsprof_tests": lsprof_tests,
3642
 
                          "bench_history": benchfile,
3643
3613
                          "matching_tests_first": first,
3644
3614
                          "list_only": list_only,
3645
3615
                          "random_seed": randomize,
4099
4069
        from bzrlib.conflicts import restore
4100
4070
        if merge_type is None:
4101
4071
            merge_type = _mod_merge.Merge3Merger
4102
 
        tree, file_list = tree_files(file_list)
 
4072
        tree, file_list = WorkingTree.open_containing_paths(file_list)
4103
4073
        self.add_cleanup(tree.lock_write().unlock)
4104
4074
        parents = tree.get_parent_ids()
4105
4075
        if len(parents) != 2:
4215
4185
 
4216
4186
    def run(self, revision=None, no_backup=False, file_list=None,
4217
4187
            forget_merges=None):
4218
 
        tree, file_list = tree_files(file_list)
 
4188
        tree, file_list = WorkingTree.open_containing_paths(file_list)
4219
4189
        self.add_cleanup(tree.lock_tree_write().unlock)
4220
4190
        if forget_merges:
4221
4191
            tree.set_parent_ids(tree.get_parent_ids()[:1])
4837
4807
 
4838
4808
 
4839
4809
class cmd_break_lock(Command):
4840
 
    __doc__ = """Break a dead lock on a repository, branch or working directory.
 
4810
    __doc__ = """Break a dead lock.
 
4811
 
 
4812
    This command breaks a lock on a repository, branch, working directory or
 
4813
    config file.
4841
4814
 
4842
4815
    CAUTION: Locks should only be broken when you are sure that the process
4843
4816
    holding the lock has been stopped.
4848
4821
    :Examples:
4849
4822
        bzr break-lock
4850
4823
        bzr break-lock bzr+ssh://example.com/bzr/foo
 
4824
        bzr break-lock --conf ~/.bazaar
4851
4825
    """
 
4826
 
4852
4827
    takes_args = ['location?']
 
4828
    takes_options = [
 
4829
        Option('config',
 
4830
               help='LOCATION is the directory where the config lock is.'),
 
4831
        ]
4853
4832
 
4854
 
    def run(self, location=None, show=False):
 
4833
    def run(self, location=None, config=False):
4855
4834
        if location is None:
4856
4835
            location = u'.'
4857
 
        control, relpath = bzrdir.BzrDir.open_containing(location)
4858
 
        try:
4859
 
            control.break_lock()
4860
 
        except NotImplementedError:
4861
 
            pass
 
4836
        if config:
 
4837
            conf = _mod_config.LockableConfig(file_name=location)
 
4838
            conf.break_lock()
 
4839
        else:
 
4840
            control, relpath = bzrdir.BzrDir.open_containing(location)
 
4841
            try:
 
4842
                control.break_lock()
 
4843
            except NotImplementedError:
 
4844
                pass
4862
4845
 
4863
4846
 
4864
4847
class cmd_wait_until_signalled(Command):
5717
5700
            name=None,
5718
5701
            switch=None,
5719
5702
            ):
5720
 
        tree, file_list = tree_files(file_list, apply_view=False)
 
5703
        tree, file_list = WorkingTree.open_containing_paths(file_list,
 
5704
            apply_view=False)
5721
5705
        current_view, view_dict = tree.views.get_view_info()
5722
5706
        if name is None:
5723
5707
            name = current_view