75
76
from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
79
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
78
80
def tree_files(file_list, default_branch=u'.', canonicalize=True,
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]))
82
return internal_tree_files(file_list, default_branch, canonicalize,
88
86
def tree_files_for_add(file_list):
153
151
# XXX: Bad function name; should possibly also be a class method of
154
152
# WorkingTree rather than a function.
153
@symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
155
154
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True,
156
155
apply_view=True):
157
156
"""Convert command-line paths to a WorkingTree and relative paths.
158
Deprecated: use WorkingTree.open_containing_paths instead.
159
160
This is typically used for command-line processors that take one or
160
161
more filenames, and infer the workingtree that contains them.
172
173
:return: workingtree, [relative_paths]
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)
175
return WorkingTree.open_containing_paths(
176
file_list, default_directory='.',
223
181
def _get_view_info_for_change_reporter(tree):
193
def _open_directory_or_containing_tree_or_branch(filename, directory):
194
"""Open the tree or branch containing the specified file, unless
195
the --directory option is used to specify a different branch."""
196
if directory is not None:
197
return (None, Branch.open(directory), filename)
198
return bzrdir.BzrDir.open_containing_tree_or_branch(filename)
235
201
# TODO: Make sure no commands unconditionally use the working directory as a
236
202
# branch. If a filename argument is used, the first of them should be used to
237
203
# specify the branch. (Perhaps this can be factored out into some kind of
315
281
raise errors.BzrCommandError('bzr status --revision takes exactly'
316
282
' one or two revision specifiers')
318
tree, relfile_list = tree_files(file_list)
284
tree, relfile_list = WorkingTree.open_containing_paths(file_list)
319
285
# Avoid asking for specific files when that is not needed.
320
286
if relfile_list == ['']:
321
287
relfile_list = None
353
319
self.outf.write(revtext.decode('utf-8'))
356
def run(self, revision_id=None, revision=None):
322
def run(self, revision_id=None, revision=None, directory=u'.'):
357
323
if revision_id is not None and revision is not None:
358
324
raise errors.BzrCommandError('You can only supply one of'
359
325
' revision_id or --revision')
360
326
if revision_id is None and revision is None:
361
327
raise errors.BzrCommandError('You must supply either'
362
328
' --revision or a revision_id')
363
b = WorkingTree.open_containing(u'.')[0].branch
329
b = WorkingTree.open_containing(directory)[0].branch
365
331
revisions = b.repository.revisions
366
332
if revisions is None:
504
470
if (working.has_changes()):
505
471
raise errors.UncommittedChanges(working)
472
if working.get_shelf_manager().last_shelf() is not None:
473
raise errors.ShelvedChanges(working)
507
475
if working.user_url != working.branch.user_url:
508
476
raise errors.BzrCommandError("You cannot remove the working tree"
552
520
takes_args = ['revision_info*']
553
521
takes_options = [
523
custom_help('directory',
556
524
help='Branch to examine, '
557
'rather than the one containing the working directory.',
525
'rather than the one containing the working directory.'),
561
526
Option('tree', help='Show revno of working tree'),
754
719
raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
756
721
revision = _get_one_revision('inventory', revision)
757
work_tree, file_list = tree_files(file_list)
722
work_tree, file_list = WorkingTree.open_containing_paths(file_list)
758
723
self.add_cleanup(work_tree.lock_read().unlock)
759
724
if revision is not None:
760
725
tree = revision.as_tree(work_tree.branch)
826
791
if len(names_list) < 2:
827
792
raise errors.BzrCommandError("missing file argument")
828
tree, rel_names = tree_files(names_list, canonicalize=False)
793
tree, rel_names = WorkingTree.open_containing_paths(names_list, canonicalize=False)
829
794
self.add_cleanup(tree.lock_tree_write().unlock)
830
795
self._run(tree, names_list, rel_names, after)
837
802
raise errors.BzrCommandError('--after cannot be specified with'
839
work_tree, file_list = tree_files(names_list, default_branch='.')
804
work_tree, file_list = WorkingTree.open_containing_paths(
805
names_list, default_directory='.')
840
806
self.add_cleanup(work_tree.lock_tree_write().unlock)
841
807
rename_map.RenameMap.guess_renames(work_tree, dry_run)
951
917
takes_options = ['remember', 'overwrite', 'revision',
952
918
custom_help('verbose',
953
919
help='Show logs of pulled revisions.'),
920
custom_help('directory',
955
921
help='Branch to pull into, '
956
'rather than the one containing the working directory.',
922
'rather than the one containing the working directory.'),
961
924
help="Perform a local pull in a bound "
962
925
"branch. Local pulls are not applied to "
963
926
"the master branch."
929
help="Show base revision text in conflicts.")
966
931
takes_args = ['location?']
967
932
encoding_type = 'replace'
969
934
def run(self, location=None, remember=False, overwrite=False,
970
935
revision=None, verbose=False,
971
directory=None, local=False):
936
directory=None, local=False,
972
938
# FIXME: too much stuff is in the command class
973
939
revision_id = None
983
949
branch_to = Branch.open_containing(directory)[0]
984
950
self.add_cleanup(branch_to.lock_write().unlock)
952
if tree_to is None and show_base:
953
raise errors.BzrCommandError("Need working tree for --show-base.")
986
955
if local and not branch_to.get_bound_location():
987
956
raise errors.LocalRequiresBoundBranch()
1033
1002
view_info=view_info)
1034
1003
result = tree_to.pull(
1035
1004
branch_from, overwrite, revision_id, change_reporter,
1036
possible_transports=possible_transports, local=local)
1005
possible_transports=possible_transports, local=local,
1006
show_base=show_base)
1038
1008
result = branch_to.pull(
1039
1009
branch_from, overwrite, revision_id, local=local)
1076
1046
Option('create-prefix',
1077
1047
help='Create the path leading up to the branch '
1078
1048
'if it does not already exist.'),
1049
custom_help('directory',
1080
1050
help='Branch to push from, '
1081
'rather than the one containing the working directory.',
1051
'rather than the one containing the working directory.'),
1085
1052
Option('use-existing-dir',
1086
1053
help='By default push will fail if the target'
1087
1054
' directory exists, but does not already'
1177
1144
_see_also = ['checkout']
1178
1145
takes_args = ['from_location', 'to_location?']
1179
takes_options = ['revision', Option('hardlink',
1180
help='Hard-link working tree files where possible.'),
1146
takes_options = ['revision',
1147
Option('hardlink', help='Hard-link working tree files where possible.'),
1148
Option('files-from', type=str,
1149
help="Get file contents from this tree."),
1181
1150
Option('no-tree',
1182
1151
help="Create a branch without a working-tree."),
1183
1152
Option('switch',
1202
1171
def run(self, from_location, to_location=None, revision=None,
1203
1172
hardlink=False, stacked=False, standalone=False, no_tree=False,
1204
use_existing_dir=False, switch=False, bind=False):
1173
use_existing_dir=False, switch=False, bind=False,
1205
1175
from bzrlib import switch as _mod_switch
1206
1176
from bzrlib.tag import _merge_tags_if_possible
1207
1177
accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1179
if not (hardlink or files_from):
1180
# accelerator_tree is usually slower because you have to read N
1181
# files (no readahead, lots of seeks, etc), but allow the user to
1182
# explicitly request it
1183
accelerator_tree = None
1184
if files_from is not None and files_from != from_location:
1185
accelerator_tree = WorkingTree.open(files_from)
1209
1186
revision = _get_one_revision('branch', revision)
1210
1187
self.add_cleanup(br_from.lock_read().unlock)
1211
1188
if revision is not None:
1318
1295
to_location = branch_location
1319
1296
accelerator_tree, source = bzrdir.BzrDir.open_tree_or_branch(
1320
1297
branch_location)
1298
if not (hardlink or files_from):
1299
# accelerator_tree is usually slower because you have to read N
1300
# files (no readahead, lots of seeks, etc), but allow the user to
1301
# explicitly request it
1302
accelerator_tree = None
1321
1303
revision = _get_one_revision('checkout', revision)
1322
if files_from is not None:
1304
if files_from is not None and files_from != branch_location:
1323
1305
accelerator_tree = WorkingTree.open(files_from)
1324
1306
if revision is not None:
1325
1307
revision_id = revision.as_revision_id(source)
1381
1363
If you want to discard your local changes, you can just do a
1382
1364
'bzr revert' instead of 'bzr commit' after the update.
1366
If you want to restore a file that has been removed locally, use
1367
'bzr revert' instead of 'bzr update'.
1384
1369
If the tree's branch is bound to a master branch, it will also update
1385
1370
the branch from the master.
1388
1373
_see_also = ['pull', 'working-trees', 'status-flags']
1389
1374
takes_args = ['dir?']
1390
takes_options = ['revision']
1375
takes_options = ['revision',
1377
help="Show base revision text in conflicts."),
1391
1379
aliases = ['up']
1393
def run(self, dir='.', revision=None):
1381
def run(self, dir='.', revision=None, show_base=None):
1394
1382
if revision is not None and len(revision) != 1:
1395
1383
raise errors.BzrCommandError(
1396
1384
"bzr update --revision takes exactly one revision")
1436
1424
change_reporter,
1437
1425
possible_transports=possible_transports,
1438
1426
revision=revision_id,
1428
show_base=show_base)
1440
1429
except errors.NoSuchRevision, e:
1441
1430
raise errors.BzrCommandError(
1442
1431
"branch has no revision %s\n"
1504
1493
class cmd_remove(Command):
1505
1494
__doc__ = """Remove files or directories.
1507
This makes bzr stop tracking changes to the specified files. bzr will delete
1508
them if they can easily be recovered using revert. If no options or
1509
parameters are given bzr will scan for files that are being tracked by bzr
1510
but missing in your tree and stop tracking them for you.
1496
This makes Bazaar stop tracking changes to the specified files. Bazaar will
1497
delete them if they can easily be recovered using revert otherwise they
1498
will be backed up (adding an extention of the form .~#~). If no options or
1499
parameters are given Bazaar will scan for files that are being tracked by
1500
Bazaar but missing in your tree and stop tracking them for you.
1512
1502
takes_args = ['file*']
1513
1503
takes_options = ['verbose',
1515
1505
RegistryOption.from_kwargs('file-deletion-strategy',
1516
1506
'The file deletion mode to be used.',
1517
1507
title='Deletion Strategy', value_switches=True, enum_switch=False,
1518
safe='Only delete files if they can be'
1519
' safely recovered (default).',
1508
safe='Backup changed files (default).',
1520
1509
keep='Delete from bzr but leave the working copy.',
1510
no_backup='Don\'t backup changed files.',
1521
1511
force='Delete all the specified files, even if they can not be '
1522
'recovered and even if they are non-empty directories.')]
1512
'recovered and even if they are non-empty directories. '
1513
'(deprecated, use no-backup)')]
1523
1514
aliases = ['rm', 'del']
1524
1515
encoding_type = 'replace'
1526
1517
def run(self, file_list, verbose=False, new=False,
1527
1518
file_deletion_strategy='safe'):
1528
tree, file_list = tree_files(file_list)
1519
if file_deletion_strategy == 'force':
1520
note("(The --force option is deprecated, rather use --no-backup "
1522
file_deletion_strategy = 'no-backup'
1524
tree, file_list = WorkingTree.open_containing_paths(file_list)
1530
1526
if file_list is not None:
1531
1527
file_list = [f for f in file_list]
1551
1547
file_deletion_strategy = 'keep'
1552
1548
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1553
1549
keep_files=file_deletion_strategy=='keep',
1554
force=file_deletion_strategy=='force')
1550
force=(file_deletion_strategy=='no-backup'))
1557
1553
class cmd_file_id(Command):
1620
1616
_see_also = ['check']
1621
1617
takes_args = ['branch?']
1619
Option('canonicalize-chks',
1620
help='Make sure CHKs are in canonical form (repairs '
1623
def run(self, branch="."):
1625
def run(self, branch=".", canonicalize_chks=False):
1624
1626
from bzrlib.reconcile import reconcile
1625
1627
dir = bzrdir.BzrDir.open(branch)
1628
reconcile(dir, canonicalize_chks=canonicalize_chks)
1629
1631
class cmd_revision_history(Command):
1969
1975
old_branch, new_branch,
1970
1976
specific_files, extra_trees) = get_trees_and_branches_to_diff_locked(
1971
1977
file_list, revision, old, new, self.add_cleanup, apply_view=True)
1978
# GNU diff on Windows uses ANSI encoding for filenames
1979
path_encoding = osutils.get_diff_header_encoding()
1972
1980
return show_diff_trees(old_tree, new_tree, sys.stdout,
1973
1981
specific_files=specific_files,
1974
1982
external_diff_options=diff_options,
1975
1983
old_label=old_label, new_label=new_label,
1976
extra_trees=extra_trees, using=using,
1984
extra_trees=extra_trees,
1985
path_encoding=path_encoding,
1977
1987
format_cls=format)
1987
1997
# level of effort but possibly much less IO. (Or possibly not,
1988
1998
# if the directories are very large...)
1989
1999
_see_also = ['status', 'ls']
1990
takes_options = ['show-ids']
2000
takes_options = ['directory', 'show-ids']
1992
2002
@display_command
1993
def run(self, show_ids=False):
1994
tree = WorkingTree.open_containing(u'.')[0]
2003
def run(self, show_ids=False, directory=u'.'):
2004
tree = WorkingTree.open_containing(directory)[0]
1995
2005
self.add_cleanup(tree.lock_read().unlock)
1996
2006
old = tree.basis_tree()
1997
2007
self.add_cleanup(old.lock_read().unlock)
2012
2022
_see_also = ['status', 'ls']
2015
help='Write an ascii NUL (\\0) separator '
2016
'between files rather than a newline.')
2023
takes_options = ['directory', 'null']
2019
2025
@display_command
2020
def run(self, null=False):
2021
tree = WorkingTree.open_containing(u'.')[0]
2026
def run(self, null=False, directory=u'.'):
2027
tree = WorkingTree.open_containing(directory)[0]
2022
2028
td = tree.changes_from(tree.basis_tree())
2023
2029
for path, id, kind, text_modified, meta_modified in td.modified:
2035
2041
_see_also = ['status', 'ls']
2038
help='Write an ascii NUL (\\0) separator '
2039
'between files rather than a newline.')
2042
takes_options = ['directory', 'null']
2042
2044
@display_command
2043
def run(self, null=False):
2044
wt = WorkingTree.open_containing(u'.')[0]
2045
def run(self, null=False, directory=u'.'):
2046
wt = WorkingTree.open_containing(directory)[0]
2045
2047
self.add_cleanup(wt.lock_read().unlock)
2046
2048
basis = wt.basis_tree()
2047
2049
self.add_cleanup(basis.lock_read().unlock)
2053
2055
if inv.is_root(file_id) and len(basis_inv) == 0:
2055
2057
path = inv.id2path(file_id)
2056
if not os.access(osutils.abspath(path), os.F_OK):
2058
if not os.access(osutils.pathjoin(wt.basedir, path), os.F_OK):
2059
2061
self.outf.write(path + '\0')
2259
2261
help='Show just the specified revision.'
2260
2262
' See also "help revisionspec".'),
2264
RegistryOption('authors',
2265
'What names to list as authors - first, all or committer.',
2267
lazy_registry=('bzrlib.log', 'author_list_registry'),
2262
2269
Option('levels',
2263
2270
short_name='n',
2264
2271
help='Number of levels to display - 0 for all, 1 for flat.',
2382
2390
show_timezone=timezone,
2383
2391
delta_format=get_verbosity_level(),
2385
show_advice=levels is None)
2393
show_advice=levels is None,
2394
author_list_handler=authors)
2387
2396
# Choose the algorithm for doing the logging. It's annoying
2388
2397
# having multiple code paths like this but necessary until
2505
2514
help='Recurse into subdirectories.'),
2506
2515
Option('from-root',
2507
2516
help='Print paths relative to the root of the branch.'),
2508
Option('unknown', help='Print unknown files.'),
2517
Option('unknown', short_name='u',
2518
help='Print unknown files.'),
2509
2519
Option('versioned', help='Print versioned files.',
2510
2520
short_name='V'),
2511
Option('ignored', help='Print ignored files.'),
2513
help='Write an ascii NUL (\\0) separator '
2514
'between files rather than a newline.'),
2521
Option('ignored', short_name='i',
2522
help='Print ignored files.'),
2523
Option('kind', short_name='k',
2516
2524
help='List entries of a particular kind: file, directory, symlink.',
2520
2530
@display_command
2521
2531
def run(self, revision=None, verbose=False,
2522
2532
recursive=False, from_root=False,
2523
2533
unknown=False, versioned=False, ignored=False,
2524
null=False, kind=None, show_ids=False, path=None):
2534
null=False, kind=None, show_ids=False, path=None, directory=None):
2526
2536
if kind and kind not in ('file', 'directory', 'symlink'):
2527
2537
raise errors.BzrCommandError('invalid kind specified')
2539
2549
raise errors.BzrCommandError('cannot specify both --from-root'
2542
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
2552
tree, branch, relpath = \
2553
_open_directory_or_containing_tree_or_branch(fs_path, directory)
2545
2555
# Calculate the prefix to use
2616
2626
_see_also = ['ls']
2627
takes_options = ['directory']
2618
2629
@display_command
2620
for f in WorkingTree.open_containing(u'.')[0].unknowns():
2630
def run(self, directory=u'.'):
2631
for f in WorkingTree.open_containing(directory)[0].unknowns():
2621
2632
self.outf.write(osutils.quotefn(f) + '\n')
2689
2700
_see_also = ['status', 'ignored', 'patterns']
2690
2701
takes_args = ['name_pattern*']
2702
takes_options = ['directory',
2692
2703
Option('default-rules',
2693
2704
help='Display the default ignore rules that bzr uses.')
2696
def run(self, name_pattern_list=None, default_rules=None):
2707
def run(self, name_pattern_list=None, default_rules=None,
2697
2709
from bzrlib import ignores
2698
2710
if default_rules is not None:
2699
2711
# dump the default rules and exit
2705
2717
"NAME_PATTERN or --default-rules.")
2706
2718
name_pattern_list = [globbing.normalize_pattern(p)
2707
2719
for p in name_pattern_list]
2721
for p in name_pattern_list:
2722
if not globbing.Globster.is_pattern_valid(p):
2723
bad_patterns += ('\n %s' % p)
2725
msg = ('Invalid ignore pattern(s) found. %s' % bad_patterns)
2726
ui.ui_factory.show_error(msg)
2727
raise errors.InvalidPattern('')
2708
2728
for name_pattern in name_pattern_list:
2709
2729
if (name_pattern[0] == '/' or
2710
2730
(len(name_pattern) > 1 and name_pattern[1] == ':')):
2711
2731
raise errors.BzrCommandError(
2712
2732
"NAME_PATTERN should not be an absolute path")
2713
tree, relpath = WorkingTree.open_containing(u'.')
2733
tree, relpath = WorkingTree.open_containing(directory)
2714
2734
ignores.tree_ignores_add_patterns(tree, name_pattern_list)
2715
2735
ignored = globbing.Globster(name_pattern_list)
2737
self.add_cleanup(tree.lock_read().unlock)
2718
2738
for entry in tree.list_files():
2720
2740
if id is not None:
2721
2741
filename = entry[0]
2722
2742
if ignored.match(filename):
2723
2743
matches.append(filename)
2725
2744
if len(matches) > 0:
2726
2745
self.outf.write("Warning: the following files are version controlled and"
2727
2746
" match your ignore pattern:\n%s"
2743
2762
encoding_type = 'replace'
2744
2763
_see_also = ['ignore', 'ls']
2764
takes_options = ['directory']
2746
2766
@display_command
2748
tree = WorkingTree.open_containing(u'.')[0]
2767
def run(self, directory=u'.'):
2768
tree = WorkingTree.open_containing(directory)[0]
2749
2769
self.add_cleanup(tree.lock_read().unlock)
2750
2770
for path, file_class, kind, file_id, entry in tree.list_files():
2751
2771
if file_class != 'I':
2765
2785
takes_args = ['revno']
2786
takes_options = ['directory']
2767
2788
@display_command
2768
def run(self, revno):
2789
def run(self, revno, directory=u'.'):
2770
2791
revno = int(revno)
2771
2792
except ValueError:
2772
2793
raise errors.BzrCommandError("not a valid revision-number: %r"
2774
revid = WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
2795
revid = WorkingTree.open_containing(directory)[0].branch.get_rev_id(revno)
2775
2796
self.outf.write("%s\n" % revid)
2804
2825
================= =========================
2806
2827
takes_args = ['dest', 'branch_or_subdir?']
2828
takes_options = ['directory',
2808
2829
Option('format',
2809
2830
help="Type of file to export to.",
2819
2840
'revision in which it was changed.'),
2821
2842
def run(self, dest, branch_or_subdir=None, revision=None, format=None,
2822
root=None, filters=False, per_file_timestamps=False):
2843
root=None, filters=False, per_file_timestamps=False, directory=u'.'):
2823
2844
from bzrlib.export import export
2825
2846
if branch_or_subdir is None:
2826
tree = WorkingTree.open_containing(u'.')[0]
2847
tree = WorkingTree.open_containing(directory)[0]
2827
2848
b = tree.branch
2850
2871
_see_also = ['ls']
2872
takes_options = ['directory',
2852
2873
Option('name-from-revision', help='The path name in the old tree.'),
2853
2874
Option('filters', help='Apply content filters to display the '
2854
2875
'convenience form.'),
2860
2881
@display_command
2861
2882
def run(self, filename, revision=None, name_from_revision=False,
2883
filters=False, directory=None):
2863
2884
if revision is not None and len(revision) != 1:
2864
2885
raise errors.BzrCommandError("bzr cat --revision takes exactly"
2865
2886
" one revision specifier")
2866
2887
tree, branch, relpath = \
2867
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2888
_open_directory_or_containing_tree_or_branch(filename, directory)
2868
2889
self.add_cleanup(branch.lock_read().unlock)
2869
2890
return self._run(tree, branch, relpath, filename, revision,
2870
2891
name_from_revision, filters)
3102
3123
properties = {}
3104
tree, selected_list = tree_files(selected_list)
3125
tree, selected_list = WorkingTree.open_containing_paths(selected_list)
3105
3126
if selected_list == ['']:
3106
3127
# workaround - commit of root of tree should be exactly the same
3107
3128
# as just default commit in that tree, and succeed even though
3142
3163
def get_message(commit_obj):
3143
3164
"""Callback to get commit message"""
3145
my_message = codecs.open(
3146
file, 'rt', osutils.get_user_encoding()).read()
3168
my_message = f.read().decode(osutils.get_user_encoding())
3147
3171
elif message is not None:
3148
3172
my_message = message
3178
3202
reporter=None, verbose=verbose, revprops=properties,
3179
3203
authors=author, timestamp=commit_stamp,
3180
3204
timezone=offset,
3181
exclude=safe_relpath_files(tree, exclude))
3205
exclude=tree.safe_relpath_files(exclude))
3182
3206
except PointlessCommit:
3183
3207
raise errors.BzrCommandError("No changes to commit."
3184
3208
" Use --unchanged to commit anyhow.")
3304
3328
bzr whoami "Frank Chu <fchu@example.com>"
3306
takes_options = [ Option('email',
3330
takes_options = [ 'directory',
3307
3332
help='Display email address only.'),
3308
3333
Option('branch',
3309
3334
help='Set identity for the current branch instead of '
3313
3338
encoding_type = 'replace'
3315
3340
@display_command
3316
def run(self, email=False, branch=False, name=None):
3341
def run(self, email=False, branch=False, name=None, directory=None):
3317
3342
if name is None:
3318
# use branch if we're inside one; otherwise global config
3320
c = Branch.open_containing('.')[0].get_config()
3321
except errors.NotBranchError:
3322
c = config.GlobalConfig()
3343
if directory is None:
3344
# use branch if we're inside one; otherwise global config
3346
c = Branch.open_containing(u'.')[0].get_config()
3347
except errors.NotBranchError:
3348
c = _mod_config.GlobalConfig()
3350
c = Branch.open(directory).get_config()
3324
3352
self.outf.write(c.user_email() + '\n')
3329
3357
# display a warning if an email address isn't included in the given name.
3331
config.extract_email_address(name)
3359
_mod_config.extract_email_address(name)
3332
3360
except errors.NoEmailInUsername, e:
3333
3361
warning('"%s" does not seem to contain an email address. '
3334
3362
'This is allowed, but not recommended.', name)
3336
3364
# use global config unless --branch given
3338
c = Branch.open_containing('.')[0].get_config()
3366
if directory is None:
3367
c = Branch.open_containing(u'.')[0].get_config()
3369
c = Branch.open(directory).get_config()
3340
c = config.GlobalConfig()
3371
c = _mod_config.GlobalConfig()
3341
3372
c.set_user_option('email', name)
3354
3385
_see_also = ['info']
3355
3386
takes_args = ['nickname?']
3356
def run(self, nickname=None):
3357
branch = Branch.open_containing(u'.')[0]
3387
takes_options = ['directory']
3388
def run(self, nickname=None, directory=u'.'):
3389
branch = Branch.open_containing(directory)[0]
3358
3390
if nickname is None:
3359
3391
self.printme(branch)
3409
3441
'bzr alias --remove expects an alias to remove.')
3410
3442
# If alias is not found, print something like:
3411
3443
# unalias: foo: not found
3412
c = config.GlobalConfig()
3444
c = _mod_config.GlobalConfig()
3413
3445
c.unset_alias(alias_name)
3415
3447
@display_command
3416
3448
def print_aliases(self):
3417
3449
"""Print out the defined aliases in a similar format to bash."""
3418
aliases = config.GlobalConfig().get_aliases()
3450
aliases = _mod_config.GlobalConfig().get_aliases()
3419
3451
for key, value in sorted(aliases.iteritems()):
3420
3452
self.outf.write('bzr alias %s="%s"\n' % (key, value))
3432
3464
def set_alias(self, alias_name, alias_command):
3433
3465
"""Save the alias in the global config."""
3434
c = config.GlobalConfig()
3466
c = _mod_config.GlobalConfig()
3435
3467
c.set_alias(alias_name, alias_command)
3472
3504
If you set BZR_TEST_PDB=1 when running selftest, failing tests will drop
3473
3505
into a pdb postmortem session.
3507
The --coverage=DIRNAME global option produces a report with covered code
3476
3511
Run only tests relating to 'ignore'::
3510
3545
'throughout the test suite.',
3511
3546
type=get_transport_type),
3512
3547
Option('benchmark',
3513
help='Run the benchmarks rather than selftests.'),
3548
help='Run the benchmarks rather than selftests.',
3514
3550
Option('lsprof-timed',
3515
3551
help='Generate lsprof output for benchmarked'
3516
3552
' sections of code.'),
3517
3553
Option('lsprof-tests',
3518
3554
help='Generate lsprof output for each test.'),
3519
Option('cache-dir', type=str,
3520
help='Cache intermediate benchmark output in this '
3522
3555
Option('first',
3523
3556
help='Run all tests, but run specified tests first.',
3524
3557
short_name='f',
3559
3592
def run(self, testspecs_list=None, verbose=False, one=False,
3560
3593
transport=None, benchmark=None,
3561
lsprof_timed=None, cache_dir=None,
3562
3595
first=False, list_only=False,
3563
3596
randomize=None, exclude=None, strict=False,
3564
3597
load_list=None, debugflag=None, starting_with=None, subunit=False,
3565
3598
parallel=None, lsprof_tests=False):
3566
from bzrlib.tests import selftest
3567
import bzrlib.benchmarks as benchmarks
3568
from bzrlib.benchmarks import tree_creator
3570
# Make deprecation warnings visible, unless -Werror is set
3571
symbol_versioning.activate_deprecation_warnings(override=False)
3573
if cache_dir is not None:
3574
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
3599
from bzrlib import tests
3575
3601
if testspecs_list is not None:
3576
3602
pattern = '|'.join(testspecs_list)
3585
3611
self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3586
3612
# On Windows, disable automatic conversion of '\n' to '\r\n' in
3587
3613
# stdout, which would corrupt the subunit stream.
3588
if sys.platform == "win32" and sys.stdout.fileno() >= 0:
3614
# FIXME: This has been fixed in subunit trunk (>0.0.5) so the
3615
# following code can be deleted when it's sufficiently deployed
3616
# -- vila/mgz 20100514
3617
if (sys.platform == "win32"
3618
and getattr(sys.stdout, 'fileno', None) is not None):
3590
3620
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
3592
3622
self.additional_selftest_args.setdefault(
3593
3623
'suite_decorators', []).append(parallel)
3595
test_suite_factory = benchmarks.test_suite
3596
# Unless user explicitly asks for quiet, be verbose in benchmarks
3597
verbose = not is_quiet()
3598
# TODO: should possibly lock the history file...
3599
benchfile = open(".perf_history", "at", buffering=1)
3600
self.add_cleanup(benchfile.close)
3602
test_suite_factory = None
3625
raise errors.BzrCommandError(
3626
"--benchmark is no longer supported from bzr 2.2; "
3627
"use bzr-usertest instead")
3628
test_suite_factory = None
3604
3629
selftest_kwargs = {"verbose": verbose,
3605
3630
"pattern": pattern,
3606
3631
"stop_on_failure": one,
3608
3633
"test_suite_factory": test_suite_factory,
3609
3634
"lsprof_timed": lsprof_timed,
3610
3635
"lsprof_tests": lsprof_tests,
3611
"bench_history": benchfile,
3612
3636
"matching_tests_first": first,
3613
3637
"list_only": list_only,
3614
3638
"random_seed": randomize,
3619
3643
"starting_with": starting_with
3621
3645
selftest_kwargs.update(self.additional_selftest_args)
3622
result = selftest(**selftest_kwargs)
3647
# Make deprecation warnings visible, unless -Werror is set
3648
cleanup = symbol_versioning.activate_deprecation_warnings(
3651
result = tests.selftest(**selftest_kwargs)
3623
3654
return int(not result)
3764
3795
' completely merged into the source, pull from the'
3765
3796
' source rather than merging. When this happens,'
3766
3797
' you do not need to commit the result.'),
3798
custom_help('directory',
3768
3799
help='Branch to merge into, '
3769
'rather than the one containing the working directory.',
3800
'rather than the one containing the working directory.'),
3773
3801
Option('preview', help='Instead of merging, show a diff of the'
3775
3803
Option('interactive', help='Select changes interactively.',
3875
3903
def _do_preview(self, merger):
3876
3904
from bzrlib.diff import show_diff_trees
3877
3905
result_tree = self._get_preview(merger)
3906
path_encoding = osutils.get_diff_header_encoding()
3878
3907
show_diff_trees(merger.this_tree, result_tree, self.outf,
3879
old_label='', new_label='')
3908
old_label='', new_label='',
3909
path_encoding=path_encoding)
3881
3911
def _do_merge(self, merger, change_reporter, allow_pending, verified):
3882
3912
merger.change_reporter = change_reporter
4069
4099
from bzrlib.conflicts import restore
4070
4100
if merge_type is None:
4071
4101
merge_type = _mod_merge.Merge3Merger
4072
tree, file_list = tree_files(file_list)
4102
tree, file_list = WorkingTree.open_containing_paths(file_list)
4073
4103
self.add_cleanup(tree.lock_write().unlock)
4074
4104
parents = tree.get_parent_ids()
4075
4105
if len(parents) != 2:
4186
4216
def run(self, revision=None, no_backup=False, file_list=None,
4187
4217
forget_merges=None):
4188
tree, file_list = tree_files(file_list)
4218
tree, file_list = WorkingTree.open_containing_paths(file_list)
4189
4219
self.add_cleanup(tree.lock_tree_write().unlock)
4190
4220
if forget_merges:
4191
4221
tree.set_parent_ids(tree.get_parent_ids()[:1])
4281
4311
_see_also = ['merge', 'pull']
4282
4312
takes_args = ['other_branch?']
4283
4313
takes_options = [
4284
4315
Option('reverse', 'Reverse the order of revisions.'),
4285
4316
Option('mine-only',
4286
4317
'Display changes in the local branch only.'),
4308
4339
theirs_only=False,
4309
4340
log_format=None, long=False, short=False, line=False,
4310
4341
show_ids=False, verbose=False, this=False, other=False,
4311
include_merges=False, revision=None, my_revision=None):
4342
include_merges=False, revision=None, my_revision=None,
4312
4344
from bzrlib.missing import find_unmerged, iter_log_revisions
4313
4345
def message(s):
4314
4346
if not is_quiet():
4542
4574
Option('long', help='Show commit date in annotations.'),
4546
4579
encoding_type = 'exact'
4548
4581
@display_command
4549
4582
def run(self, filename, all=False, long=False, revision=None,
4583
show_ids=False, directory=None):
4551
4584
from bzrlib.annotate import annotate_file, annotate_file_tree
4552
4585
wt, branch, relpath = \
4553
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
4586
_open_directory_or_containing_tree_or_branch(filename, directory)
4554
4587
if wt is not None:
4555
4588
self.add_cleanup(wt.lock_read().unlock)
4581
4614
hidden = True # is this right ?
4582
4615
takes_args = ['revision_id*']
4583
takes_options = ['revision']
4616
takes_options = ['directory', 'revision']
4585
def run(self, revision_id_list=None, revision=None):
4618
def run(self, revision_id_list=None, revision=None, directory=u'.'):
4586
4619
if revision_id_list is not None and revision is not None:
4587
4620
raise errors.BzrCommandError('You can only supply one of revision_id or --revision')
4588
4621
if revision_id_list is None and revision is None:
4589
4622
raise errors.BzrCommandError('You must supply either --revision or a revision_id')
4590
b = WorkingTree.open_containing(u'.')[0].branch
4623
b = WorkingTree.open_containing(directory)[0].branch
4591
4624
self.add_cleanup(b.lock_write().unlock)
4592
4625
return self._run(b, revision_id_list, revision)
4654
4687
_see_also = ['checkouts', 'unbind']
4655
4688
takes_args = ['location?']
4689
takes_options = ['directory']
4658
def run(self, location=None):
4659
b, relpath = Branch.open_containing(u'.')
4691
def run(self, location=None, directory=u'.'):
4692
b, relpath = Branch.open_containing(directory)
4660
4693
if location is None:
4662
4695
location = b.get_old_bound_location()
4690
4723
_see_also = ['checkouts', 'bind']
4691
4724
takes_args = []
4725
takes_options = ['directory']
4695
b, relpath = Branch.open_containing(u'.')
4727
def run(self, directory=u'.'):
4728
b, relpath = Branch.open_containing(directory)
4696
4729
if not b.unbind():
4697
4730
raise errors.BzrCommandError('Local branch is not bound')
4791
4824
self.outf.write('The above revision(s) will be removed.\n')
4794
if not ui.ui_factory.get_boolean('Are you sure'):
4795
self.outf.write('Canceled')
4827
if not ui.ui_factory.confirm_action(
4828
'Uncommit these revisions',
4829
'bzrlib.builtins.uncommit',
4831
self.outf.write('Canceled\n')
4798
4834
mutter('Uncommitting from {%s} to {%s}',
4806
4842
class cmd_break_lock(Command):
4807
__doc__ = """Break a dead lock on a repository, branch or working directory.
4843
__doc__ = """Break a dead lock.
4845
This command breaks a lock on a repository, branch, working directory or
4809
4848
CAUTION: Locks should only be broken when you are sure that the process
4810
4849
holding the lock has been stopped.
4817
4856
bzr break-lock bzr+ssh://example.com/bzr/foo
4857
bzr break-lock --conf ~/.bazaar
4819
4860
takes_args = ['location?']
4863
help='LOCATION is the directory where the config lock is.'),
4865
help='Do not ask for confirmation before breaking the lock.'),
4821
def run(self, location=None, show=False):
4868
def run(self, location=None, config=False, force=False):
4822
4869
if location is None:
4823
4870
location = u'.'
4824
control, relpath = bzrdir.BzrDir.open_containing(location)
4826
control.break_lock()
4827
except NotImplementedError:
4872
ui.ui_factory = ui.ConfirmationUserInterfacePolicy(ui.ui_factory,
4874
{'bzrlib.lockdir.break': True})
4876
conf = _mod_config.LockableConfig(file_name=location)
4879
control, relpath = bzrdir.BzrDir.open_containing(location)
4881
control.break_lock()
4882
except NotImplementedError:
4831
4886
class cmd_wait_until_signalled(Command):
4860
4915
'result in a dynamically allocated port. The default port '
4861
4916
'depends on the protocol.',
4864
help='Serve contents of this directory.',
4918
custom_help('directory',
4919
help='Serve contents of this directory.'),
4866
4920
Option('allow-writes',
4867
4921
help='By default the server is a readonly server. Supplying '
4868
4922
'--allow-writes enables write access to the contents of '
4896
4950
def run(self, port=None, inet=False, directory=None, allow_writes=False,
4897
4951
protocol=None):
4898
from bzrlib.transport import get_transport, transport_server_registry
4952
from bzrlib import transport
4899
4953
if directory is None:
4900
4954
directory = os.getcwd()
4901
4955
if protocol is None:
4902
protocol = transport_server_registry.get()
4956
protocol = transport.transport_server_registry.get()
4903
4957
host, port = self.get_host_and_port(port)
4904
4958
url = urlutils.local_path_to_url(directory)
4905
4959
if not allow_writes:
4906
4960
url = 'readonly+' + url
4907
transport = get_transport(url)
4908
protocol(transport, host, port, inet)
4961
t = transport.get_transport(url)
4962
protocol(t, host, port, inet)
4911
4965
class cmd_join(Command):
4917
4971
not part of it. (Such trees can be produced by "bzr split", but also by
4918
4972
running "bzr branch" with the target inside a tree.)
4920
The result is a combined tree, with the subtree no longer an independant
4974
The result is a combined tree, with the subtree no longer an independent
4921
4975
part. This is marked as a merge of the subtree into the containing tree,
4922
4976
and all history is preserved.
5022
5077
encoding_type = 'exact'
5024
5079
def run(self, submit_branch=None, public_branch=None, patch_type='bundle',
5025
sign=False, revision=None, mail_to=None, message=None):
5080
sign=False, revision=None, mail_to=None, message=None,
5026
5082
from bzrlib.revision import ensure_null, NULL_REVISION
5027
5083
include_patch, include_bundle = {
5028
5084
'plain': (False, False),
5029
5085
'diff': (True, False),
5030
5086
'bundle': (True, True),
5032
branch = Branch.open('.')
5088
branch = Branch.open(directory)
5033
5089
stored_submit_branch = branch.get_submit_branch()
5034
5090
if submit_branch is None:
5035
5091
submit_branch = stored_submit_branch
5120
5176
given, in which case it is sent to a file.
5122
5178
Mail is sent using your preferred mail program. This should be transparent
5123
on Windows (it uses MAPI). On Linux, it requires the xdg-email utility.
5179
on Windows (it uses MAPI). On Unix, it requires the xdg-email utility.
5124
5180
If the preferred client can't be found (or used), your editor will be used.
5126
5182
To use a specific mail program, set the mail_client configuration option.
5297
5353
Option('delete',
5298
5354
help='Delete this tag rather than placing it.',
5301
help='Branch in which to place the tag.',
5356
custom_help('directory',
5357
help='Branch in which to place the tag.'),
5305
5358
Option('force',
5306
5359
help='Replace existing tags.',
5350
5403
_see_also = ['tag']
5351
5404
takes_options = [
5353
help='Branch whose tags should be displayed.',
5405
custom_help('directory',
5406
help='Branch whose tags should be displayed.'),
5357
5407
RegistryOption.from_kwargs('sort',
5358
5408
'Sort tags by different criteria.', title='Sorting',
5359
alpha='Sort tags lexicographically (default).',
5409
natural='Sort numeric substrings as numbers:'
5410
' suitable for version numbers. (default)',
5411
alpha='Sort tags lexicographically.',
5360
5412
time='Sort tags chronologically.',
5384
5436
# only show revisions between revid1 and revid2 (inclusive)
5385
5437
tags = [(tag, revid) for tag, revid in tags if
5386
5438
graph.is_between(revid, revid1, revid2)]
5439
if sort == 'natural':
5440
def natural_sort_key(tag):
5441
return [f(s) for f,s in
5442
zip(itertools.cycle((unicode.lower,int)),
5443
re.split('([0-9]+)', tag[0]))]
5444
tags.sort(key=natural_sort_key)
5445
elif sort == 'alpha':
5389
5447
elif sort == 'time':
5390
5448
timestamps = {}
5531
5589
takes_args = ['to_location?']
5532
takes_options = [Option('force',
5590
takes_options = ['directory',
5533
5592
help='Switch even if local commits will be lost.'),
5535
5594
Option('create-branch', short_name='b',
5540
5599
def run(self, to_location=None, force=False, create_branch=False,
5600
revision=None, directory=u'.'):
5542
5601
from bzrlib import switch
5602
tree_location = directory
5544
5603
revision = _get_one_revision('switch', revision)
5545
5604
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5546
5605
if to_location is None:
5547
5606
if revision is None:
5548
5607
raise errors.BzrCommandError('You must supply either a'
5549
5608
' revision or a location')
5609
to_location = tree_location
5552
5611
branch = control_dir.open_branch()
5553
5612
had_explicit_nick = branch.get_config().has_explicit_nickname()
5691
tree, file_list = tree_files(file_list, apply_view=False)
5750
tree, file_list = WorkingTree.open_containing_paths(file_list,
5692
5752
current_view, view_dict = tree.views.get_view_info()
5693
5753
if name is None:
5694
5754
name = current_view
5842
5903
_see_also = ['unshelve']
5844
5905
def run(self, revision=None, all=False, file_list=None, message=None,
5845
writer=None, list=False, destroy=False):
5906
writer=None, list=False, destroy=False, directory=u'.'):
5847
5908
return self.run_for_list()
5848
5909
from bzrlib.shelf_ui import Shelver
5850
5911
writer = bzrlib.option.diff_writer_registry.get()
5852
5913
shelver = Shelver.from_args(writer(sys.stdout), revision, all,
5853
file_list, message, destroy=destroy)
5914
file_list, message, destroy=destroy, directory=directory)
5885
5946
takes_args = ['shelf_id?']
5886
5947
takes_options = [
5887
5949
RegistryOption.from_kwargs(
5888
5950
'action', help="The action to perform.",
5889
5951
enum_switch=False, value_switches=True,
5898
5960
_see_also = ['shelve']
5900
def run(self, shelf_id=None, action='apply'):
5962
def run(self, shelf_id=None, action='apply', directory=u'.'):
5901
5963
from bzrlib.shelf_ui import Unshelver
5902
unshelver = Unshelver.from_args(shelf_id, action)
5964
unshelver = Unshelver.from_args(shelf_id, action, directory=directory)
5904
5966
unshelver.run()
5922
5984
To check what clean-tree will do, use --dry-run.
5924
takes_options = [Option('ignored', help='Delete all ignored files.'),
5986
takes_options = ['directory',
5987
Option('ignored', help='Delete all ignored files.'),
5925
5988
Option('detritus', help='Delete conflict files, merge'
5926
5989
' backups, and failed selftest dirs.'),
5927
5990
Option('unknown',
5930
5993
' deleting them.'),
5931
5994
Option('force', help='Do not prompt before deleting.')]
5932
5995
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5996
force=False, directory=u'.'):
5934
5997
from bzrlib.clean_tree import clean_tree
5935
5998
if not (unknown or ignored or detritus):
5939
clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
5940
dry_run=dry_run, no_prompt=force)
6002
clean_tree(directory, unknown=unknown, ignored=ignored,
6003
detritus=detritus, dry_run=dry_run, no_prompt=force)
5943
6006
class cmd_reference(Command):