939
915
encoding_type = 'replace'
941
917
def run(self, names_list):
942
919
if names_list is None:
944
921
if len(names_list) < 2:
945
922
raise errors.BzrCommandError(gettext("missing file argument"))
946
tree, rel_names = WorkingTree.open_containing_paths(
947
names_list, canonicalize=False)
923
tree, rel_names = WorkingTree.open_containing_paths(names_list, canonicalize=False)
948
924
for file_name in rel_names[0:-1]:
949
925
if file_name == '':
950
raise errors.BzrCommandError(
951
gettext("can not copy root of branch"))
952
self.enter_context(tree.lock_tree_write())
926
raise errors.BzrCommandError(gettext("can not copy root of branch"))
927
self.add_cleanup(tree.lock_tree_write().unlock)
953
928
into_existing = osutils.isdir(names_list[-1])
954
929
if not into_existing:
956
931
(src, dst) = rel_names
957
932
except IndexError:
958
raise errors.BzrCommandError(
959
gettext('to copy multiple files the'
960
' destination must be a versioned'
933
raise errors.BzrCommandError(gettext('to copy multiple files the'
934
' destination must be a versioned'
962
936
pairs = [(src, dst)]
965
(n, osutils.joinpath([rel_names[-1], osutils.basename(n)]))
966
for n in rel_names[:-1]]
938
pairs = [(n, osutils.joinpath([rel_names[-1], osutils.basename(n)]))
939
for n in rel_names[:-1]]
968
941
for src, dst in pairs:
970
943
src_kind = tree.stored_kind(src)
971
944
except errors.NoSuchFile:
972
945
raise errors.BzrCommandError(
973
gettext('Could not copy %s => %s: %s is not versioned.')
946
gettext('Could not copy %s => %s: %s is not versioned.')
975
948
if src_kind is None:
976
949
raise errors.BzrCommandError(
977
gettext('Could not copy %s => %s . %s is not versioned\\.'
950
gettext('Could not copy %s => %s . %s is not versioned\.'
979
952
if src_kind == 'directory':
980
953
raise errors.BzrCommandError(
981
954
gettext('Could not copy %s => %s . %s is a directory.'
983
956
dst_parent = osutils.split(dst)[0]
984
957
if dst_parent != '':
986
959
dst_parent_kind = tree.stored_kind(dst_parent)
987
960
except errors.NoSuchFile:
988
961
raise errors.BzrCommandError(
989
gettext('Could not copy %s => %s: %s is not versioned.')
990
% (src, dst, dst_parent))
962
gettext('Could not copy %s => %s: %s is not versioned.')
963
% (src, dst, dst_parent))
991
964
if dst_parent_kind != 'directory':
992
965
raise errors.BzrCommandError(
993
gettext('Could not copy to %s: %s is not a directory.')
994
% (dst_parent, dst_parent))
966
gettext('Could not copy to %s: %s is not a directory.')
967
% (dst_parent, dst_parent))
996
969
tree.copy_one(src, dst)
1319
1287
_see_also = ['pull', 'update', 'working-trees']
1320
1288
takes_options = ['remember', 'overwrite', 'verbose', 'revision',
1321
Option('create-prefix',
1322
help='Create the path leading up to the branch '
1323
'if it does not already exist.'),
1324
custom_help('directory',
1325
help='Branch to push from, '
1326
'rather than the one containing the working directory.'),
1327
Option('use-existing-dir',
1328
help='By default push will fail if the target'
1329
' directory exists, but does not already'
1330
' have a control directory. This flag will'
1331
' allow push to proceed.'),
1333
help='Create a stacked branch that references the public location '
1334
'of the parent branch.'),
1335
Option('stacked-on',
1336
help='Create a stacked branch that refers to another branch '
1337
'for the commit history. Only the work not present in the '
1338
'referenced branch is included in the branch created.',
1341
help='Refuse to push if there are uncommitted changes in'
1342
' the working tree, --no-strict disables the check.'),
1344
help="Don't populate the working tree, even for protocols"
1345
" that support it."),
1346
Option('overwrite-tags',
1347
help="Overwrite tags only."),
1348
Option('lossy', help="Allow lossy push, i.e. dropping metadata "
1349
"that can't be represented in the target.")
1289
Option('create-prefix',
1290
help='Create the path leading up to the branch '
1291
'if it does not already exist.'),
1292
custom_help('directory',
1293
help='Branch to push from, '
1294
'rather than the one containing the working directory.'),
1295
Option('use-existing-dir',
1296
help='By default push will fail if the target'
1297
' directory exists, but does not already'
1298
' have a control directory. This flag will'
1299
' allow push to proceed.'),
1301
help='Create a stacked branch that references the public location '
1302
'of the parent branch.'),
1303
Option('stacked-on',
1304
help='Create a stacked branch that refers to another branch '
1305
'for the commit history. Only the work not present in the '
1306
'referenced branch is included in the branch created.',
1309
help='Refuse to push if there are uncommitted changes in'
1310
' the working tree, --no-strict disables the check.'),
1312
help="Don't populate the working tree, even for protocols"
1313
" that support it."),
1314
Option('overwrite-tags',
1315
help="Overwrite tags only."),
1316
Option('lossy', help="Allow lossy push, i.e. dropping metadata "
1317
"that can't be represented in the target.")
1351
1319
takes_args = ['location?']
1352
1320
encoding_type = 'replace'
1354
1322
def run(self, location=None, remember=None, overwrite=False,
1355
create_prefix=False, verbose=False, revision=None,
1356
use_existing_dir=False, directory=None, stacked_on=None,
1357
stacked=False, strict=None, no_tree=False,
1358
overwrite_tags=False, lossy=False):
1359
from .location import location_to_url
1323
create_prefix=False, verbose=False, revision=None,
1324
use_existing_dir=False, directory=None, stacked_on=None,
1325
stacked=False, strict=None, no_tree=False,
1326
overwrite_tags=False, lossy=False):
1360
1327
from .push import _show_push_branch
1442
1408
parameter, as in "branch foo/bar -r 5".
1446
1411
_see_also = ['checkout']
1447
1412
takes_args = ['from_location', 'to_location?']
1448
1413
takes_options = ['revision',
1450
'hardlink', help='Hard-link working tree files where possible.'),
1451
Option('files-from', type=text_type,
1452
help="Get file contents from this tree."),
1454
help="Create a branch without a working-tree."),
1456
help="Switch the checkout in the current directory "
1457
"to the new branch."),
1459
help='Create a stacked branch referring to the source branch. '
1460
'The new branch will depend on the availability of the source '
1461
'branch for all operations.'),
1462
Option('standalone',
1463
help='Do not use a shared repository, even if available.'),
1464
Option('use-existing-dir',
1465
help='By default branch will fail if the target'
1466
' directory exists, but does not already'
1467
' have a control directory. This flag will'
1468
' allow branch to proceed.'),
1470
help="Bind new branch to from location."),
1471
Option('no-recurse-nested',
1472
help='Do not recursively check out nested trees.'),
1473
Option('colocated-branch', short_name='b',
1474
type=str, help='Name of colocated branch to sprout.'),
1414
Option('hardlink', help='Hard-link working tree files where possible.'),
1415
Option('files-from', type=text_type,
1416
help="Get file contents from this tree."),
1418
help="Create a branch without a working-tree."),
1420
help="Switch the checkout in the current directory "
1421
"to the new branch."),
1423
help='Create a stacked branch referring to the source branch. '
1424
'The new branch will depend on the availability of the source '
1425
'branch for all operations.'),
1426
Option('standalone',
1427
help='Do not use a shared repository, even if available.'),
1428
Option('use-existing-dir',
1429
help='By default branch will fail if the target'
1430
' directory exists, but does not already'
1431
' have a control directory. This flag will'
1432
' allow branch to proceed.'),
1434
help="Bind new branch to from location."),
1477
1437
def run(self, from_location, to_location=None, revision=None,
1478
1438
hardlink=False, stacked=False, standalone=False, no_tree=False,
1479
1439
use_existing_dir=False, switch=False, bind=False,
1480
files_from=None, no_recurse_nested=False, colocated_branch=None):
1481
1441
from breezy import switch as _mod_switch
1482
1442
accelerator_tree, br_from = controldir.ControlDir.open_tree_or_branch(
1483
from_location, name=colocated_branch)
1484
if no_recurse_nested:
1488
1444
if not (hardlink or files_from):
1489
1445
# accelerator_tree is usually slower because you have to read N
1490
1446
# files (no readahead, lots of seeks, etc), but allow the user to
1927
1847
class cmd_remove(Command):
1928
1848
__doc__ = """Remove files or directories.
1930
This makes Breezy stop tracking changes to the specified files. Breezy will
1850
This makes Bazaar stop tracking changes to the specified files. Bazaar will
1931
1851
delete them if they can easily be recovered using revert otherwise they
1932
1852
will be backed up (adding an extension of the form .~#~). If no options or
1933
parameters are given Breezy will scan for files that are being tracked by
1934
Breezy but missing in your tree and stop tracking them for you.
1853
parameters are given Bazaar will scan for files that are being tracked by
1854
Bazaar but missing in your tree and stop tracking them for you.
1936
1856
takes_args = ['file*']
1937
1857
takes_options = ['verbose',
1939
'new', help='Only remove files that have never been committed.'),
1940
RegistryOption.from_kwargs('file-deletion-strategy',
1941
'The file deletion mode to be used.',
1942
title='Deletion Strategy', value_switches=True, enum_switch=False,
1943
safe='Backup changed files (default).',
1944
keep='Delete from brz but leave the working copy.',
1945
no_backup='Don\'t backup changed files.'),
1858
Option('new', help='Only remove files that have never been committed.'),
1859
RegistryOption.from_kwargs('file-deletion-strategy',
1860
'The file deletion mode to be used.',
1861
title='Deletion Strategy', value_switches=True, enum_switch=False,
1862
safe='Backup changed files (default).',
1863
keep='Delete from brz but leave the working copy.',
1864
no_backup='Don\'t backup changed files.'),
1947
1866
aliases = ['rm', 'del']
1948
1867
encoding_type = 'replace'
1950
1869
def run(self, file_list, verbose=False, new=False,
1951
file_deletion_strategy='safe'):
1870
file_deletion_strategy='safe'):
1953
1872
tree, file_list = WorkingTree.open_containing_paths(file_list)
1955
1874
if file_list is not None:
1956
1875
file_list = [f for f in file_list]
1958
self.enter_context(tree.lock_write())
1877
self.add_cleanup(tree.lock_write().unlock)
1959
1878
# Heuristics should probably all move into tree.remove_smart or
1962
1881
added = tree.changes_from(tree.basis_tree(),
1963
specific_files=file_list).added
1964
file_list = sorted([f.path[1] for f in added], reverse=True)
1882
specific_files=file_list).added
1883
file_list = sorted([f[0] for f in added], reverse=True)
1965
1884
if len(file_list) == 0:
1966
1885
raise errors.BzrCommandError(gettext('No matching files.'))
1967
1886
elif file_list is None:
2707
2642
takes_args = ['file*']
2708
2643
_see_also = ['log-formats', 'revisionspec']
2709
2644
takes_options = [
2711
help='Show from oldest to newest.'),
2713
custom_help('verbose',
2714
help='Show files changed in each revision.'),
2718
type=breezy.option._parse_revision_str,
2720
help='Show just the specified revision.'
2721
' See also "help revisionspec".'),
2723
RegistryOption('authors',
2724
'What names to list as authors - first, all or committer.',
2727
'breezy.log', 'author_list_registry'),
2731
help='Number of levels to display - 0 for all, 1 for flat.',
2733
type=_parse_levels),
2735
help='Show revisions whose message matches this '
2736
'regular expression.',
2741
help='Limit the output to the first N revisions.',
2746
help='Show changes made in each revision as a patch.'),
2747
Option('include-merged',
2748
help='Show merged revisions like --levels 0 does.'),
2749
Option('include-merges', hidden=True,
2750
help='Historical alias for --include-merged.'),
2751
Option('omit-merges',
2752
help='Do not report commits with more than one parent.'),
2753
Option('exclude-common-ancestry',
2754
help='Display only the revisions that are not part'
2755
' of both ancestries (require -rX..Y).'
2757
Option('signatures',
2758
help='Show digital signature validity.'),
2761
help='Show revisions whose properties match this '
2764
ListOption('match-message',
2765
help='Show revisions whose message matches this '
2768
ListOption('match-committer',
2646
help='Show from oldest to newest.'),
2648
custom_help('verbose',
2649
help='Show files changed in each revision.'),
2653
type=breezy.option._parse_revision_str,
2655
help='Show just the specified revision.'
2656
' See also "help revisionspec".'),
2658
RegistryOption('authors',
2659
'What names to list as authors - first, all or committer.',
2661
lazy_registry=('breezy.log', 'author_list_registry'),
2665
help='Number of levels to display - 0 for all, 1 for flat.',
2667
type=_parse_levels),
2669
help='Show revisions whose message matches this '
2670
'regular expression.',
2675
help='Limit the output to the first N revisions.',
2680
help='Show changes made in each revision as a patch.'),
2681
Option('include-merged',
2682
help='Show merged revisions like --levels 0 does.'),
2683
Option('include-merges', hidden=True,
2684
help='Historical alias for --include-merged.'),
2685
Option('omit-merges',
2686
help='Do not report commits with more than one parent.'),
2687
Option('exclude-common-ancestry',
2688
help='Display only the revisions that are not part'
2689
' of both ancestries (require -rX..Y).'
2691
Option('signatures',
2692
help='Show digital signature validity.'),
2695
help='Show revisions whose properties match this '
2698
ListOption('match-message',
2699
help='Show revisions whose message matches this '
2702
ListOption('match-committer',
2769
2703
help='Show revisions whose committer matches this '
2772
ListOption('match-author',
2706
ListOption('match-author',
2773
2707
help='Show revisions whose authors match this '
2776
ListOption('match-bugs',
2710
ListOption('match-bugs',
2777
2711
help='Show revisions whose bugs match this '
2781
2715
encoding_type = 'replace'
2783
2717
@display_command
3453
3359
filters=False, directory=None):
3454
3360
if revision is not None and len(revision) != 1:
3455
3361
raise errors.BzrCommandError(gettext("brz cat --revision takes exactly"
3456
" one revision specifier"))
3362
" one revision specifier"))
3457
3363
tree, branch, relpath = \
3458
3364
_open_directory_or_containing_tree_or_branch(filename, directory)
3459
self.enter_context(branch.lock_read())
3365
self.add_cleanup(branch.lock_read().unlock)
3460
3366
return self._run(tree, branch, relpath, filename, revision,
3461
3367
name_from_revision, filters)
3463
3369
def _run(self, tree, b, relpath, filename, revision, name_from_revision,
3466
3371
if tree is None:
3467
3372
tree = b.basis_tree()
3468
3373
rev_tree = _get_one_revision_tree('cat', revision, branch=b)
3469
self.enter_context(rev_tree.lock_read())
3374
self.add_cleanup(rev_tree.lock_read().unlock)
3376
old_file_id = rev_tree.path2id(relpath)
3378
# TODO: Split out this code to something that generically finds the
3379
# best id for a path across one or more trees; it's like
3380
# find_ids_across_trees but restricted to find just one. -- mbp
3471
3382
if name_from_revision:
3472
3383
# Try in revision if requested
3473
if not rev_tree.is_versioned(relpath):
3384
if old_file_id is None:
3474
3385
raise errors.BzrCommandError(gettext(
3475
3386
"{0!r} is not present in revision {1}").format(
3476
3387
filename, rev_tree.get_revision_id()))
3477
rev_tree_path = relpath
3389
actual_file_id = old_file_id
3480
rev_tree_path = _mod_tree.find_previous_path(
3481
tree, rev_tree, relpath)
3482
except errors.NoSuchFile:
3483
rev_tree_path = None
3485
if rev_tree_path is None:
3486
# Path didn't exist in working tree
3487
if not rev_tree.is_versioned(relpath):
3488
raise errors.BzrCommandError(gettext(
3489
"{0!r} is not present in revision {1}").format(
3490
filename, rev_tree.get_revision_id()))
3492
# Fall back to the same path in the basis tree, if present.
3493
rev_tree_path = relpath
3391
cur_file_id = tree.path2id(relpath)
3392
if cur_file_id is not None and rev_tree.has_id(cur_file_id):
3393
actual_file_id = cur_file_id
3394
elif old_file_id is not None:
3395
actual_file_id = old_file_id
3397
raise errors.BzrCommandError(gettext(
3398
"{0!r} is not present in revision {1}").format(
3399
filename, rev_tree.get_revision_id()))
3400
relpath = rev_tree.id2path(actual_file_id)
3496
3402
from .filter_tree import ContentFilterTree
3497
filter_tree = ContentFilterTree(
3498
rev_tree, rev_tree._content_filter_stack)
3499
fileobj = filter_tree.get_file(rev_tree_path)
3403
filter_tree = ContentFilterTree(rev_tree,
3404
rev_tree._content_filter_stack)
3405
content = filter_tree.get_file_text(relpath, actual_file_id)
3501
fileobj = rev_tree.get_file(rev_tree_path)
3502
shutil.copyfileobj(fileobj, self.outf)
3407
content = rev_tree.get_file_text(relpath, actual_file_id)
3503
3408
self.cleanup_now()
3409
self.outf.write(content)
3506
3412
class cmd_local_time_offset(Command):
3507
3413
__doc__ = """Show the offset in seconds from GMT to local time."""
3510
3415
@display_command
3512
3417
self.outf.write("%s\n" % osutils.local_time_offset())
3515
3421
class cmd_commit(Command):
3516
3422
__doc__ = """Commit changes into a new revision.
3572
3478
_see_also = ['add', 'bugs', 'hooks', 'uncommit']
3573
3479
takes_args = ['selected*']
3574
3480
takes_options = [
3576
'exclude', type=text_type, short_name='x',
3577
help="Do not consider changes made to a given path."),
3578
Option('message', type=text_type,
3580
help="Description of the new revision."),
3583
help='Commit even if nothing has changed.'),
3584
Option('file', type=text_type,
3587
help='Take commit message from this file.'),
3589
help="Refuse to commit if there are unknown "
3590
"files in the working tree."),
3591
Option('commit-time', type=text_type,
3592
help="Manually set a commit time using commit date "
3593
"format, e.g. '2009-10-10 08:00:00 +0100'."),
3595
'bugs', type=text_type,
3596
help="Link to a related bug. (see \"brz help bugs\")."),
3598
'fixes', type=text_type,
3599
help="Mark a bug as being fixed by this revision "
3600
"(see \"brz help bugs\")."),
3602
'author', type=text_type,
3603
help="Set the author's name, if it's different "
3604
"from the committer."),
3606
help="Perform a local commit in a bound "
3607
"branch. Local commits are not pushed to "
3608
"the master branch until a normal commit "
3611
Option('show-diff', short_name='p',
3612
help='When no message is supplied, show the diff along'
3613
' with the status summary in the message editor.'),
3615
help='When committing to a foreign version control '
3616
'system do not push data that can not be natively '
3481
ListOption('exclude', type=text_type, short_name='x',
3482
help="Do not consider changes made to a given path."),
3483
Option('message', type=text_type,
3485
help="Description of the new revision."),
3488
help='Commit even if nothing has changed.'),
3489
Option('file', type=text_type,
3492
help='Take commit message from this file.'),
3494
help="Refuse to commit if there are unknown "
3495
"files in the working tree."),
3496
Option('commit-time', type=text_type,
3497
help="Manually set a commit time using commit date "
3498
"format, e.g. '2009-10-10 08:00:00 +0100'."),
3499
ListOption('fixes', type=text_type,
3500
help="Mark a bug as being fixed by this revision "
3501
"(see \"brz help bugs\")."),
3502
ListOption('author', type=text_type,
3503
help="Set the author's name, if it's different "
3504
"from the committer."),
3506
help="Perform a local commit in a bound "
3507
"branch. Local commits are not pushed to "
3508
"the master branch until a normal commit "
3511
Option('show-diff', short_name='p',
3512
help='When no message is supplied, show the diff along'
3513
' with the status summary in the message editor.'),
3515
help='When committing to a foreign version control '
3516
'system do not push data that can not be natively '
3618
3519
aliases = ['ci', 'checkin']
3620
def _iter_bug_urls(self, bugs, branch, status):
3621
default_bugtracker = None
3521
def _iter_bug_fix_urls(self, fixes, branch):
3522
default_bugtracker = None
3622
3523
# Configure the properties for bug fixing attributes.
3624
tokens = bug.split(':')
3524
for fixed_bug in fixes:
3525
tokens = fixed_bug.split(':')
3625
3526
if len(tokens) == 1:
3626
3527
if default_bugtracker is None:
3627
3528
branch_config = branch.get_config_stack()
4511
4403
change_reporter = delta._ChangeReporter(
4512
4404
unversioned_filter=tree.is_ignored, view_info=view_info)
4513
4405
pb = ui.ui_factory.nested_progress_bar()
4514
self.enter_context(pb)
4515
self.enter_context(tree.lock_write())
4406
self.add_cleanup(pb.finished)
4407
self.add_cleanup(tree.lock_write().unlock)
4516
4408
if location is not None:
4518
mergeable = _mod_mergeable.read_mergeable_from_url(
4519
location, possible_transports=possible_transports)
4410
mergeable = bundle.read_mergeable_from_url(location,
4411
possible_transports=possible_transports)
4520
4412
except errors.NotABundle:
4521
4413
mergeable = None
4523
4415
if uncommitted:
4524
4416
raise errors.BzrCommandError(gettext('Cannot use --uncommitted'
4525
' with bundles or merge directives.'))
4417
' with bundles or merge directives.'))
4527
4419
if revision is not None:
4528
4420
raise errors.BzrCommandError(gettext(
4529
4421
'Cannot use -r with merge directives or bundles'))
4530
4422
merger, verified = _mod_merge.Merger.from_mergeable(tree,
4533
4425
if merger is None and uncommitted:
4534
4426
if revision is not None and len(revision) > 0:
4535
4427
raise errors.BzrCommandError(gettext('Cannot use --uncommitted and'
4536
' --revision at the same time.'))
4428
' --revision at the same time.'))
4537
4429
merger = self.get_merger_from_uncommitted(tree, location, None)
4538
4430
allow_pending = False
4540
4432
if merger is None:
4541
4433
merger, allow_pending = self._get_merger_from_branch(tree,
4542
location, revision, remember, possible_transports, None)
4434
location, revision, remember, possible_transports, None)
4544
4436
merger.merge_type = merge_type
4545
4437
merger.reprocess = reprocess
4546
4438
merger.show_base = show_base
4547
4439
self.sanity_check_merger(merger)
4548
4440
if (merger.base_rev_id == merger.other_rev_id and
4549
merger.other_rev_id is not None):
4441
merger.other_rev_id is not None):
4550
4442
# check if location is a nonexistent file (and not a branch) to
4551
4443
# disambiguate the 'Nothing to do'
4552
4444
if merger.interesting_files:
4553
4445
if not merger.other_tree.has_filename(
4554
merger.interesting_files[0]):
4446
merger.interesting_files[0]):
4555
4447
note(gettext("merger: ") + str(merger))
4556
4448
raise errors.PathsDoNotExist([location])
4557
4449
note(gettext('Nothing to do.'))
4559
4451
if pull and not preview:
4560
4452
if merger.interesting_files is not None:
4561
raise errors.BzrCommandError(
4562
gettext('Cannot pull individual files'))
4453
raise errors.BzrCommandError(gettext('Cannot pull individual files'))
4563
4454
if (merger.base_rev_id == tree.last_revision()):
4564
4455
result = tree.pull(merger.other_branch, False,
4565
4456
merger.other_rev_id)
5298
5185
wt, branch, relpath = \
5299
5186
_open_directory_or_containing_tree_or_branch(filename, directory)
5300
5187
if wt is not None:
5301
self.enter_context(wt.lock_read())
5188
self.add_cleanup(wt.lock_read().unlock)
5303
self.enter_context(branch.lock_read())
5190
self.add_cleanup(branch.lock_read().unlock)
5304
5191
tree = _get_one_revision_tree('annotate', revision, branch=branch)
5305
self.enter_context(tree.lock_read())
5306
if wt is not None and revision is None:
5307
if not wt.is_versioned(relpath):
5308
raise errors.NotVersionedError(relpath)
5192
self.add_cleanup(tree.lock_read().unlock)
5193
if wt is not None and revision is None:
5194
file_id = wt.path2id(relpath)
5196
file_id = tree.path2id(relpath)
5198
raise errors.NotVersionedError(filename)
5199
if wt is not None and revision is None:
5309
5200
# If there is a tree and we're not annotating historical
5310
5201
# versions, annotate the working tree's content.
5311
5202
annotate_file_tree(wt, relpath, self.outf, long, all,
5203
show_ids=show_ids, file_id=file_id)
5314
if not tree.is_versioned(relpath):
5315
raise errors.NotVersionedError(relpath)
5316
5205
annotate_file_tree(tree, relpath, self.outf, long, all,
5317
show_ids=show_ids, branch=branch)
5206
show_ids=show_ids, branch=branch, file_id=file_id)
5320
5209
class cmd_re_sign(Command):
5321
5210
__doc__ = """Create a digital signature for an existing revision."""
5322
5211
# TODO be able to replace existing ones.
5324
hidden = True # is this right ?
5213
hidden = True # is this right ?
5325
5214
takes_args = ['revision_id*']
5326
5215
takes_options = ['directory', 'revision']
5328
5217
def run(self, revision_id_list=None, revision=None, directory=u'.'):
5329
5218
if revision_id_list is not None and revision is not None:
5330
raise errors.BzrCommandError(
5331
gettext('You can only supply one of revision_id or --revision'))
5219
raise errors.BzrCommandError(gettext('You can only supply one of revision_id or --revision'))
5332
5220
if revision_id_list is None and revision is None:
5333
raise errors.BzrCommandError(
5334
gettext('You must supply either --revision or a revision_id'))
5221
raise errors.BzrCommandError(gettext('You must supply either --revision or a revision_id'))
5335
5222
b = WorkingTree.open_containing(directory)[0].branch
5336
self.enter_context(b.lock_write())
5223
self.add_cleanup(b.lock_write().unlock)
5337
5224
return self._run(b, revision_id_list, revision)
5339
5226
def _run(self, b, revision_id_list, revision):
5340
from .repository import WriteGroup
5341
5227
gpg_strategy = gpg.GPGStrategy(b.get_config_stack())
5342
5228
if revision_id_list is not None:
5343
with WriteGroup(b.repository):
5229
b.repository.start_write_group()
5344
5231
for revision_id in revision_id_list:
5345
5232
revision_id = cache_utf8.encode(revision_id)
5346
5233
b.repository.sign_revision(revision_id, gpg_strategy)
5235
b.repository.abort_write_group()
5238
b.repository.commit_write_group()
5347
5239
elif revision is not None:
5348
5240
if len(revision) == 1:
5349
5241
revno, rev_id = revision[0].in_history(b)
5350
with WriteGroup(b.repository):
5242
b.repository.start_write_group()
5351
5244
b.repository.sign_revision(rev_id, gpg_strategy)
5246
b.repository.abort_write_group()
5249
b.repository.commit_write_group()
5352
5250
elif len(revision) == 2:
5353
5251
# are they both on rh- if so we can walk between them
5354
5252
# might be nice to have a range helper for arbitrary
6351
6248
except errors.NotBranchError:
6353
6250
had_explicit_nick = False
6355
possible_transports.append(branch.user_transport)
6356
6251
if create_branch:
6357
6252
if branch is None:
6358
6253
raise errors.BzrCommandError(
6359
6254
gettext('cannot create branch without source branch'))
6360
to_location = lookup_new_sibling_branch(
6361
control_dir, to_location,
6362
possible_transports=possible_transports)
6363
if revision is not None:
6364
revision = revision.as_revision_id(branch)
6365
to_branch = branch.controldir.sprout(
6367
possible_transports=possible_transports,
6368
revision_id=revision,
6369
source_branch=branch).open_branch()
6255
to_location = lookup_new_sibling_branch(control_dir, to_location,
6256
possible_transports=possible_transports)
6257
to_branch = branch.controldir.sprout(to_location,
6258
possible_transports=possible_transports,
6259
source_branch=branch).open_branch()
6372
to_branch = Branch.open(
6373
to_location, possible_transports=possible_transports)
6262
to_branch = Branch.open(to_location,
6263
possible_transports=possible_transports)
6374
6264
except errors.NotBranchError:
6375
to_branch = open_sibling_branch(
6376
control_dir, to_location,
6265
to_branch = open_sibling_branch(control_dir, to_location,
6377
6266
possible_transports=possible_transports)
6378
if revision is not None:
6379
revision = revision.as_revision_id(to_branch)
6380
possible_transports.append(to_branch.user_transport)
6267
if revision is not None:
6268
revision = revision.as_revision_id(to_branch)
6382
6270
switch.switch(control_dir, to_branch, force, revision_id=revision,
6383
store_uncommitted=store,
6384
possible_transports=possible_transports)
6271
store_uncommitted=store)
6385
6272
except controldir.BranchReferenceLoop:
6386
6273
raise errors.BzrCommandError(
6387
gettext('switching would create a branch reference loop. '
6388
'Use the "bzr up" command to switch to a '
6389
'different revision.'))
6274
gettext('switching would create a branch reference loop. '
6275
'Use the "bzr up" command to switch to a '
6276
'different revision.'))
6390
6277
if had_explicit_nick:
6391
branch = control_dir.open_branch() # get the new branch!
6278
branch = control_dir.open_branch() #get the new branch!
6392
6279
branch.nick = to_branch.nick
6394
if to_branch.controldir.control_url != control_dir.control_url:
6395
note(gettext('Switched to branch %s at %s'),
6396
to_branch.name, urlutils.unescape_for_display(to_branch.base, 'utf-8'))
6398
note(gettext('Switched to branch %s'), to_branch.name)
6400
note(gettext('Switched to branch at %s'),
6401
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
6280
note(gettext('Switched to branch: %s'),
6281
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
6404
6285
class cmd_view(Command):
6788
6662
takes_args = ['path?', 'location?']
6791
Option('force-unversioned',
6792
help='Set reference even if path is not versioned.'),
6795
def run(self, path=None, directory='.', location=None, force_unversioned=False):
6796
tree, branch, relpath = (
6797
controldir.ControlDir.open_containing_tree_or_branch(directory))
6664
def run(self, path=None, location=None):
6666
if path is not None:
6668
tree, branch, relpath =(
6669
controldir.ControlDir.open_containing_tree_or_branch(branchdir))
6670
if path is not None:
6798
6672
if tree is None:
6799
6673
tree = branch.basis_tree()
6800
6674
if path is None:
6801
with tree.lock_read():
6803
(path, tree.get_reference_info(path, branch))
6804
for path in tree.iter_references()]
6805
self._display_reference_info(tree, branch, info)
6675
info = viewitems(branch._get_all_reference_info())
6676
self._display_reference_info(tree, branch, info)
6807
if not tree.is_versioned(path) and not force_unversioned:
6678
if not tree.is_versioned(path):
6808
6679
raise errors.NotVersionedError(path)
6809
6680
if location is None:
6810
info = [(path, tree.get_reference_info(path, branch))]
6681
info = [(path, branch.get_reference_info(path))]
6811
6682
self._display_reference_info(tree, branch, info)
6813
tree.set_reference_info(path, location)
6684
branch.set_reference_info(
6685
path, location, file_id=tree.path2id(path))
6815
6687
def _display_reference_info(self, tree, branch, info):
6817
for path, location in info:
6689
for path, (location, file_id) in info:
6818
6690
ref_list.append((path, location))
6819
6691
for path, location in sorted(ref_list):
6820
6692
self.outf.write('%s %s\n' % (path, location))
6892
6771
if len(installed) > 0:
6893
6772
self.outf.write("Installed:\n")
6894
6773
for rev in installed:
6895
self.outf.write(rev.decode('utf-8') + "\n")
6774
self.outf.write(rev + "\n")
6896
6775
if len(failed) > 0:
6897
6776
self.outf.write("Still missing:\n")
6898
6777
for rev in failed:
6899
self.outf.write(rev.decode('utf-8') + "\n")
6778
self.outf.write(rev + "\n")
6900
6779
if not no_fix and len(installed) > 0:
6901
6780
cmd_reconcile().run(".")
6904
class cmd_grep(Command):
6905
"""Print lines matching PATTERN for specified files and revisions.
6907
This command searches the specified files and revisions for a given
6908
pattern. The pattern is specified as a Python regular expressions[1].
6910
If the file name is not specified, the revisions starting with the
6911
current directory are searched recursively. If the revision number is
6912
not specified, the working copy is searched. To search the last committed
6913
revision, use the '-r -1' or '-r last:1' option.
6915
Unversioned files are not searched unless explicitly specified on the
6916
command line. Unversioned directores are not searched.
6918
When searching a pattern, the output is shown in the 'filepath:string'
6919
format. If a revision is explicitly searched, the output is shown as
6920
'filepath~N:string', where N is the revision number.
6922
--include and --exclude options can be used to search only (or exclude
6923
from search) files with base name matches the specified Unix style GLOB
6924
pattern. The GLOB pattern an use *, ?, and [...] as wildcards, and \\
6925
to quote wildcard or backslash character literally. Note that the glob
6926
pattern is not a regular expression.
6928
[1] http://docs.python.org/library/re.html#regular-expression-syntax
6931
encoding_type = 'replace'
6932
takes_args = ['pattern', 'path*']
6936
Option('color', type=text_type, argname='when',
6937
help='Show match in color. WHEN is never, always or auto.'),
6938
Option('diff', short_name='p',
6939
help='Grep for pattern in changeset for each revision.'),
6940
ListOption('exclude', type=text_type, argname='glob', short_name='X',
6941
help="Skip files whose base name matches GLOB."),
6942
ListOption('include', type=text_type, argname='glob', short_name='I',
6943
help="Search only files whose base name matches GLOB."),
6944
Option('files-with-matches', short_name='l',
6945
help='Print only the name of each input file in '
6946
'which PATTERN is found.'),
6947
Option('files-without-match', short_name='L',
6948
help='Print only the name of each input file in '
6949
'which PATTERN is not found.'),
6950
Option('fixed-string', short_name='F',
6951
help='Interpret PATTERN is a single fixed string (not regex).'),
6953
help='Search for pattern starting from the root of the branch. '
6954
'(implies --recursive)'),
6955
Option('ignore-case', short_name='i',
6956
help='Ignore case distinctions while matching.'),
6958
help='Number of levels to display - 0 for all, 1 for collapsed '
6961
type=_parse_levels),
6962
Option('line-number', short_name='n',
6963
help='Show 1-based line number.'),
6964
Option('no-recursive',
6965
help="Don't recurse into subdirectories. (default is --recursive)"),
6966
Option('null', short_name='Z',
6967
help='Write an ASCII NUL (\\0) separator '
6968
'between output lines rather than a newline.'),
6972
def run(self, verbose=False, ignore_case=False, no_recursive=False,
6973
from_root=False, null=False, levels=None, line_number=False,
6974
path_list=None, revision=None, pattern=None, include=None,
6975
exclude=None, fixed_string=False, files_with_matches=False,
6976
files_without_match=False, color=None, diff=False):
6977
from breezy import _termcolor
6980
if path_list is None:
6984
raise errors.BzrCommandError(
6985
'cannot specify both --from-root and PATH.')
6987
if files_with_matches and files_without_match:
6988
raise errors.BzrCommandError(
6989
'cannot specify both '
6990
'-l/--files-with-matches and -L/--files-without-matches.')
6992
global_config = _mod_config.GlobalConfig()
6995
color = global_config.get_user_option('grep_color')
7000
if color not in ['always', 'never', 'auto']:
7001
raise errors.BzrCommandError('Valid values for --color are '
7002
'"always", "never" or "auto".')
7008
if revision is not None or levels == 0:
7009
# print revision numbers as we may be showing multiple revisions
7016
if not ignore_case and grep.is_fixed_string(pattern):
7017
# if the pattern isalnum, implicitly use to -F for faster grep
7019
elif ignore_case and fixed_string:
7020
# GZ 2010-06-02: Fall back to regexp rather than lowercasing
7021
# pattern and text which will cause pain later
7022
fixed_string = False
7023
pattern = re.escape(pattern)
7026
re_flags = re.MULTILINE
7028
re_flags |= re.IGNORECASE
7030
if not fixed_string:
7031
patternc = grep.compile_pattern(
7032
pattern.encode(grep._user_encoding), re_flags)
7034
if color == 'always':
7036
elif color == 'never':
7038
elif color == 'auto':
7039
show_color = _termcolor.allow_color()
7041
opts = grep.GrepOptions()
7043
opts.verbose = verbose
7044
opts.ignore_case = ignore_case
7045
opts.no_recursive = no_recursive
7046
opts.from_root = from_root
7048
opts.levels = levels
7049
opts.line_number = line_number
7050
opts.path_list = path_list
7051
opts.revision = revision
7052
opts.pattern = pattern
7053
opts.include = include
7054
opts.exclude = exclude
7055
opts.fixed_string = fixed_string
7056
opts.files_with_matches = files_with_matches
7057
opts.files_without_match = files_without_match
7061
opts.eol_marker = eol_marker
7062
opts.print_revno = print_revno
7063
opts.patternc = patternc
7064
opts.recursive = not no_recursive
7065
opts.fixed_string = fixed_string
7066
opts.outf = self.outf
7067
opts.show_color = show_color
7071
# files_with_matches, files_without_match
7072
# levels(?), line_number, from_root
7074
# These are silently ignored.
7075
grep.grep_diff(opts)
7076
elif revision is None:
7077
grep.workingtree_grep(opts)
7079
grep.versioned_grep(opts)
7082
class cmd_patch(Command):
7083
"""Apply a named patch to the current tree.
7087
takes_args = ['filename?']
7088
takes_options = [Option('strip', type=int, short_name='p',
7089
help=("Strip the smallest prefix containing num "
7090
"leading slashes from filenames.")),
7091
Option('silent', help='Suppress chatter.')]
7093
def run(self, filename=None, strip=None, silent=False):
7094
from .patch import patch_tree
7095
wt = WorkingTree.open_containing('.')[0]
7099
if filename is None:
7100
my_file = getattr(sys.stdin, 'buffer', sys.stdin)
7102
my_file = open(filename, 'rb')
7103
patches = [my_file.read()]
7104
return patch_tree(wt, patches, strip, quiet=is_quiet(), out=self.outf)
7107
class cmd_resolve_location(Command):
7108
__doc__ = """Expand a location to a full URL.
7111
Look up a Launchpad URL.
7113
brz resolve-location lp:brz
7115
takes_args = ['location']
7118
def run(self, location):
7119
from .location import location_to_url
7120
url = location_to_url(location)
7121
display_url = urlutils.unescape_for_display(url, self.outf.encoding)
7122
self.outf.write('%s\n' % display_url)
7125
6783
def _register_lazy_builtins():
7126
6784
# register lazy builtins from other modules; called at startup and should
7127
6785
# be only called once.
7128
6786
for (name, aliases, module_name) in [
7129
('cmd_bisect', [], 'breezy.bisect'),
7130
('cmd_bundle_info', [], 'breezy.bzr.bundle.commands'),
7131
('cmd_config', [], 'breezy.config'),
7132
('cmd_dump_btree', [], 'breezy.bzr.debug_commands'),
7133
('cmd_file_id', [], 'breezy.bzr.debug_commands'),
7134
('cmd_file_path', [], 'breezy.bzr.debug_commands'),
7135
('cmd_version_info', [], 'breezy.cmd_version_info'),
7136
('cmd_resolve', ['resolved'], 'breezy.conflicts'),
7137
('cmd_conflicts', [], 'breezy.conflicts'),
7138
('cmd_ping', [], 'breezy.bzr.smart.ping'),
7139
('cmd_sign_my_commits', [], 'breezy.commit_signature_commands'),
7140
('cmd_verify_signatures', [], 'breezy.commit_signature_commands'),
7141
('cmd_test_script', [], 'breezy.cmd_test_script'),
6787
('cmd_bisect', [], 'breezy.bisect'),
6788
('cmd_bundle_info', [], 'breezy.bundle.commands'),
6789
('cmd_config', [], 'breezy.config'),
6790
('cmd_dump_btree', [], 'breezy.bzr.debug_commands'),
6791
('cmd_dpush', [], 'breezy.foreign'),
6792
('cmd_version_info', [], 'breezy.cmd_version_info'),
6793
('cmd_resolve', ['resolved'], 'breezy.conflicts'),
6794
('cmd_conflicts', [], 'breezy.conflicts'),
6795
('cmd_ping', [], 'breezy.bzr.smart.ping'),
6796
('cmd_sign_my_commits', [], 'breezy.commit_signature_commands'),
6797
('cmd_verify_signatures', [], 'breezy.commit_signature_commands'),
6798
('cmd_test_script', [], 'breezy.cmd_test_script'),
7143
6800
builtin_command_registry.register_lazy(name, aliases, module_name)