74
75
from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
77
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
78
78
def tree_files(file_list, default_branch=u'.', canonicalize=True,
80
return internal_tree_files(file_list, default_branch, canonicalize,
81
return internal_tree_files(file_list, default_branch, canonicalize,
83
except errors.FileInWrongBranch, e:
84
raise errors.BzrCommandError("%s is not in the same branch as %s" %
85
(e.path, file_list[0]))
84
88
def tree_files_for_add(file_list):
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.
156
Deprecated: use WorkingTree.open_containing_paths instead.
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.
171
172
:return: workingtree, [relative_paths]
173
return WorkingTree.open_containing_paths(
174
file_list, default_directory='.',
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()
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)
188
def safe_relpath_files(tree, file_list, canonicalize=True, apply_view=True):
189
"""Convert file_list into a list of relpaths in tree.
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
199
if file_list is None:
201
if tree.supports_views() and apply_view:
202
view_files = tree.views.lookup_view()
206
# tree.relpath exists as a "thunk" to osutils, but canonical_relpath
207
# doesn't - fix that up here before we enter the loop.
209
fixer = lambda p: osutils.canonical_relpath(tree.basedir, p)
212
for filename in file_list:
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)
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')
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
468
512
if (working.has_changes()):
469
513
raise errors.UncommittedChanges(working)
470
if working.get_shelf_manager().last_shelf() is not None:
471
raise errors.ShelvedChanges(working)
473
515
if working.user_url != working.branch.user_url:
474
516
raise errors.BzrCommandError("You cannot remove the working tree"
717
759
raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
719
761
revision = _get_one_revision('inventory', revision)
720
work_tree, file_list = WorkingTree.open_containing_paths(file_list)
762
work_tree, file_list = tree_files(file_list)
721
763
self.add_cleanup(work_tree.lock_read().unlock)
722
764
if revision is not None:
723
765
tree = revision.as_tree(work_tree.branch)
789
831
if len(names_list) < 2:
790
832
raise errors.BzrCommandError("missing file argument")
791
tree, rel_names = WorkingTree.open_containing_paths(names_list, canonicalize=False)
833
tree, rel_names = tree_files(names_list, canonicalize=False)
792
834
self.add_cleanup(tree.lock_tree_write().unlock)
793
835
self._run(tree, names_list, rel_names, after)
800
842
raise errors.BzrCommandError('--after cannot be specified with'
802
work_tree, file_list = WorkingTree.open_containing_paths(
803
names_list, default_directory='.')
844
work_tree, file_list = tree_files(names_list, default_branch='.')
804
845
self.add_cleanup(work_tree.lock_tree_write().unlock)
805
846
rename_map.RenameMap.guess_renames(work_tree, dry_run)
1135
1176
_see_also = ['checkout']
1136
1177
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."),
1178
takes_options = ['revision', Option('hardlink',
1179
help='Hard-link working tree files where possible.'),
1141
1180
Option('no-tree',
1142
1181
help="Create a branch without a working-tree."),
1143
1182
Option('switch',
1162
1201
def run(self, from_location, to_location=None, revision=None,
1163
1202
hardlink=False, stacked=False, standalone=False, no_tree=False,
1164
use_existing_dir=False, switch=False, bind=False,
1203
use_existing_dir=False, switch=False, bind=False):
1166
1204
from bzrlib import switch as _mod_switch
1167
1205
from bzrlib.tag import _merge_tags_if_possible
1168
1206
accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
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
1208
revision = _get_one_revision('branch', revision)
1178
1209
self.add_cleanup(br_from.lock_read().unlock)
1179
1210
if revision is not None:
1286
1317
to_location = branch_location
1287
1318
accelerator_tree, source = bzrdir.BzrDir.open_tree_or_branch(
1288
1319
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
1320
revision = _get_one_revision('checkout', revision)
1295
if files_from is not None and files_from != branch_location:
1321
if files_from is not None:
1296
1322
accelerator_tree = WorkingTree.open(files_from)
1297
1323
if revision is not None:
1298
1324
revision_id = revision.as_revision_id(source)
1477
1503
class cmd_remove(Command):
1478
1504
__doc__ = """Remove files or directories.
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.
1506
This makes bzr stop tracking changes to the specified files. bzr will delete
1507
them if they can easily be recovered using revert. If no options or
1508
parameters are given bzr will scan for files that are being tracked by bzr
1509
but missing in your tree and stop tracking them for you.
1486
1511
takes_args = ['file*']
1487
1512
takes_options = ['verbose',
1489
1514
RegistryOption.from_kwargs('file-deletion-strategy',
1490
1515
'The file deletion mode to be used.',
1491
1516
title='Deletion Strategy', value_switches=True, enum_switch=False,
1492
safe='Backup changed files (default).',
1517
safe='Only delete files if they can be'
1518
' safely recovered (default).',
1493
1519
keep='Delete from bzr but leave the working copy.',
1494
1520
force='Delete all the specified files, even if they can not be '
1495
1521
'recovered and even if they are non-empty directories.')]
1499
1525
def run(self, file_list, verbose=False, new=False,
1500
1526
file_deletion_strategy='safe'):
1501
tree, file_list = WorkingTree.open_containing_paths(file_list)
1527
tree, file_list = tree_files(file_list)
1503
1529
if file_list is not None:
1504
1530
file_list = [f for f in file_list]
1593
1619
_see_also = ['check']
1594
1620
takes_args = ['branch?']
1596
Option('canonicalize-chks',
1597
help='Make sure CHKs are in canonical form (repairs '
1602
def run(self, branch=".", canonicalize_chks=False):
1622
def run(self, branch="."):
1603
1623
from bzrlib.reconcile import reconcile
1604
1624
dir = bzrdir.BzrDir.open(branch)
1605
reconcile(dir, canonicalize_chks=canonicalize_chks)
1608
1628
class cmd_revision_history(Command):
1952
1968
old_branch, new_branch,
1953
1969
specific_files, extra_trees) = get_trees_and_branches_to_diff_locked(
1954
1970
file_list, revision, old, new, self.add_cleanup, apply_view=True)
1955
# GNU diff on Windows uses ANSI encoding for filenames
1956
path_encoding = osutils.get_diff_header_encoding()
1957
1971
return show_diff_trees(old_tree, new_tree, sys.stdout,
1958
1972
specific_files=specific_files,
1959
1973
external_diff_options=diff_options,
1960
1974
old_label=old_label, new_label=new_label,
1961
extra_trees=extra_trees,
1962
path_encoding=path_encoding,
1975
extra_trees=extra_trees, using=using,
1964
1976
format_cls=format)
2694
2706
"NAME_PATTERN or --default-rules.")
2695
2707
name_pattern_list = [globbing.normalize_pattern(p)
2696
2708
for p in name_pattern_list]
2698
for p in name_pattern_list:
2699
if not globbing.Globster.is_pattern_valid(p):
2700
bad_patterns += ('\n %s' % p)
2702
msg = ('Invalid ignore pattern(s) found. %s' % bad_patterns)
2703
ui.ui_factory.show_error(msg)
2704
raise errors.InvalidPattern('')
2705
2709
for name_pattern in name_pattern_list:
2706
2710
if (name_pattern[0] == '/' or
2707
2711
(len(name_pattern) > 1 and name_pattern[1] == ':')):
2711
2715
ignores.tree_ignores_add_patterns(tree, name_pattern_list)
2712
2716
ignored = globbing.Globster(name_pattern_list)
2714
self.add_cleanup(tree.lock_read().unlock)
2715
2719
for entry in tree.list_files():
2717
2721
if id is not None:
2718
2722
filename = entry[0]
2719
2723
if ignored.match(filename):
2720
2724
matches.append(filename)
2721
2726
if len(matches) > 0:
2722
2727
self.outf.write("Warning: the following files are version controlled and"
2723
2728
" match your ignore pattern:\n%s"
3100
3105
properties = {}
3102
tree, selected_list = WorkingTree.open_containing_paths(selected_list)
3107
tree, selected_list = tree_files(selected_list)
3103
3108
if selected_list == ['']:
3104
3109
# workaround - commit of root of tree should be exactly the same
3105
3110
# as just default commit in that tree, and succeed even though
3140
3145
def get_message(commit_obj):
3141
3146
"""Callback to get commit message"""
3145
my_message = f.read().decode(osutils.get_user_encoding())
3148
my_message = codecs.open(
3149
file, 'rt', osutils.get_user_encoding()).read()
3148
3150
elif message is not None:
3149
3151
my_message = message
3179
3181
reporter=None, verbose=verbose, revprops=properties,
3180
3182
authors=author, timestamp=commit_stamp,
3181
3183
timezone=offset,
3182
exclude=tree.safe_relpath_files(exclude))
3184
exclude=safe_relpath_files(tree, exclude))
3183
3185
except PointlessCommit:
3184
3186
raise errors.BzrCommandError("No changes to commit."
3185
3187
" Use --unchanged to commit anyhow.")
3305
3307
bzr whoami "Frank Chu <fchu@example.com>"
3307
takes_options = [ 'directory',
3309
takes_options = [ Option('email',
3309
3310
help='Display email address only.'),
3310
3311
Option('branch',
3311
3312
help='Set identity for the current branch instead of '
3315
3316
encoding_type = 'replace'
3317
3318
@display_command
3318
def run(self, email=False, branch=False, name=None, directory=None):
3319
def run(self, email=False, branch=False, name=None):
3319
3320
if name is None:
3320
if directory is None:
3321
# use branch if we're inside one; otherwise global config
3323
c = Branch.open_containing(u'.')[0].get_config()
3324
except errors.NotBranchError:
3325
c = _mod_config.GlobalConfig()
3327
c = Branch.open(directory).get_config()
3321
# use branch if we're inside one; otherwise global config
3323
c = Branch.open_containing('.')[0].get_config()
3324
except errors.NotBranchError:
3325
c = config.GlobalConfig()
3329
3327
self.outf.write(c.user_email() + '\n')
3334
3332
# display a warning if an email address isn't included in the given name.
3336
_mod_config.extract_email_address(name)
3334
config.extract_email_address(name)
3337
3335
except errors.NoEmailInUsername, e:
3338
3336
warning('"%s" does not seem to contain an email address. '
3339
3337
'This is allowed, but not recommended.', name)
3341
3339
# use global config unless --branch given
3343
if directory is None:
3344
c = Branch.open_containing(u'.')[0].get_config()
3346
c = Branch.open(directory).get_config()
3341
c = Branch.open_containing('.')[0].get_config()
3348
c = _mod_config.GlobalConfig()
3343
c = config.GlobalConfig()
3349
3344
c.set_user_option('email', name)
3418
3413
'bzr alias --remove expects an alias to remove.')
3419
3414
# If alias is not found, print something like:
3420
3415
# unalias: foo: not found
3421
c = _mod_config.GlobalConfig()
3416
c = config.GlobalConfig()
3422
3417
c.unset_alias(alias_name)
3424
3419
@display_command
3425
3420
def print_aliases(self):
3426
3421
"""Print out the defined aliases in a similar format to bash."""
3427
aliases = _mod_config.GlobalConfig().get_aliases()
3422
aliases = config.GlobalConfig().get_aliases()
3428
3423
for key, value in sorted(aliases.iteritems()):
3429
3424
self.outf.write('bzr alias %s="%s"\n' % (key, value))
3441
3436
def set_alias(self, alias_name, alias_command):
3442
3437
"""Save the alias in the global config."""
3443
c = _mod_config.GlobalConfig()
3438
c = config.GlobalConfig()
3444
3439
c.set_alias(alias_name, alias_command)
3519
3514
'throughout the test suite.',
3520
3515
type=get_transport_type),
3521
3516
Option('benchmark',
3522
help='Run the benchmarks rather than selftests.',
3517
help='Run the benchmarks rather than selftests.'),
3524
3518
Option('lsprof-timed',
3525
3519
help='Generate lsprof output for benchmarked'
3526
3520
' sections of code.'),
3527
3521
Option('lsprof-tests',
3528
3522
help='Generate lsprof output for each test.'),
3523
Option('cache-dir', type=str,
3524
help='Cache intermediate benchmark output in this '
3529
3526
Option('first',
3530
3527
help='Run all tests, but run specified tests first.',
3531
3528
short_name='f',
3566
3563
def run(self, testspecs_list=None, verbose=False, one=False,
3567
3564
transport=None, benchmark=None,
3565
lsprof_timed=None, cache_dir=None,
3569
3566
first=False, list_only=False,
3570
3567
randomize=None, exclude=None, strict=False,
3571
3568
load_list=None, debugflag=None, starting_with=None, subunit=False,
3572
3569
parallel=None, lsprof_tests=False):
3573
from bzrlib import tests
3570
from bzrlib.tests import selftest
3571
import bzrlib.benchmarks as benchmarks
3572
from bzrlib.benchmarks import tree_creator
3574
# Make deprecation warnings visible, unless -Werror is set
3575
symbol_versioning.activate_deprecation_warnings(override=False)
3577
if cache_dir is not None:
3578
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
3575
3579
if testspecs_list is not None:
3576
3580
pattern = '|'.join(testspecs_list)
3596
3600
self.additional_selftest_args.setdefault(
3597
3601
'suite_decorators', []).append(parallel)
3599
raise errors.BzrCommandError(
3600
"--benchmark is no longer supported from bzr 2.2; "
3601
"use bzr-usertest instead")
3602
test_suite_factory = None
3603
test_suite_factory = benchmarks.test_suite
3604
# Unless user explicitly asks for quiet, be verbose in benchmarks
3605
verbose = not is_quiet()
3606
# TODO: should possibly lock the history file...
3607
benchfile = open(".perf_history", "at", buffering=1)
3608
self.add_cleanup(benchfile.close)
3610
test_suite_factory = None
3603
3612
selftest_kwargs = {"verbose": verbose,
3604
3613
"pattern": pattern,
3605
3614
"stop_on_failure": one,
3607
3616
"test_suite_factory": test_suite_factory,
3608
3617
"lsprof_timed": lsprof_timed,
3609
3618
"lsprof_tests": lsprof_tests,
3619
"bench_history": benchfile,
3610
3620
"matching_tests_first": first,
3611
3621
"list_only": list_only,
3612
3622
"random_seed": randomize,
3617
3627
"starting_with": starting_with
3619
3629
selftest_kwargs.update(self.additional_selftest_args)
3621
# Make deprecation warnings visible, unless -Werror is set
3622
cleanup = symbol_versioning.activate_deprecation_warnings(
3625
result = tests.selftest(**selftest_kwargs)
3630
result = selftest(**selftest_kwargs)
3628
3631
return int(not result)
3877
3880
def _do_preview(self, merger):
3878
3881
from bzrlib.diff import show_diff_trees
3879
3882
result_tree = self._get_preview(merger)
3880
path_encoding = osutils.get_diff_header_encoding()
3881
3883
show_diff_trees(merger.this_tree, result_tree, self.outf,
3882
old_label='', new_label='',
3883
path_encoding=path_encoding)
3884
old_label='', new_label='')
3885
3886
def _do_merge(self, merger, change_reporter, allow_pending, verified):
3886
3887
merger.change_reporter = change_reporter
4073
4074
from bzrlib.conflicts import restore
4074
4075
if merge_type is None:
4075
4076
merge_type = _mod_merge.Merge3Merger
4076
tree, file_list = WorkingTree.open_containing_paths(file_list)
4077
tree, file_list = tree_files(file_list)
4077
4078
self.add_cleanup(tree.lock_write().unlock)
4078
4079
parents = tree.get_parent_ids()
4079
4080
if len(parents) != 2:
4190
4191
def run(self, revision=None, no_backup=False, file_list=None,
4191
4192
forget_merges=None):
4192
tree, file_list = WorkingTree.open_containing_paths(file_list)
4193
tree, file_list = tree_files(file_list)
4193
4194
self.add_cleanup(tree.lock_tree_write().unlock)
4194
4195
if forget_merges:
4195
4196
tree.set_parent_ids(tree.get_parent_ids()[:1])
4285
4286
_see_also = ['merge', 'pull']
4286
4287
takes_args = ['other_branch?']
4287
4288
takes_options = [
4289
4289
Option('reverse', 'Reverse the order of revisions.'),
4290
4290
Option('mine-only',
4291
4291
'Display changes in the local branch only.'),
4313
4313
theirs_only=False,
4314
4314
log_format=None, long=False, short=False, line=False,
4315
4315
show_ids=False, verbose=False, this=False, other=False,
4316
include_merges=False, revision=None, my_revision=None,
4316
include_merges=False, revision=None, my_revision=None):
4318
4317
from bzrlib.missing import find_unmerged, iter_log_revisions
4319
4318
def message(s):
4320
4319
if not is_quiet():
4813
4812
class cmd_break_lock(Command):
4814
__doc__ = """Break a dead lock.
4816
This command breaks a lock on a repository, branch, working directory or
4813
__doc__ = """Break a dead lock on a repository, branch or working directory.
4819
4815
CAUTION: Locks should only be broken when you are sure that the process
4820
4816
holding the lock has been stopped.
4827
4823
bzr break-lock bzr+ssh://example.com/bzr/foo
4828
bzr break-lock --conf ~/.bazaar
4831
4825
takes_args = ['location?']
4834
help='LOCATION is the directory where the config lock is.'),
4837
def run(self, location=None, config=False):
4827
def run(self, location=None, show=False):
4838
4828
if location is None:
4839
4829
location = u'.'
4841
conf = _mod_config.LockableConfig(file_name=location)
4844
control, relpath = bzrdir.BzrDir.open_containing(location)
4846
control.break_lock()
4847
except NotImplementedError:
4830
control, relpath = bzrdir.BzrDir.open_containing(location)
4832
control.break_lock()
4833
except NotImplementedError:
4851
4837
class cmd_wait_until_signalled(Command):
4915
4901
def run(self, port=None, inet=False, directory=None, allow_writes=False,
4916
4902
protocol=None):
4917
from bzrlib import transport
4903
from bzrlib.transport import get_transport, transport_server_registry
4918
4904
if directory is None:
4919
4905
directory = os.getcwd()
4920
4906
if protocol is None:
4921
protocol = transport.transport_server_registry.get()
4907
protocol = transport_server_registry.get()
4922
4908
host, port = self.get_host_and_port(port)
4923
4909
url = urlutils.local_path_to_url(directory)
4924
4910
if not allow_writes:
4925
4911
url = 'readonly+' + url
4926
t = transport.get_transport(url)
4927
protocol(t, host, port, inet)
4912
transport = get_transport(url)
4913
protocol(transport, host, port, inet)
4930
4916
class cmd_join(Command):
5042
5027
encoding_type = 'exact'
5044
5029
def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
5045
sign=False, revision=None, mail_to=None, message=None,
5030
sign=False, revision=None, mail_to=None, message=None):
5047
5031
from bzrlib.revision import ensure_null, NULL_REVISION
5048
5032
include_patch, include_bundle = {
5049
5033
'plain': (False, False),
5050
5034
'diff': (True, False),
5051
5035
'bundle': (True, True),
5053
branch = Branch.open(directory)
5037
branch = Branch.open('.')
5054
5038
stored_submit_branch = branch.get_submit_branch()
5055
5039
if submit_branch is None:
5056
5040
submit_branch = stored_submit_branch
5141
5125
given, in which case it is sent to a file.
5143
5127
Mail is sent using your preferred mail program. This should be transparent
5144
on Windows (it uses MAPI). On Unix, it requires the xdg-email utility.
5128
on Windows (it uses MAPI). On Linux, it requires the xdg-email utility.
5145
5129
If the preferred client can't be found (or used), your editor will be used.
5147
5131
To use a specific mail program, set the mail_client configuration option.
5546
5530
takes_args = ['to_location?']
5547
takes_options = ['directory',
5531
takes_options = [Option('force',
5549
5532
help='Switch even if local commits will be lost.'),
5551
5534
Option('create-branch', short_name='b',
5556
5539
def run(self, to_location=None, force=False, create_branch=False,
5557
revision=None, directory=u'.'):
5558
5541
from bzrlib import switch
5559
tree_location = directory
5560
5543
revision = _get_one_revision('switch', revision)
5561
5544
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5562
5545
if to_location is None:
5563
5546
if revision is None:
5564
5547
raise errors.BzrCommandError('You must supply either a'
5565
5548
' revision or a location')
5566
to_location = tree_location
5568
5551
branch = control_dir.open_branch()
5569
5552
had_explicit_nick = branch.get_config().has_explicit_nickname()
5707
tree, file_list = WorkingTree.open_containing_paths(file_list,
5690
tree, file_list = tree_files(file_list, apply_view=False)
5709
5691
current_view, view_dict = tree.views.get_view_info()
5710
5692
if name is None:
5711
5693
name = current_view
5860
5841
_see_also = ['unshelve']
5862
5843
def run(self, revision=None, all=False, file_list=None, message=None,
5863
writer=None, list=False, destroy=False, directory=u'.'):
5844
writer=None, list=False, destroy=False):
5865
5846
return self.run_for_list()
5866
5847
from bzrlib.shelf_ui import Shelver
5868
5849
writer = bzrlib.option.diff_writer_registry.get()
5870
5851
shelver = Shelver.from_args(writer(sys.stdout), revision, all,
5871
file_list, message, destroy=destroy, directory=directory)
5852
file_list, message, destroy=destroy)
5903
5884
takes_args = ['shelf_id?']
5904
5885
takes_options = [
5906
5886
RegistryOption.from_kwargs(
5907
5887
'action', help="The action to perform.",
5908
5888
enum_switch=False, value_switches=True,
5917
5897
_see_also = ['shelve']
5919
def run(self, shelf_id=None, action='apply', directory=u'.'):
5899
def run(self, shelf_id=None, action='apply'):
5920
5900
from bzrlib.shelf_ui import Unshelver
5921
unshelver = Unshelver.from_args(shelf_id, action, directory=directory)
5901
unshelver = Unshelver.from_args(shelf_id, action)
5923
5903
unshelver.run()