481
475
self.print_revision(revisions, rev_id)
484
class cmd_dump_btree(Command):
485
__doc__ = """Dump the contents of a btree index file to stdout.
487
PATH is a btree index file, it can be any URL. This includes things like
488
.bzr/repository/pack-names, or .bzr/repository/indices/a34b3a...ca4a4.iix
490
By default, the tuples stored in the index file will be displayed. With
491
--raw, we will uncompress the pages, but otherwise display the raw bytes
495
# TODO: Do we want to dump the internal nodes as well?
496
# TODO: It would be nice to be able to dump the un-parsed information,
497
# rather than only going through iter_all_entries. However, this is
498
# good enough for a start
500
encoding_type = 'exact'
501
takes_args = ['path']
502
takes_options = [Option('raw', help='Write the uncompressed bytes out,'
503
' rather than the parsed tuples.'),
506
def run(self, path, raw=False):
507
dirname, basename = osutils.split(path)
508
t = transport.get_transport(dirname)
510
self._dump_raw_bytes(t, basename)
512
self._dump_entries(t, basename)
514
def _get_index_and_bytes(self, trans, basename):
515
"""Create a BTreeGraphIndex and raw bytes."""
516
bt = btree_index.BTreeGraphIndex(trans, basename, None)
517
bytes = trans.get_bytes(basename)
518
bt._file = BytesIO(bytes)
519
bt._size = len(bytes)
522
def _dump_raw_bytes(self, trans, basename):
525
# We need to parse at least the root node.
526
# This is because the first page of every row starts with an
527
# uncompressed header.
528
bt, bytes = self._get_index_and_bytes(trans, basename)
529
for page_idx, page_start in enumerate(range(0, len(bytes),
530
btree_index._PAGE_SIZE)):
531
page_end = min(page_start + btree_index._PAGE_SIZE, len(bytes))
532
page_bytes = bytes[page_start:page_end]
534
self.outf.write('Root node:\n')
535
header_end, data = bt._parse_header_from_bytes(page_bytes)
536
self.outf.write(page_bytes[:header_end])
538
self.outf.write('\nPage %d\n' % (page_idx,))
539
if len(page_bytes) == 0:
540
self.outf.write('(empty)\n');
542
decomp_bytes = zlib.decompress(page_bytes)
543
self.outf.write(decomp_bytes)
544
self.outf.write('\n')
546
def _dump_entries(self, trans, basename):
548
st = trans.stat(basename)
549
except errors.TransportNotPossible:
550
# We can't stat, so we'll fake it because we have to do the 'get()'
552
bt, _ = self._get_index_and_bytes(trans, basename)
554
bt = btree_index.BTreeGraphIndex(trans, basename, st.st_size)
555
for node in bt.iter_all_entries():
556
# Node is made up of:
557
# (index, key, value, [references])
561
refs_as_tuples = None
563
refs_as_tuples = static_tuple.as_tuples(refs)
564
as_tuple = (tuple(node[1]), node[2], refs_as_tuples)
565
self.outf.write('%s\n' % (as_tuple,))
568
478
class cmd_remove_tree(Command):
569
479
__doc__ = """Remove the working tree from a given branch/checkout.
935
858
takes_options = [
861
Option('include-root',
862
help='Include the entry for the root of the tree, if any.'),
939
help='List entries of a particular kind: file, directory, symlink.',
864
help='List entries of a particular kind: file, directory, '
942
868
takes_args = ['file*']
945
def run(self, revision=None, show_ids=False, kind=None, file_list=None):
871
def run(self, revision=None, show_ids=False, kind=None, include_root=False,
946
873
if kind and kind not in ['file', 'directory', 'symlink']:
947
raise errors.BzrCommandError(gettext('invalid kind %r specified') % (kind,))
874
raise errors.BzrCommandError(
875
gettext('invalid kind %r specified') % (kind,))
949
877
revision = _get_one_revision('inventory', revision)
950
878
work_tree, file_list = WorkingTree.open_containing_paths(file_list)
951
self.add_cleanup(work_tree.lock_read().unlock)
879
self.enter_context(work_tree.lock_read())
952
880
if revision is not None:
953
881
tree = revision.as_tree(work_tree.branch)
955
883
extra_trees = [work_tree]
956
self.add_cleanup(tree.lock_read().unlock)
884
self.enter_context(tree.lock_read())
961
self.add_cleanup(tree.lock_read().unlock)
889
self.enter_context(tree.lock_read())
962
890
if file_list is not None:
963
file_ids = tree.paths2ids(file_list, trees=extra_trees,
964
require_versioned=True)
891
paths = tree.find_related_paths_across_trees(
892
file_list, extra_trees, require_versioned=True)
965
893
# find_ids_across_trees may include some paths that don't
966
894
# exist in 'tree'.
967
entries = tree.iter_entries_by_dir(specific_file_ids=file_ids)
895
entries = tree.iter_entries_by_dir(specific_files=paths)
969
897
entries = tree.iter_entries_by_dir()
971
899
for path, entry in sorted(entries):
972
900
if kind and kind != entry.kind:
902
if path == "" and not include_root:
977
self.outf.write('%-50s %s\n' % (path, entry.file_id))
905
self.outf.write('%-50s %s\n' % (
906
path, entry.file_id.decode('utf-8')))
979
908
self.outf.write(path)
980
909
self.outf.write('\n')
1002
931
encoding_type = 'replace'
1004
933
def run(self, names_list):
1006
934
if names_list is None:
1008
936
if len(names_list) < 2:
1009
937
raise errors.BzrCommandError(gettext("missing file argument"))
1010
tree, rel_names = WorkingTree.open_containing_paths(names_list, canonicalize=False)
938
tree, rel_names = WorkingTree.open_containing_paths(
939
names_list, canonicalize=False)
1011
940
for file_name in rel_names[0:-1]:
1012
941
if file_name == '':
1013
raise errors.BzrCommandError(gettext("can not copy root of branch"))
1014
self.add_cleanup(tree.lock_tree_write().unlock)
942
raise errors.BzrCommandError(
943
gettext("can not copy root of branch"))
944
self.enter_context(tree.lock_tree_write())
1015
945
into_existing = osutils.isdir(names_list[-1])
1016
946
if not into_existing:
1018
948
(src, dst) = rel_names
1019
949
except IndexError:
1020
raise errors.BzrCommandError(gettext('to copy multiple files the'
1021
' destination must be a versioned'
950
raise errors.BzrCommandError(
951
gettext('to copy multiple files the'
952
' destination must be a versioned'
1023
954
pairs = [(src, dst)]
1025
pairs = [(n, osutils.joinpath([rel_names[-1], osutils.basename(n)]))
1026
for n in rel_names[:-1]]
957
(n, osutils.joinpath([rel_names[-1], osutils.basename(n)]))
958
for n in rel_names[:-1]]
1028
960
for src, dst in pairs:
1030
962
src_kind = tree.stored_kind(src)
1031
963
except errors.NoSuchFile:
1032
964
raise errors.BzrCommandError(
1033
gettext('Could not copy %s => %s: %s is not versioned.')
965
gettext('Could not copy %s => %s: %s is not versioned.')
1035
967
if src_kind is None:
1036
968
raise errors.BzrCommandError(
1037
gettext('Could not copy %s => %s . %s is not versioned\.'
969
gettext('Could not copy %s => %s . %s is not versioned\\.'
1039
971
if src_kind == 'directory':
1040
972
raise errors.BzrCommandError(
1041
973
gettext('Could not copy %s => %s . %s is a directory.'
1043
975
dst_parent = osutils.split(dst)[0]
1044
976
if dst_parent != '':
1046
978
dst_parent_kind = tree.stored_kind(dst_parent)
1047
979
except errors.NoSuchFile:
1048
980
raise errors.BzrCommandError(
1049
gettext('Could not copy %s => %s: %s is not versioned.')
1050
% (src, dst, dst_parent))
981
gettext('Could not copy %s => %s: %s is not versioned.')
982
% (src, dst, dst_parent))
1051
983
if dst_parent_kind != 'directory':
1052
984
raise errors.BzrCommandError(
1053
gettext('Could not copy to %s: %s is not a directory.')
1054
% (dst_parent, dst_parent))
985
gettext('Could not copy to %s: %s is not a directory.')
986
% (dst_parent, dst_parent))
1056
988
tree.copy_one(src, dst)
1374
1311
_see_also = ['pull', 'update', 'working-trees']
1375
1312
takes_options = ['remember', 'overwrite', 'verbose', 'revision',
1376
Option('create-prefix',
1377
help='Create the path leading up to the branch '
1378
'if it does not already exist.'),
1379
custom_help('directory',
1380
help='Branch to push from, '
1381
'rather than the one containing the working directory.'),
1382
Option('use-existing-dir',
1383
help='By default push will fail if the target'
1384
' directory exists, but does not already'
1385
' have a control directory. This flag will'
1386
' allow push to proceed.'),
1388
help='Create a stacked branch that references the public location '
1389
'of the parent branch.'),
1390
Option('stacked-on',
1391
help='Create a stacked branch that refers to another branch '
1392
'for the commit history. Only the work not present in the '
1393
'referenced branch is included in the branch created.',
1396
help='Refuse to push if there are uncommitted changes in'
1397
' the working tree, --no-strict disables the check.'),
1399
help="Don't populate the working tree, even for protocols"
1400
" that support it."),
1401
Option('overwrite-tags',
1402
help="Overwrite tags only."),
1313
Option('create-prefix',
1314
help='Create the path leading up to the branch '
1315
'if it does not already exist.'),
1316
custom_help('directory',
1317
help='Branch to push from, '
1318
'rather than the one containing the working directory.'),
1319
Option('use-existing-dir',
1320
help='By default push will fail if the target'
1321
' directory exists, but does not already'
1322
' have a control directory. This flag will'
1323
' allow push to proceed.'),
1325
help='Create a stacked branch that references the public location '
1326
'of the parent branch.'),
1327
Option('stacked-on',
1328
help='Create a stacked branch that refers to another branch '
1329
'for the commit history. Only the work not present in the '
1330
'referenced branch is included in the branch created.',
1333
help='Refuse to push if there are uncommitted changes in'
1334
' the working tree, --no-strict disables the check.'),
1336
help="Don't populate the working tree, even for protocols"
1337
" that support it."),
1338
Option('overwrite-tags',
1339
help="Overwrite tags only."),
1340
Option('lossy', help="Allow lossy push, i.e. dropping metadata "
1341
"that can't be represented in the target.")
1404
1343
takes_args = ['location?']
1405
1344
encoding_type = 'replace'
1407
1346
def run(self, location=None, remember=None, overwrite=False,
1408
create_prefix=False, verbose=False, revision=None,
1409
use_existing_dir=False, directory=None, stacked_on=None,
1410
stacked=False, strict=None, no_tree=False,
1411
overwrite_tags=False):
1347
create_prefix=False, verbose=False, revision=None,
1348
use_existing_dir=False, directory=None, stacked_on=None,
1349
stacked=False, strict=None, no_tree=False,
1350
overwrite_tags=False, lossy=False):
1351
from .location import location_to_url
1412
1352
from .push import _show_push_branch
1495
1437
_see_also = ['checkout']
1496
1438
takes_args = ['from_location', 'to_location?']
1497
1439
takes_options = ['revision',
1498
Option('hardlink', help='Hard-link working tree files where possible.'),
1499
Option('files-from', type=text_type,
1500
help="Get file contents from this tree."),
1502
help="Create a branch without a working-tree."),
1504
help="Switch the checkout in the current directory "
1505
"to the new branch."),
1507
help='Create a stacked branch referring to the source branch. '
1508
'The new branch will depend on the availability of the source '
1509
'branch for all operations.'),
1510
Option('standalone',
1511
help='Do not use a shared repository, even if available.'),
1512
Option('use-existing-dir',
1513
help='By default branch will fail if the target'
1514
' directory exists, but does not already'
1515
' have a control directory. This flag will'
1516
' allow branch to proceed.'),
1518
help="Bind new branch to from location."),
1441
'hardlink', help='Hard-link working tree files where possible.'),
1442
Option('files-from', type=str,
1443
help="Get file contents from this tree."),
1445
help="Create a branch without a working-tree."),
1447
help="Switch the checkout in the current directory "
1448
"to the new branch."),
1450
help='Create a stacked branch referring to the source branch. '
1451
'The new branch will depend on the availability of the source '
1452
'branch for all operations.'),
1453
Option('standalone',
1454
help='Do not use a shared repository, even if available.'),
1455
Option('use-existing-dir',
1456
help='By default branch will fail if the target'
1457
' directory exists, but does not already'
1458
' have a control directory. This flag will'
1459
' allow branch to proceed.'),
1461
help="Bind new branch to from location."),
1462
Option('no-recurse-nested',
1463
help='Do not recursively check out nested trees.'),
1521
1466
def run(self, from_location, to_location=None, revision=None,
1522
1467
hardlink=False, stacked=False, standalone=False, no_tree=False,
1523
1468
use_existing_dir=False, switch=False, bind=False,
1469
files_from=None, no_recurse_nested=False):
1525
1470
from breezy import switch as _mod_switch
1526
1471
accelerator_tree, br_from = controldir.ControlDir.open_tree_or_branch(
1473
if no_recurse_nested:
1528
1477
if not (hardlink or files_from):
1529
1478
# accelerator_tree is usually slower because you have to read N
1530
1479
# files (no readahead, lots of seeks, etc), but allow the user to
1931
1883
class cmd_remove(Command):
1932
1884
__doc__ = """Remove files or directories.
1934
This makes Bazaar stop tracking changes to the specified files. Bazaar will
1886
This makes Breezy stop tracking changes to the specified files. Breezy will
1935
1887
delete them if they can easily be recovered using revert otherwise they
1936
1888
will be backed up (adding an extension of the form .~#~). If no options or
1937
parameters are given Bazaar will scan for files that are being tracked by
1938
Bazaar but missing in your tree and stop tracking them for you.
1889
parameters are given Breezy will scan for files that are being tracked by
1890
Breezy but missing in your tree and stop tracking them for you.
1940
1892
takes_args = ['file*']
1941
1893
takes_options = ['verbose',
1942
Option('new', help='Only remove files that have never been committed.'),
1943
RegistryOption.from_kwargs('file-deletion-strategy',
1944
'The file deletion mode to be used.',
1945
title='Deletion Strategy', value_switches=True, enum_switch=False,
1946
safe='Backup changed files (default).',
1947
keep='Delete from brz but leave the working copy.',
1948
no_backup='Don\'t backup changed files.'),
1895
'new', help='Only remove files that have never been committed.'),
1896
RegistryOption.from_kwargs('file-deletion-strategy',
1897
'The file deletion mode to be used.',
1898
title='Deletion Strategy', value_switches=True, enum_switch=False,
1899
safe='Backup changed files (default).',
1900
keep='Delete from brz but leave the working copy.',
1901
no_backup='Don\'t backup changed files.'),
1950
1903
aliases = ['rm', 'del']
1951
1904
encoding_type = 'replace'
1953
1906
def run(self, file_list, verbose=False, new=False,
1954
file_deletion_strategy='safe'):
1907
file_deletion_strategy='safe'):
1956
1909
tree, file_list = WorkingTree.open_containing_paths(file_list)
1958
1911
if file_list is not None:
1959
1912
file_list = [f for f in file_list]
1961
self.add_cleanup(tree.lock_write().unlock)
1914
self.enter_context(tree.lock_write())
1962
1915
# Heuristics should probably all move into tree.remove_smart or
1965
1918
added = tree.changes_from(tree.basis_tree(),
1966
specific_files=file_list).added
1967
file_list = sorted([f[0] for f in added], reverse=True)
1919
specific_files=file_list).added
1920
file_list = sorted([f.path[1] for f in added], reverse=True)
1968
1921
if len(file_list) == 0:
1969
1922
raise errors.BzrCommandError(gettext('No matching files.'))
1970
1923
elif file_list is None:
2378
2297
_see_also = ['status']
2379
2298
takes_args = ['file*']
2380
2299
takes_options = [
2381
Option('diff-options', type=text_type,
2300
Option('diff-options', type=str,
2382
2301
help='Pass these options to the external diff program.'),
2383
Option('prefix', type=text_type,
2302
Option('prefix', type=str,
2384
2303
short_name='p',
2385
2304
help='Set prefixes added to old and new filenames, as '
2386
2305
'two values separated by a colon. (eg "old/:new/").'),
2388
help='Branch/tree to compare from.',
2307
help='Branch/tree to compare from.',
2392
help='Branch/tree to compare to.',
2311
help='Branch/tree to compare to.',
2397
2316
Option('using',
2398
help='Use this command to compare files.',
2317
help='Use this command to compare files.',
2401
2320
RegistryOption('format',
2403
help='Diff format to use.',
2404
lazy_registry=('breezy.diff', 'format_registry'),
2405
title='Diff format'),
2322
help='Diff format to use.',
2323
lazy_registry=('breezy.diff', 'format_registry'),
2324
title='Diff format'),
2406
2325
Option('context',
2407
help='How many lines of context to show.',
2326
help='How many lines of context to show.',
2329
RegistryOption.from_kwargs(
2331
help='Color mode to use.',
2332
title='Color Mode', value_switches=False, enum_switch=True,
2333
never='Never colorize output.',
2334
auto='Only colorize output if terminal supports it and STDOUT is a'
2336
always='Always colorize output (default).'),
2339
help=('Warn if trailing whitespace or spurious changes have been'
2411
2343
aliases = ['di', 'dif']
2412
2344
encoding_type = 'exact'
2414
2346
@display_command
2415
2347
def run(self, revision=None, file_list=None, diff_options=None,
2416
2348
prefix=None, old=None, new=None, using=None, format=None,
2349
context=None, color='never'):
2418
2350
from .diff import (get_trees_and_branches_to_diff_locked,
2421
2353
if prefix == u'0':
2422
2354
# diff -p0 format
2721
2663
takes_args = ['file*']
2722
2664
_see_also = ['log-formats', 'revisionspec']
2723
2665
takes_options = [
2725
help='Show from oldest to newest.'),
2727
custom_help('verbose',
2728
help='Show files changed in each revision.'),
2732
type=breezy.option._parse_revision_str,
2734
help='Show just the specified revision.'
2735
' See also "help revisionspec".'),
2737
RegistryOption('authors',
2738
'What names to list as authors - first, all or committer.',
2740
lazy_registry=('breezy.log', 'author_list_registry'),
2744
help='Number of levels to display - 0 for all, 1 for flat.',
2746
type=_parse_levels),
2748
help='Show revisions whose message matches this '
2749
'regular expression.',
2754
help='Limit the output to the first N revisions.',
2759
help='Show changes made in each revision as a patch.'),
2760
Option('include-merged',
2761
help='Show merged revisions like --levels 0 does.'),
2762
Option('include-merges', hidden=True,
2763
help='Historical alias for --include-merged.'),
2764
Option('omit-merges',
2765
help='Do not report commits with more than one parent.'),
2766
Option('exclude-common-ancestry',
2767
help='Display only the revisions that are not part'
2768
' of both ancestries (require -rX..Y).'
2770
Option('signatures',
2771
help='Show digital signature validity.'),
2774
help='Show revisions whose properties match this '
2777
ListOption('match-message',
2778
help='Show revisions whose message matches this '
2781
ListOption('match-committer',
2667
help='Show from oldest to newest.'),
2669
custom_help('verbose',
2670
help='Show files changed in each revision.'),
2674
type=breezy.option._parse_revision_str,
2676
help='Show just the specified revision.'
2677
' See also "help revisionspec".'),
2679
RegistryOption('authors',
2680
'What names to list as authors - first, all or committer.',
2683
'breezy.log', 'author_list_registry'),
2687
help='Number of levels to display - 0 for all, 1 for flat.',
2689
type=_parse_levels),
2691
help='Show revisions whose message matches this '
2692
'regular expression.',
2697
help='Limit the output to the first N revisions.',
2702
help='Show changes made in each revision as a patch.'),
2703
Option('include-merged',
2704
help='Show merged revisions like --levels 0 does.'),
2705
Option('include-merges', hidden=True,
2706
help='Historical alias for --include-merged.'),
2707
Option('omit-merges',
2708
help='Do not report commits with more than one parent.'),
2709
Option('exclude-common-ancestry',
2710
help='Display only the revisions that are not part'
2711
' of both ancestries (require -rX..Y).'
2713
Option('signatures',
2714
help='Show digital signature validity.'),
2717
help='Show revisions whose properties match this '
2720
ListOption('match-message',
2721
help='Show revisions whose message matches this '
2724
ListOption('match-committer',
2782
2725
help='Show revisions whose committer matches this '
2785
ListOption('match-author',
2728
ListOption('match-author',
2786
2729
help='Show revisions whose authors match this '
2789
ListOption('match-bugs',
2732
ListOption('match-bugs',
2790
2733
help='Show revisions whose bugs match this '
2794
2737
encoding_type = 'replace'
2796
2739
@display_command
3039
2983
_see_also = ['status', 'cat']
3040
2984
takes_args = ['path?']
3041
2985
takes_options = [
3044
Option('recursive', short_name='R',
3045
help='Recurse into subdirectories.'),
3047
help='Print paths relative to the root of the branch.'),
3048
Option('unknown', short_name='u',
3049
help='Print unknown files.'),
3050
Option('versioned', help='Print versioned files.',
3052
Option('ignored', short_name='i',
3053
help='Print ignored files.'),
3054
Option('kind', short_name='k',
3055
help='List entries of a particular kind: file, directory, symlink.',
2988
Option('recursive', short_name='R',
2989
help='Recurse into subdirectories.'),
2991
help='Print paths relative to the root of the branch.'),
2992
Option('unknown', short_name='u',
2993
help='Print unknown files.'),
2994
Option('versioned', help='Print versioned files.',
2996
Option('ignored', short_name='i',
2997
help='Print ignored files.'),
2998
Option('kind', short_name='k',
2999
help=('List entries of a particular kind: file, '
3000
'directory, symlink, tree-reference.'),
3061
3007
@display_command
3062
3008
def run(self, revision=None, verbose=False,
3063
3009
recursive=False, from_root=False,
3064
3010
unknown=False, versioned=False, ignored=False,
3065
3011
null=False, kind=None, show_ids=False, path=None, directory=None):
3067
if kind and kind not in ('file', 'directory', 'symlink'):
3013
if kind and kind not in ('file', 'directory', 'symlink', 'tree-reference'):
3068
3014
raise errors.BzrCommandError(gettext('invalid kind specified'))
3070
3016
if verbose and null:
3071
raise errors.BzrCommandError(gettext('Cannot set both --verbose and --null'))
3017
raise errors.BzrCommandError(
3018
gettext('Cannot set both --verbose and --null'))
3072
3019
all = not (unknown or versioned or ignored)
3074
selection = {'I':ignored, '?':unknown, 'V':versioned}
3021
selection = {'I': ignored, '?': unknown, 'V': versioned}
3076
3023
if path is None:
3080
3027
raise errors.BzrCommandError(gettext('cannot specify both --from-root'
3083
3030
tree, branch, relpath = \
3084
3031
_open_directory_or_containing_tree_or_branch(fs_path, directory)
3439
3409
filters=False, directory=None):
3440
3410
if revision is not None and len(revision) != 1:
3441
3411
raise errors.BzrCommandError(gettext("brz cat --revision takes exactly"
3442
" one revision specifier"))
3412
" one revision specifier"))
3443
3413
tree, branch, relpath = \
3444
3414
_open_directory_or_containing_tree_or_branch(filename, directory)
3445
self.add_cleanup(branch.lock_read().unlock)
3415
self.enter_context(branch.lock_read())
3446
3416
return self._run(tree, branch, relpath, filename, revision,
3447
3417
name_from_revision, filters)
3449
3419
def _run(self, tree, b, relpath, filename, revision, name_from_revision,
3451
3422
if tree is None:
3452
3423
tree = b.basis_tree()
3453
3424
rev_tree = _get_one_revision_tree('cat', revision, branch=b)
3454
self.add_cleanup(rev_tree.lock_read().unlock)
3456
old_file_id = rev_tree.path2id(relpath)
3458
# TODO: Split out this code to something that generically finds the
3459
# best id for a path across one or more trees; it's like
3460
# find_ids_across_trees but restricted to find just one. -- mbp
3425
self.enter_context(rev_tree.lock_read())
3462
3427
if name_from_revision:
3463
3428
# Try in revision if requested
3464
if old_file_id is None:
3429
if not rev_tree.is_versioned(relpath):
3465
3430
raise errors.BzrCommandError(gettext(
3466
3431
"{0!r} is not present in revision {1}").format(
3467
3432
filename, rev_tree.get_revision_id()))
3469
actual_file_id = old_file_id
3433
rev_tree_path = relpath
3471
cur_file_id = tree.path2id(relpath)
3472
if cur_file_id is not None and rev_tree.has_id(cur_file_id):
3473
actual_file_id = cur_file_id
3474
elif old_file_id is not None:
3475
actual_file_id = old_file_id
3477
raise errors.BzrCommandError(gettext(
3478
"{0!r} is not present in revision {1}").format(
3479
filename, rev_tree.get_revision_id()))
3436
rev_tree_path = _mod_tree.find_previous_path(
3437
tree, rev_tree, relpath)
3438
except errors.NoSuchFile:
3439
rev_tree_path = None
3441
if rev_tree_path is None:
3442
# Path didn't exist in working tree
3443
if not rev_tree.is_versioned(relpath):
3444
raise errors.BzrCommandError(gettext(
3445
"{0!r} is not present in revision {1}").format(
3446
filename, rev_tree.get_revision_id()))
3448
# Fall back to the same path in the basis tree, if present.
3449
rev_tree_path = relpath
3481
3452
from .filter_tree import ContentFilterTree
3482
filter_tree = ContentFilterTree(rev_tree,
3483
rev_tree._content_filter_stack)
3484
content = filter_tree.get_file_text(relpath, actual_file_id)
3453
filter_tree = ContentFilterTree(
3454
rev_tree, rev_tree._content_filter_stack)
3455
fileobj = filter_tree.get_file(rev_tree_path)
3486
content = rev_tree.get_file_text(relpath, actual_file_id)
3457
fileobj = rev_tree.get_file(rev_tree_path)
3458
shutil.copyfileobj(fileobj, self.outf)
3487
3459
self.cleanup_now()
3488
self.outf.write(content)
3491
3462
class cmd_local_time_offset(Command):
3492
3463
__doc__ = """Show the offset in seconds from GMT to local time."""
3494
3466
@display_command
3496
3468
self.outf.write("%s\n" % osutils.local_time_offset())
3500
3471
class cmd_commit(Command):
3501
3472
__doc__ = """Commit changes into a new revision.
3557
3528
_see_also = ['add', 'bugs', 'hooks', 'uncommit']
3558
3529
takes_args = ['selected*']
3559
3530
takes_options = [
3560
ListOption('exclude', type=text_type, short_name='x',
3561
help="Do not consider changes made to a given path."),
3562
Option('message', type=text_type,
3564
help="Description of the new revision."),
3567
help='Commit even if nothing has changed.'),
3568
Option('file', type=text_type,
3571
help='Take commit message from this file.'),
3573
help="Refuse to commit if there are unknown "
3574
"files in the working tree."),
3575
Option('commit-time', type=text_type,
3576
help="Manually set a commit time using commit date "
3577
"format, e.g. '2009-10-10 08:00:00 +0100'."),
3578
ListOption('fixes', type=text_type,
3579
help="Mark a bug as being fixed by this revision "
3580
"(see \"brz help bugs\")."),
3581
ListOption('author', type=text_type,
3582
help="Set the author's name, if it's different "
3583
"from the committer."),
3585
help="Perform a local commit in a bound "
3586
"branch. Local commits are not pushed to "
3587
"the master branch until a normal commit "
3590
Option('show-diff', short_name='p',
3591
help='When no message is supplied, show the diff along'
3592
' with the status summary in the message editor.'),
3594
help='When committing to a foreign version control '
3595
'system do not push data that can not be natively '
3532
'exclude', type=str, short_name='x',
3533
help="Do not consider changes made to a given path."),
3534
Option('message', type=str,
3536
help="Description of the new revision."),
3539
help='Commit even if nothing has changed.'),
3540
Option('file', type=str,
3543
help='Take commit message from this file.'),
3545
help="Refuse to commit if there are unknown "
3546
"files in the working tree."),
3547
Option('commit-time', type=str,
3548
help="Manually set a commit time using commit date "
3549
"format, e.g. '2009-10-10 08:00:00 +0100'."),
3552
help="Link to a related bug. (see \"brz help bugs\")."),
3555
help="Mark a bug as being fixed by this revision "
3556
"(see \"brz help bugs\")."),
3559
help="Set the author's name, if it's different "
3560
"from the committer."),
3562
help="Perform a local commit in a bound "
3563
"branch. Local commits are not pushed to "
3564
"the master branch until a normal commit "
3567
Option('show-diff', short_name='p',
3568
help='When no message is supplied, show the diff along'
3569
' with the status summary in the message editor.'),
3571
help='When committing to a foreign version control '
3572
'system do not push data that can not be natively '
3598
3574
aliases = ['ci', 'checkin']
3600
def _iter_bug_fix_urls(self, fixes, branch):
3601
default_bugtracker = None
3576
def _iter_bug_urls(self, bugs, branch, status):
3577
default_bugtracker = None
3602
3578
# Configure the properties for bug fixing attributes.
3603
for fixed_bug in fixes:
3604
tokens = fixed_bug.split(':')
3580
tokens = bug.split(':')
3605
3581
if len(tokens) == 1:
3606
3582
if default_bugtracker is None:
3607
3583
branch_config = branch.get_config_stack()
4478
4467
change_reporter = delta._ChangeReporter(
4479
4468
unversioned_filter=tree.is_ignored, view_info=view_info)
4480
4469
pb = ui.ui_factory.nested_progress_bar()
4481
self.add_cleanup(pb.finished)
4482
self.add_cleanup(tree.lock_write().unlock)
4470
self.enter_context(pb)
4471
self.enter_context(tree.lock_write())
4483
4472
if location is not None:
4485
mergeable = bundle.read_mergeable_from_url(location,
4486
possible_transports=possible_transports)
4474
mergeable = _mod_mergeable.read_mergeable_from_url(
4475
location, possible_transports=possible_transports)
4487
4476
except errors.NotABundle:
4488
4477
mergeable = None
4490
4479
if uncommitted:
4491
4480
raise errors.BzrCommandError(gettext('Cannot use --uncommitted'
4492
' with bundles or merge directives.'))
4481
' with bundles or merge directives.'))
4494
4483
if revision is not None:
4495
4484
raise errors.BzrCommandError(gettext(
4496
4485
'Cannot use -r with merge directives or bundles'))
4497
4486
merger, verified = _mod_merge.Merger.from_mergeable(tree,
4500
4489
if merger is None and uncommitted:
4501
4490
if revision is not None and len(revision) > 0:
4502
4491
raise errors.BzrCommandError(gettext('Cannot use --uncommitted and'
4503
' --revision at the same time.'))
4492
' --revision at the same time.'))
4504
4493
merger = self.get_merger_from_uncommitted(tree, location, None)
4505
4494
allow_pending = False
4507
4496
if merger is None:
4508
4497
merger, allow_pending = self._get_merger_from_branch(tree,
4509
location, revision, remember, possible_transports, None)
4498
location, revision, remember, possible_transports, None)
4511
4500
merger.merge_type = merge_type
4512
4501
merger.reprocess = reprocess
4513
4502
merger.show_base = show_base
4514
4503
self.sanity_check_merger(merger)
4515
4504
if (merger.base_rev_id == merger.other_rev_id and
4516
merger.other_rev_id is not None):
4505
merger.other_rev_id is not None):
4517
4506
# check if location is a nonexistent file (and not a branch) to
4518
4507
# disambiguate the 'Nothing to do'
4519
4508
if merger.interesting_files:
4520
4509
if not merger.other_tree.has_filename(
4521
merger.interesting_files[0]):
4510
merger.interesting_files[0]):
4522
4511
note(gettext("merger: ") + str(merger))
4523
4512
raise errors.PathsDoNotExist([location])
4524
4513
note(gettext('Nothing to do.'))
4526
4515
if pull and not preview:
4527
4516
if merger.interesting_files is not None:
4528
raise errors.BzrCommandError(gettext('Cannot pull individual files'))
4517
raise errors.BzrCommandError(
4518
gettext('Cannot pull individual files'))
4529
4519
if (merger.base_rev_id == tree.last_revision()):
4530
4520
result = tree.pull(merger.other_branch, False,
4531
4521
merger.other_rev_id)
4757
4757
if merge_type is None:
4758
4758
merge_type = _mod_merge.Merge3Merger
4759
4759
tree, file_list = WorkingTree.open_containing_paths(file_list)
4760
self.add_cleanup(tree.lock_write().unlock)
4760
self.enter_context(tree.lock_write())
4761
4761
parents = tree.get_parent_ids()
4762
4762
if len(parents) != 2:
4763
raise errors.BzrCommandError(gettext("Sorry, remerge only works after normal"
4764
" merges. Not cherrypicking or"
4766
repository = tree.branch.repository
4767
interesting_ids = None
4763
raise errors.BzrCommandError(
4764
gettext("Sorry, remerge only works after normal"
4765
" merges. Not cherrypicking or multi-merges."))
4766
interesting_files = None
4768
4767
new_conflicts = []
4769
4768
conflicts = tree.conflicts()
4770
4769
if file_list is not None:
4771
interesting_ids = set()
4770
interesting_files = set()
4772
4771
for filename in file_list:
4773
file_id = tree.path2id(filename)
4772
if not tree.is_versioned(filename):
4775
4773
raise errors.NotVersionedError(filename)
4776
interesting_ids.add(file_id)
4777
if tree.kind(filename, file_id) != "directory":
4774
interesting_files.add(filename)
4775
if tree.kind(filename) != "directory":
4780
# FIXME: Support nested trees
4781
for name, ie in tree.root_inventory.iter_entries(file_id):
4782
interesting_ids.add(ie.file_id)
4778
for path, ie in tree.iter_entries_by_dir(
4779
specific_files=[filename]):
4780
interesting_files.add(path)
4783
4781
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
4785
4783
# Remerge only supports resolving contents conflicts
4786
4784
allowed_conflicts = ('text conflict', 'contents conflict')
4787
4785
restore_files = [c.path for c in conflicts
4788
4786
if c.typestring in allowed_conflicts]
4789
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
4787
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_files)
4790
4788
tree.set_conflicts(ConflictList(new_conflicts))
4791
4789
if file_list is not None:
4792
4790
restore_files = file_list
5253
5254
wt, branch, relpath = \
5254
5255
_open_directory_or_containing_tree_or_branch(filename, directory)
5255
5256
if wt is not None:
5256
self.add_cleanup(wt.lock_read().unlock)
5257
self.enter_context(wt.lock_read())
5258
self.add_cleanup(branch.lock_read().unlock)
5259
self.enter_context(branch.lock_read())
5259
5260
tree = _get_one_revision_tree('annotate', revision, branch=branch)
5260
self.add_cleanup(tree.lock_read().unlock)
5261
if wt is not None and revision is None:
5262
file_id = wt.path2id(relpath)
5264
file_id = tree.path2id(relpath)
5266
raise errors.NotVersionedError(filename)
5267
if wt is not None and revision is None:
5261
self.enter_context(tree.lock_read())
5262
if wt is not None and revision is None:
5263
if not wt.is_versioned(relpath):
5264
raise errors.NotVersionedError(relpath)
5268
5265
# If there is a tree and we're not annotating historical
5269
5266
# versions, annotate the working tree's content.
5270
5267
annotate_file_tree(wt, relpath, self.outf, long, all,
5271
show_ids=show_ids, file_id=file_id)
5270
if not tree.is_versioned(relpath):
5271
raise errors.NotVersionedError(relpath)
5273
5272
annotate_file_tree(tree, relpath, self.outf, long, all,
5274
show_ids=show_ids, branch=branch, file_id=file_id)
5273
show_ids=show_ids, branch=branch)
5277
5276
class cmd_re_sign(Command):
5278
5277
__doc__ = """Create a digital signature for an existing revision."""
5279
5278
# TODO be able to replace existing ones.
5281
hidden = True # is this right ?
5280
hidden = True # is this right ?
5282
5281
takes_args = ['revision_id*']
5283
5282
takes_options = ['directory', 'revision']
5285
5284
def run(self, revision_id_list=None, revision=None, directory=u'.'):
5286
5285
if revision_id_list is not None and revision is not None:
5287
raise errors.BzrCommandError(gettext('You can only supply one of revision_id or --revision'))
5286
raise errors.BzrCommandError(
5287
gettext('You can only supply one of revision_id or --revision'))
5288
5288
if revision_id_list is None and revision is None:
5289
raise errors.BzrCommandError(gettext('You must supply either --revision or a revision_id'))
5289
raise errors.BzrCommandError(
5290
gettext('You must supply either --revision or a revision_id'))
5290
5291
b = WorkingTree.open_containing(directory)[0].branch
5291
self.add_cleanup(b.lock_write().unlock)
5292
self.enter_context(b.lock_write())
5292
5293
return self._run(b, revision_id_list, revision)
5294
5295
def _run(self, b, revision_id_list, revision):
5296
from .repository import WriteGroup
5296
5297
gpg_strategy = gpg.GPGStrategy(b.get_config_stack())
5297
5298
if revision_id_list is not None:
5298
b.repository.start_write_group()
5299
with WriteGroup(b.repository):
5300
5300
for revision_id in revision_id_list:
5301
5301
revision_id = cache_utf8.encode(revision_id)
5302
5302
b.repository.sign_revision(revision_id, gpg_strategy)
5304
b.repository.abort_write_group()
5307
b.repository.commit_write_group()
5308
5303
elif revision is not None:
5309
5304
if len(revision) == 1:
5310
5305
revno, rev_id = revision[0].in_history(b)
5311
b.repository.start_write_group()
5306
with WriteGroup(b.repository):
5313
5307
b.repository.sign_revision(rev_id, gpg_strategy)
5315
b.repository.abort_write_group()
5318
b.repository.commit_write_group()
5319
5308
elif len(revision) == 2:
5320
5309
# are they both on rh- if so we can walk between them
5321
5310
# might be nice to have a range helper for arbitrary
6317
6307
except errors.NotBranchError:
6319
6309
had_explicit_nick = False
6311
possible_transports.append(branch.user_transport)
6320
6312
if create_branch:
6321
6313
if branch is None:
6322
6314
raise errors.BzrCommandError(
6323
6315
gettext('cannot create branch without source branch'))
6324
to_location = lookup_new_sibling_branch(control_dir, to_location,
6325
possible_transports=possible_transports)
6326
to_branch = branch.controldir.sprout(to_location,
6327
possible_transports=possible_transports,
6328
source_branch=branch).open_branch()
6316
to_location = lookup_new_sibling_branch(
6317
control_dir, to_location,
6318
possible_transports=possible_transports)
6319
if revision is not None:
6320
revision = revision.as_revision_id(branch)
6321
to_branch = branch.controldir.sprout(
6323
possible_transports=possible_transports,
6324
revision_id=revision,
6325
source_branch=branch).open_branch()
6331
to_branch = Branch.open(to_location,
6332
possible_transports=possible_transports)
6328
to_branch = Branch.open(
6329
to_location, possible_transports=possible_transports)
6333
6330
except errors.NotBranchError:
6334
to_branch = open_sibling_branch(control_dir, to_location,
6331
to_branch = open_sibling_branch(
6332
control_dir, to_location,
6335
6333
possible_transports=possible_transports)
6336
if revision is not None:
6337
revision = revision.as_revision_id(to_branch)
6338
switch.switch(control_dir, to_branch, force, revision_id=revision,
6339
store_uncommitted=store)
6334
if revision is not None:
6335
revision = revision.as_revision_id(to_branch)
6336
possible_transports.append(to_branch.user_transport)
6338
switch.switch(control_dir, to_branch, force, revision_id=revision,
6339
store_uncommitted=store,
6340
possible_transports=possible_transports)
6341
except controldir.BranchReferenceLoop:
6342
raise errors.BzrCommandError(
6343
gettext('switching would create a branch reference loop. '
6344
'Use the "bzr up" command to switch to a '
6345
'different revision.'))
6340
6346
if had_explicit_nick:
6341
branch = control_dir.open_branch() #get the new branch!
6347
branch = control_dir.open_branch() # get the new branch!
6342
6348
branch.nick = to_branch.nick
6343
note(gettext('Switched to branch: %s'),
6344
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
6350
if to_branch.controldir.control_url != control_dir.control_url:
6351
note(gettext('Switched to branch %s at %s'),
6352
to_branch.name, urlutils.unescape_for_display(to_branch.base, 'utf-8'))
6354
note(gettext('Switched to branch %s'), to_branch.name)
6356
note(gettext('Switched to branch at %s'),
6357
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
6348
6360
class cmd_view(Command):
6725
6744
takes_args = ['path?', 'location?']
6747
Option('force-unversioned',
6748
help='Set reference even if path is not versioned.'),
6727
def run(self, path=None, location=None):
6729
if path is not None:
6731
tree, branch, relpath =(
6732
controldir.ControlDir.open_containing_tree_or_branch(branchdir))
6733
if path is not None:
6751
def run(self, path=None, directory='.', location=None, force_unversioned=False):
6752
tree, branch, relpath = (
6753
controldir.ControlDir.open_containing_tree_or_branch(directory))
6735
6754
if tree is None:
6736
6755
tree = branch.basis_tree()
6737
6756
if path is None:
6738
info = viewitems(branch._get_all_reference_info())
6739
self._display_reference_info(tree, branch, info)
6757
with tree.lock_read():
6759
(path, tree.get_reference_info(path, branch))
6760
for path in tree.iter_references()]
6761
self._display_reference_info(tree, branch, info)
6741
file_id = tree.path2id(path)
6763
if not tree.is_versioned(path) and not force_unversioned:
6743
6764
raise errors.NotVersionedError(path)
6744
6765
if location is None:
6745
info = [(file_id, branch.get_reference_info(file_id))]
6766
info = [(path, tree.get_reference_info(path, branch))]
6746
6767
self._display_reference_info(tree, branch, info)
6748
branch.set_reference_info(file_id, path, location)
6769
tree.set_reference_info(path, location)
6750
6771
def _display_reference_info(self, tree, branch, info):
6752
for file_id, (path, location) in info:
6754
path = tree.id2path(file_id)
6755
except errors.NoSuchId:
6773
for path, location in info:
6757
6774
ref_list.append((path, location))
6758
6775
for path, location in sorted(ref_list):
6759
6776
self.outf.write('%s %s\n' % (path, location))
6838
6848
if len(installed) > 0:
6839
6849
self.outf.write("Installed:\n")
6840
6850
for rev in installed:
6841
self.outf.write(rev + "\n")
6851
self.outf.write(rev.decode('utf-8') + "\n")
6842
6852
if len(failed) > 0:
6843
6853
self.outf.write("Still missing:\n")
6844
6854
for rev in failed:
6845
self.outf.write(rev + "\n")
6855
self.outf.write(rev.decode('utf-8') + "\n")
6846
6856
if not no_fix and len(installed) > 0:
6847
6857
cmd_reconcile().run(".")
6860
class cmd_grep(Command):
6861
"""Print lines matching PATTERN for specified files and revisions.
6863
This command searches the specified files and revisions for a given
6864
pattern. The pattern is specified as a Python regular expressions[1].
6866
If the file name is not specified, the revisions starting with the
6867
current directory are searched recursively. If the revision number is
6868
not specified, the working copy is searched. To search the last committed
6869
revision, use the '-r -1' or '-r last:1' option.
6871
Unversioned files are not searched unless explicitly specified on the
6872
command line. Unversioned directores are not searched.
6874
When searching a pattern, the output is shown in the 'filepath:string'
6875
format. If a revision is explicitly searched, the output is shown as
6876
'filepath~N:string', where N is the revision number.
6878
--include and --exclude options can be used to search only (or exclude
6879
from search) files with base name matches the specified Unix style GLOB
6880
pattern. The GLOB pattern an use *, ?, and [...] as wildcards, and \\
6881
to quote wildcard or backslash character literally. Note that the glob
6882
pattern is not a regular expression.
6884
[1] http://docs.python.org/library/re.html#regular-expression-syntax
6887
encoding_type = 'replace'
6888
takes_args = ['pattern', 'path*']
6892
Option('color', type=str, argname='when',
6893
help='Show match in color. WHEN is never, always or auto.'),
6894
Option('diff', short_name='p',
6895
help='Grep for pattern in changeset for each revision.'),
6896
ListOption('exclude', type=str, argname='glob', short_name='X',
6897
help="Skip files whose base name matches GLOB."),
6898
ListOption('include', type=str, argname='glob', short_name='I',
6899
help="Search only files whose base name matches GLOB."),
6900
Option('files-with-matches', short_name='l',
6901
help='Print only the name of each input file in '
6902
'which PATTERN is found.'),
6903
Option('files-without-match', short_name='L',
6904
help='Print only the name of each input file in '
6905
'which PATTERN is not found.'),
6906
Option('fixed-string', short_name='F',
6907
help='Interpret PATTERN is a single fixed string (not regex).'),
6909
help='Search for pattern starting from the root of the branch. '
6910
'(implies --recursive)'),
6911
Option('ignore-case', short_name='i',
6912
help='Ignore case distinctions while matching.'),
6914
help='Number of levels to display - 0 for all, 1 for collapsed '
6917
type=_parse_levels),
6918
Option('line-number', short_name='n',
6919
help='Show 1-based line number.'),
6920
Option('no-recursive',
6921
help="Don't recurse into subdirectories. (default is --recursive)"),
6922
Option('null', short_name='Z',
6923
help='Write an ASCII NUL (\\0) separator '
6924
'between output lines rather than a newline.'),
6928
def run(self, verbose=False, ignore_case=False, no_recursive=False,
6929
from_root=False, null=False, levels=None, line_number=False,
6930
path_list=None, revision=None, pattern=None, include=None,
6931
exclude=None, fixed_string=False, files_with_matches=False,
6932
files_without_match=False, color=None, diff=False):
6933
from breezy import _termcolor
6936
if path_list is None:
6940
raise errors.BzrCommandError(
6941
'cannot specify both --from-root and PATH.')
6943
if files_with_matches and files_without_match:
6944
raise errors.BzrCommandError(
6945
'cannot specify both '
6946
'-l/--files-with-matches and -L/--files-without-matches.')
6948
global_config = _mod_config.GlobalConfig()
6951
color = global_config.get_user_option('grep_color')
6956
if color not in ['always', 'never', 'auto']:
6957
raise errors.BzrCommandError('Valid values for --color are '
6958
'"always", "never" or "auto".')
6964
if revision is not None or levels == 0:
6965
# print revision numbers as we may be showing multiple revisions
6972
if not ignore_case and grep.is_fixed_string(pattern):
6973
# if the pattern isalnum, implicitly use to -F for faster grep
6975
elif ignore_case and fixed_string:
6976
# GZ 2010-06-02: Fall back to regexp rather than lowercasing
6977
# pattern and text which will cause pain later
6978
fixed_string = False
6979
pattern = re.escape(pattern)
6982
re_flags = re.MULTILINE
6984
re_flags |= re.IGNORECASE
6986
if not fixed_string:
6987
patternc = grep.compile_pattern(
6988
pattern.encode(grep._user_encoding), re_flags)
6990
if color == 'always':
6992
elif color == 'never':
6994
elif color == 'auto':
6995
show_color = _termcolor.allow_color()
6997
opts = grep.GrepOptions()
6999
opts.verbose = verbose
7000
opts.ignore_case = ignore_case
7001
opts.no_recursive = no_recursive
7002
opts.from_root = from_root
7004
opts.levels = levels
7005
opts.line_number = line_number
7006
opts.path_list = path_list
7007
opts.revision = revision
7008
opts.pattern = pattern
7009
opts.include = include
7010
opts.exclude = exclude
7011
opts.fixed_string = fixed_string
7012
opts.files_with_matches = files_with_matches
7013
opts.files_without_match = files_without_match
7017
opts.eol_marker = eol_marker
7018
opts.print_revno = print_revno
7019
opts.patternc = patternc
7020
opts.recursive = not no_recursive
7021
opts.fixed_string = fixed_string
7022
opts.outf = self.outf
7023
opts.show_color = show_color
7027
# files_with_matches, files_without_match
7028
# levels(?), line_number, from_root
7030
# These are silently ignored.
7031
grep.grep_diff(opts)
7032
elif revision is None:
7033
grep.workingtree_grep(opts)
7035
grep.versioned_grep(opts)
7038
class cmd_patch(Command):
7039
"""Apply a named patch to the current tree.
7043
takes_args = ['filename?']
7044
takes_options = [Option('strip', type=int, short_name='p',
7045
help=("Strip the smallest prefix containing num "
7046
"leading slashes from filenames.")),
7047
Option('silent', help='Suppress chatter.')]
7049
def run(self, filename=None, strip=None, silent=False):
7050
from .patch import patch_tree
7051
wt = WorkingTree.open_containing('.')[0]
7055
if filename is None:
7056
my_file = getattr(sys.stdin, 'buffer', sys.stdin)
7058
my_file = open(filename, 'rb')
7059
patches = [my_file.read()]
7060
return patch_tree(wt, patches, strip, quiet=is_quiet(), out=self.outf)
7063
class cmd_resolve_location(Command):
7064
__doc__ = """Expand a location to a full URL.
7067
Look up a Launchpad URL.
7069
brz resolve-location lp:brz
7071
takes_args = ['location']
7074
def run(self, location):
7075
from .location import location_to_url
7076
url = location_to_url(location)
7077
display_url = urlutils.unescape_for_display(url, self.outf.encoding)
7078
self.outf.write('%s\n' % display_url)
6850
7081
def _register_lazy_builtins():
6851
7082
# register lazy builtins from other modules; called at startup and should
6852
7083
# be only called once.
6853
7084
for (name, aliases, module_name) in [
6854
('cmd_bisect', [], 'breezy.bisect'),
6855
('cmd_bundle_info', [], 'breezy.bundle.commands'),
6856
('cmd_config', [], 'breezy.config'),
6857
('cmd_dpush', [], 'breezy.foreign'),
6858
('cmd_version_info', [], 'breezy.cmd_version_info'),
6859
('cmd_resolve', ['resolved'], 'breezy.conflicts'),
6860
('cmd_conflicts', [], 'breezy.conflicts'),
6861
('cmd_ping', [], 'breezy.bzr.smart.ping'),
6862
('cmd_sign_my_commits', [], 'breezy.commit_signature_commands'),
6863
('cmd_verify_signatures', [], 'breezy.commit_signature_commands'),
6864
('cmd_test_script', [], 'breezy.cmd_test_script'),
7085
('cmd_bisect', [], 'breezy.bisect'),
7086
('cmd_bundle_info', [], 'breezy.bzr.bundle.commands'),
7087
('cmd_config', [], 'breezy.config'),
7088
('cmd_dump_btree', [], 'breezy.bzr.debug_commands'),
7089
('cmd_file_id', [], 'breezy.bzr.debug_commands'),
7090
('cmd_file_path', [], 'breezy.bzr.debug_commands'),
7091
('cmd_version_info', [], 'breezy.cmd_version_info'),
7092
('cmd_resolve', ['resolved'], 'breezy.conflicts'),
7093
('cmd_conflicts', [], 'breezy.conflicts'),
7094
('cmd_ping', [], 'breezy.bzr.smart.ping'),
7095
('cmd_sign_my_commits', [], 'breezy.commit_signature_commands'),
7096
('cmd_verify_signatures', [], 'breezy.commit_signature_commands'),
7097
('cmd_test_script', [], 'breezy.cmd_test_script'),
6866
7099
builtin_command_registry.register_lazy(name, aliases, module_name)