442
439
def run(self, revision_id=None, revision=None, directory=u'.'):
443
440
if revision_id is not None and revision is not None:
444
raise errors.CommandError(gettext('You can only supply one of'
445
' revision_id or --revision'))
441
raise errors.BzrCommandError(gettext('You can only supply one of'
442
' revision_id or --revision'))
446
443
if revision_id is None and revision is None:
447
raise errors.CommandError(
448
gettext('You must supply either --revision or a revision_id'))
444
raise errors.BzrCommandError(gettext('You must supply either'
445
' --revision or a revision_id'))
450
447
b = controldir.ControlDir.open_containing_tree_or_branch(directory)[1]
452
revisions = getattr(b.repository, "revisions", None)
449
revisions = b.repository.revisions
453
450
if revisions is None:
454
raise errors.CommandError(
455
gettext('Repository %r does not support '
456
'access to raw revision texts') % b.repository)
451
raise errors.BzrCommandError(gettext('Repository %r does not support '
452
'access to raw revision texts'))
458
with b.repository.lock_read():
454
b.repository.lock_read()
459
456
# TODO: jam 20060112 should cat-revision always output utf-8?
460
457
if revision_id is not None:
461
revision_id = cache_utf8.encode(revision_id)
458
revision_id = osutils.safe_revision_id(revision_id, warn=False)
463
460
self.print_revision(revisions, revision_id)
464
461
except errors.NoSuchRevision:
466
"The repository {0} contains no revision {1}.").format(
467
b.repository.base, revision_id.decode('utf-8'))
468
raise errors.CommandError(msg)
462
msg = gettext("The repository {0} contains no revision {1}.").format(
463
b.repository.base, revision_id)
464
raise errors.BzrCommandError(msg)
469
465
elif revision is not None:
470
466
for rev in revision:
472
raise errors.CommandError(
468
raise errors.BzrCommandError(
473
469
gettext('You cannot specify a NULL revision.'))
474
470
rev_id = rev.as_revision_id(b)
475
471
self.print_revision(revisions, rev_id)
473
b.repository.unlock()
476
class cmd_dump_btree(Command):
477
__doc__ = """Dump the contents of a btree index file to stdout.
479
PATH is a btree index file, it can be any URL. This includes things like
480
.bzr/repository/pack-names, or .bzr/repository/indices/a34b3a...ca4a4.iix
482
By default, the tuples stored in the index file will be displayed. With
483
--raw, we will uncompress the pages, but otherwise display the raw bytes
487
# TODO: Do we want to dump the internal nodes as well?
488
# TODO: It would be nice to be able to dump the un-parsed information,
489
# rather than only going through iter_all_entries. However, this is
490
# good enough for a start
492
encoding_type = 'exact'
493
takes_args = ['path']
494
takes_options = [Option('raw', help='Write the uncompressed bytes out,'
495
' rather than the parsed tuples.'),
498
def run(self, path, raw=False):
499
dirname, basename = osutils.split(path)
500
t = transport.get_transport(dirname)
502
self._dump_raw_bytes(t, basename)
504
self._dump_entries(t, basename)
506
def _get_index_and_bytes(self, trans, basename):
507
"""Create a BTreeGraphIndex and raw bytes."""
508
bt = btree_index.BTreeGraphIndex(trans, basename, None)
509
bytes = trans.get_bytes(basename)
510
bt._file = cStringIO.StringIO(bytes)
511
bt._size = len(bytes)
514
def _dump_raw_bytes(self, trans, basename):
517
# We need to parse at least the root node.
518
# This is because the first page of every row starts with an
519
# uncompressed header.
520
bt, bytes = self._get_index_and_bytes(trans, basename)
521
for page_idx, page_start in enumerate(xrange(0, len(bytes),
522
btree_index._PAGE_SIZE)):
523
page_end = min(page_start + btree_index._PAGE_SIZE, len(bytes))
524
page_bytes = bytes[page_start:page_end]
526
self.outf.write('Root node:\n')
527
header_end, data = bt._parse_header_from_bytes(page_bytes)
528
self.outf.write(page_bytes[:header_end])
530
self.outf.write('\nPage %d\n' % (page_idx,))
531
if len(page_bytes) == 0:
532
self.outf.write('(empty)\n');
534
decomp_bytes = zlib.decompress(page_bytes)
535
self.outf.write(decomp_bytes)
536
self.outf.write('\n')
538
def _dump_entries(self, trans, basename):
540
st = trans.stat(basename)
541
except errors.TransportNotPossible:
542
# We can't stat, so we'll fake it because we have to do the 'get()'
544
bt, _ = self._get_index_and_bytes(trans, basename)
546
bt = btree_index.BTreeGraphIndex(trans, basename, st.st_size)
547
for node in bt.iter_all_entries():
548
# Node is made up of:
549
# (index, key, value, [references])
553
refs_as_tuples = None
555
refs_as_tuples = static_tuple.as_tuples(refs)
556
as_tuple = (tuple(node[1]), node[2], refs_as_tuples)
557
self.outf.write('%s\n' % (as_tuple,))
478
560
class cmd_remove_tree(Command):
858
927
takes_options = [
861
Option('include-root',
862
help='Include the entry for the root of the tree, if any.'),
864
help='List entries of a particular kind: file, directory, '
931
help='List entries of a particular kind: file, directory, symlink.',
868
934
takes_args = ['file*']
871
def run(self, revision=None, show_ids=False, kind=None, include_root=False,
937
def run(self, revision=None, show_ids=False, kind=None, file_list=None):
873
938
if kind and kind not in ['file', 'directory', 'symlink']:
874
raise errors.CommandError(
875
gettext('invalid kind %r specified') % (kind,))
939
raise errors.BzrCommandError(gettext('invalid kind %r specified') % (kind,))
877
941
revision = _get_one_revision('inventory', revision)
878
942
work_tree, file_list = WorkingTree.open_containing_paths(file_list)
879
self.enter_context(work_tree.lock_read())
943
self.add_cleanup(work_tree.lock_read().unlock)
880
944
if revision is not None:
881
945
tree = revision.as_tree(work_tree.branch)
883
947
extra_trees = [work_tree]
884
self.enter_context(tree.lock_read())
948
self.add_cleanup(tree.lock_read().unlock)
889
self.enter_context(tree.lock_read())
953
self.add_cleanup(tree.lock_read().unlock)
890
954
if file_list is not None:
891
paths = tree.find_related_paths_across_trees(
892
file_list, extra_trees, require_versioned=True)
955
file_ids = tree.paths2ids(file_list, trees=extra_trees,
956
require_versioned=True)
893
957
# find_ids_across_trees may include some paths that don't
894
958
# exist in 'tree'.
895
entries = tree.iter_entries_by_dir(specific_files=paths)
959
entries = tree.iter_entries_by_dir(specific_file_ids=file_ids)
897
961
entries = tree.iter_entries_by_dir()
899
963
for path, entry in sorted(entries):
900
964
if kind and kind != entry.kind:
902
if path == "" and not include_root:
905
self.outf.write('%-50s %s\n' % (
906
path, entry.file_id.decode('utf-8')))
969
self.outf.write('%-50s %s\n' % (path, entry.file_id))
908
971
self.outf.write(path)
909
972
self.outf.write('\n')
912
class cmd_cp(Command):
913
__doc__ = """Copy a file.
916
brz cp OLDNAME NEWNAME
918
brz cp SOURCE... DESTINATION
920
If the last argument is a versioned directory, all the other names
921
are copied into it. Otherwise, there must be exactly two arguments
922
and the file is copied to a new name.
924
Files cannot be copied between branches. Only files can be copied
928
takes_args = ['names*']
931
encoding_type = 'replace'
933
def run(self, names_list):
934
if names_list is None:
936
if len(names_list) < 2:
937
raise errors.CommandError(gettext("missing file argument"))
938
tree, rel_names = WorkingTree.open_containing_paths(
939
names_list, canonicalize=False)
940
for file_name in rel_names[0:-1]:
942
raise errors.CommandError(
943
gettext("can not copy root of branch"))
944
self.enter_context(tree.lock_tree_write())
945
into_existing = osutils.isdir(names_list[-1])
946
if not into_existing:
948
(src, dst) = rel_names
950
raise errors.CommandError(
951
gettext('to copy multiple files the'
952
' destination must be a versioned'
957
(n, osutils.joinpath([rel_names[-1], osutils.basename(n)]))
958
for n in rel_names[:-1]]
960
for src, dst in pairs:
962
src_kind = tree.stored_kind(src)
963
except errors.NoSuchFile:
964
raise errors.CommandError(
965
gettext('Could not copy %s => %s: %s is not versioned.')
968
raise errors.CommandError(
969
gettext('Could not copy %s => %s . %s is not versioned\\.'
971
if src_kind == 'directory':
972
raise errors.CommandError(
973
gettext('Could not copy %s => %s . %s is a directory.'
975
dst_parent = osutils.split(dst)[0]
978
dst_parent_kind = tree.stored_kind(dst_parent)
979
except errors.NoSuchFile:
980
raise errors.CommandError(
981
gettext('Could not copy %s => %s: %s is not versioned.')
982
% (src, dst, dst_parent))
983
if dst_parent_kind != 'directory':
984
raise errors.CommandError(
985
gettext('Could not copy to %s: %s is not a directory.')
986
% (dst_parent, dst_parent))
988
tree.copy_one(src, dst)
991
975
class cmd_mv(Command):
992
976
__doc__ = """Move or rename a file.
995
brz mv OLDNAME NEWNAME
979
bzr mv OLDNAME NEWNAME
997
brz mv SOURCE... DESTINATION
981
bzr mv SOURCE... DESTINATION
999
983
If the last argument is a versioned directory, all the other names
1000
984
are moved into it. Otherwise, there must be exactly two arguments
1311
1289
_see_also = ['pull', 'update', 'working-trees']
1312
1290
takes_options = ['remember', 'overwrite', 'verbose', 'revision',
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.")
1291
Option('create-prefix',
1292
help='Create the path leading up to the branch '
1293
'if it does not already exist.'),
1294
custom_help('directory',
1295
help='Branch to push from, '
1296
'rather than the one containing the working directory.'),
1297
Option('use-existing-dir',
1298
help='By default push will fail if the target'
1299
' directory exists, but does not already'
1300
' have a control directory. This flag will'
1301
' allow push to proceed.'),
1303
help='Create a stacked branch that references the public location '
1304
'of the parent branch.'),
1305
Option('stacked-on',
1306
help='Create a stacked branch that refers to another branch '
1307
'for the commit history. Only the work not present in the '
1308
'referenced branch is included in the branch created.',
1311
help='Refuse to push if there are uncommitted changes in'
1312
' the working tree, --no-strict disables the check.'),
1314
help="Don't populate the working tree, even for protocols"
1315
" that support it."),
1316
Option('overwrite-tags',
1317
help="Overwrite tags only."),
1343
1319
takes_args = ['location?']
1344
1320
encoding_type = 'replace'
1346
1322
def run(self, location=None, remember=None, overwrite=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
1352
from .push import _show_push_branch
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):
1327
from bzrlib.push import _show_push_branch
1355
1330
overwrite = ["history", "tags"]
1433
1406
To retrieve the branch as of a particular revision, supply the --revision
1434
1407
parameter, as in "branch foo/bar -r 5".
1409
The synonyms 'clone' and 'get' for this command are deprecated.
1438
1412
_see_also = ['checkout']
1439
1413
takes_args = ['from_location', 'to_location?']
1440
1414
takes_options = ['revision',
1442
'hardlink', help='Hard-link working tree files where possible.'),
1443
Option('files-from', type=str,
1444
help="Get file contents from this tree."),
1446
help="Create a branch without a working-tree."),
1448
help="Switch the checkout in the current directory "
1449
"to the new branch."),
1451
help='Create a stacked branch referring to the source branch. '
1452
'The new branch will depend on the availability of the source '
1453
'branch for all operations.'),
1454
Option('standalone',
1455
help='Do not use a shared repository, even if available.'),
1456
Option('use-existing-dir',
1457
help='By default branch will fail if the target'
1458
' directory exists, but does not already'
1459
' have a control directory. This flag will'
1460
' allow branch to proceed.'),
1462
help="Bind new branch to from location."),
1463
Option('no-recurse-nested',
1464
help='Do not recursively check out nested trees.'),
1465
Option('colocated-branch', short_name='b',
1466
type=str, help='Name of colocated branch to sprout.'),
1415
Option('hardlink', help='Hard-link working tree files where possible.'),
1416
Option('files-from', type=str,
1417
help="Get file contents from this tree."),
1419
help="Create a branch without a working-tree."),
1421
help="Switch the checkout in the current directory "
1422
"to the new branch."),
1424
help='Create a stacked branch referring to the source branch. '
1425
'The new branch will depend on the availability of the source '
1426
'branch for all operations.'),
1427
Option('standalone',
1428
help='Do not use a shared repository, even if available.'),
1429
Option('use-existing-dir',
1430
help='By default branch will fail if the target'
1431
' directory exists, but does not already'
1432
' have a control directory. This flag will'
1433
' allow branch to proceed.'),
1435
help="Bind new branch to from location."),
1437
aliases = ['get', 'clone']
1469
1439
def run(self, from_location, to_location=None, revision=None,
1470
1440
hardlink=False, stacked=False, standalone=False, no_tree=False,
1471
1441
use_existing_dir=False, switch=False, bind=False,
1472
files_from=None, no_recurse_nested=False, colocated_branch=None):
1473
from breezy import switch as _mod_switch
1443
from bzrlib import switch as _mod_switch
1444
from bzrlib.tag import _merge_tags_if_possible
1445
if self.invoked_as in ['get', 'clone']:
1446
ui.ui_factory.show_user_warning(
1447
'deprecated_command',
1448
deprecated_name=self.invoked_as,
1449
recommended_name='branch',
1450
deprecated_in_version='2.4')
1474
1451
accelerator_tree, br_from = controldir.ControlDir.open_tree_or_branch(
1475
from_location, name=colocated_branch)
1476
if no_recurse_nested:
1480
1453
if not (hardlink or files_from):
1481
1454
# accelerator_tree is usually slower because you have to read N
1482
1455
# files (no readahead, lots of seeks, etc), but allow the user to
1517
1492
raise errors.AlreadyBranchError(to_location)
1518
1493
except errors.NoSuchFile:
1519
raise errors.CommandError(gettext('Parent of "%s" does not exist.')
1494
raise errors.BzrCommandError(gettext('Parent of "%s" does not exist.')
1523
1498
if to_dir is None:
1525
1500
# preserve whatever source format we have.
1526
to_dir = br_from.controldir.sprout(
1527
to_transport.base, revision_id,
1528
possible_transports=[to_transport],
1529
accelerator_tree=accelerator_tree, hardlink=hardlink,
1530
stacked=stacked, force_new_repo=standalone,
1531
create_tree_if_local=not no_tree, source_branch=br_from,
1501
to_dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
1502
possible_transports=[to_transport],
1503
accelerator_tree=accelerator_tree,
1504
hardlink=hardlink, stacked=stacked,
1505
force_new_repo=standalone,
1506
create_tree_if_local=not no_tree,
1507
source_branch=br_from)
1533
1508
branch = to_dir.open_branch(
1534
1509
possible_transports=[
1535
br_from.controldir.root_transport, to_transport])
1510
br_from.bzrdir.root_transport, to_transport])
1536
1511
except errors.NoSuchRevision:
1537
1512
to_transport.delete_tree('.')
1538
1513
msg = gettext("The branch {0} has no revision {1}.").format(
1539
1514
from_location, revision)
1540
raise errors.CommandError(msg)
1515
raise errors.BzrCommandError(msg)
1543
1518
to_repo = to_dir.open_repository()
1544
1519
except errors.NoRepositoryPresent:
1545
1520
to_repo = to_dir.create_repository()
1546
1521
to_repo.fetch(br_from.repository, revision_id=revision_id)
1547
branch = br_from.sprout(
1548
to_dir, revision_id=revision_id)
1549
br_from.tags.merge_to(branch.tags)
1522
branch = br_from.sprout(to_dir, revision_id=revision_id)
1523
_merge_tags_if_possible(br_from, branch)
1551
1524
# If the source branch is stacked, the new branch may
1552
1525
# be stacked whether we asked for that explicitly or not.
1553
1526
# We therefore need a try/except here and not just 'if stacked:'
1555
1528
note(gettext('Created new stacked branch referring to %s.') %
1556
branch.get_stacked_on_url())
1557
except (errors.NotStacked, _mod_branch.UnstackableBranchFormat,
1558
errors.UnstackableRepositoryFormat) as e:
1559
revno = branch.revno()
1560
if revno is not None:
1561
note(ngettext('Branched %d revision.',
1562
'Branched %d revisions.',
1563
branch.revno()) % revno)
1565
note(gettext('Created new branch.'))
1529
branch.get_stacked_on_url())
1530
except (errors.NotStacked, errors.UnstackableBranchFormat,
1531
errors.UnstackableRepositoryFormat), e:
1532
note(ngettext('Branched %d revision.', 'Branched %d revisions.', branch.revno()) % branch.revno())
1567
1534
# Bind to the parent
1568
1535
parent_branch = Branch.open(from_location)
1918
1856
class cmd_remove(Command):
1919
1857
__doc__ = """Remove files or directories.
1921
This makes Breezy stop tracking changes to the specified files. Breezy will
1859
This makes Bazaar stop tracking changes to the specified files. Bazaar will
1922
1860
delete them if they can easily be recovered using revert otherwise they
1923
1861
will be backed up (adding an extension of the form .~#~). If no options or
1924
parameters are given Breezy will scan for files that are being tracked by
1925
Breezy but missing in your tree and stop tracking them for you.
1862
parameters are given Bazaar will scan for files that are being tracked by
1863
Bazaar but missing in your tree and stop tracking them for you.
1927
1865
takes_args = ['file*']
1928
1866
takes_options = ['verbose',
1930
'new', help='Only remove files that have never been committed.'),
1931
RegistryOption.from_kwargs('file-deletion-strategy',
1932
'The file deletion mode to be used.',
1933
title='Deletion Strategy', value_switches=True, enum_switch=False,
1934
safe='Backup changed files (default).',
1935
keep='Delete from brz but leave the working copy.',
1936
no_backup='Don\'t backup changed files.'),
1867
Option('new', help='Only remove files that have never been committed.'),
1868
RegistryOption.from_kwargs('file-deletion-strategy',
1869
'The file deletion mode to be used.',
1870
title='Deletion Strategy', value_switches=True, enum_switch=False,
1871
safe='Backup changed files (default).',
1872
keep='Delete from bzr but leave the working copy.',
1873
no_backup='Don\'t backup changed files.'),
1938
1875
aliases = ['rm', 'del']
1939
1876
encoding_type = 'replace'
1941
1878
def run(self, file_list, verbose=False, new=False,
1942
file_deletion_strategy='safe'):
1879
file_deletion_strategy='safe'):
1944
1881
tree, file_list = WorkingTree.open_containing_paths(file_list)
1946
1883
if file_list is not None:
1947
1884
file_list = [f for f in file_list]
1949
self.enter_context(tree.lock_write())
1886
self.add_cleanup(tree.lock_write().unlock)
1950
1887
# Heuristics should probably all move into tree.remove_smart or
1953
1890
added = tree.changes_from(tree.basis_tree(),
1954
specific_files=file_list).added
1955
file_list = sorted([f.path[1] for f in added], reverse=True)
1891
specific_files=file_list).added
1892
file_list = sorted([f[0] for f in added], reverse=True)
1956
1893
if len(file_list) == 0:
1957
raise errors.CommandError(gettext('No matching files.'))
1894
raise errors.BzrCommandError(gettext('No matching files.'))
1958
1895
elif file_list is None:
1959
1896
# missing files show up in iter_changes(basis) as
1960
1897
# versioned-with-no-kind.
1962
1899
for change in tree.iter_changes(tree.basis_tree()):
1963
1900
# Find paths in the working tree that have no kind:
1964
if change.path[1] is not None and change.kind[1] is None:
1965
missing.append(change.path[1])
1901
if change[1][1] is not None and change[6][1] is None:
1902
missing.append(change[1][1])
1966
1903
file_list = sorted(missing, reverse=True)
1967
1904
file_deletion_strategy = 'keep'
1968
1905
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1969
keep_files=file_deletion_strategy == 'keep',
1970
force=(file_deletion_strategy == 'no-backup'))
1906
keep_files=file_deletion_strategy=='keep',
1907
force=(file_deletion_strategy=='no-backup'))
1910
class cmd_file_id(Command):
1911
__doc__ = """Print file_id of a particular file or directory.
1913
The file_id is assigned when the file is first added and remains the
1914
same through all revisions where the file exists, even when it is
1919
_see_also = ['inventory', 'ls']
1920
takes_args = ['filename']
1923
def run(self, filename):
1924
tree, relpath = WorkingTree.open_containing(filename)
1925
i = tree.path2id(relpath)
1927
raise errors.NotVersionedError(filename)
1929
self.outf.write(i + '\n')
1932
class cmd_file_path(Command):
1933
__doc__ = """Print path of file_ids to a file or directory.
1935
This prints one line for each directory down to the target,
1936
starting at the branch root.
1940
takes_args = ['filename']
1943
def run(self, filename):
1944
tree, relpath = WorkingTree.open_containing(filename)
1945
fid = tree.path2id(relpath)
1947
raise errors.NotVersionedError(filename)
1948
segments = osutils.splitpath(relpath)
1949
for pos in range(1, len(segments) + 1):
1950
path = osutils.joinpath(segments[:pos])
1951
self.outf.write("%s\n" % tree.path2id(path))
1973
1954
class cmd_reconcile(Command):
1974
__doc__ = """Reconcile brz metadata in a branch.
1955
__doc__ = """Reconcile bzr metadata in a branch.
1976
1957
This can correct data mismatches that may have been caused by
1977
previous ghost operations or brz upgrades. You should only
1978
need to run this command if 'brz check' or a brz developer
1958
previous ghost operations or bzr upgrades. You should only
1959
need to run this command if 'bzr check' or a bzr developer
1979
1960
advises you to run it.
1981
1962
If a second branch is provided, cross-branch reconciliation is
1982
1963
also attempted, which will check that data like the tree root
1983
id which was not present in very early brz versions is represented
1964
id which was not present in very early bzr versions is represented
1984
1965
correctly in both branches.
1986
1967
At the same time it is run it may recompress data resulting in
2136
2114
branch = create_branch(to_transport.base, format=format,
2137
2115
possible_transports=[to_transport],
2138
2116
force_new_tree=force_new_tree)
2139
a_controldir = branch.controldir
2117
a_bzrdir = branch.bzrdir
2141
from .transport.local import LocalTransport
2142
if a_controldir.has_branch():
2119
from bzrlib.transport.local import LocalTransport
2120
if a_bzrdir.has_branch():
2143
2121
if (isinstance(to_transport, LocalTransport)
2144
and not a_controldir.has_workingtree()):
2145
raise errors.BranchExistsWithoutWorkingTree(location)
2122
and not a_bzrdir.has_workingtree()):
2123
raise errors.BranchExistsWithoutWorkingTree(location)
2146
2124
raise errors.AlreadyBranchError(location)
2147
branch = a_controldir.create_branch()
2148
if not no_tree and not a_controldir.has_workingtree():
2149
a_controldir.create_workingtree()
2125
branch = a_bzrdir.create_branch()
2126
if not no_tree and not a_bzrdir.has_workingtree():
2127
a_bzrdir.create_workingtree()
2150
2128
if append_revisions_only:
2152
2130
branch.set_append_revisions_only(True)
2153
2131
except errors.UpgradeRequired:
2154
raise errors.CommandError(gettext('This branch format cannot be set'
2155
' to append-revisions-only. Try --default.'))
2132
raise errors.BzrCommandError(gettext('This branch format cannot be set'
2133
' to append-revisions-only. Try --default.'))
2156
2134
if not is_quiet():
2157
from .info import describe_layout, describe_format
2135
from bzrlib.info import describe_layout, describe_format
2159
tree = a_controldir.open_workingtree(recommend_upgrade=False)
2137
tree = a_bzrdir.open_workingtree(recommend_upgrade=False)
2160
2138
except (errors.NoWorkingTree, errors.NotLocalUrl):
2162
2140
repository = branch.repository
2163
2141
layout = describe_layout(repository, branch, tree).lower()
2164
format = describe_format(a_controldir, repository, branch, tree)
2142
format = describe_format(a_bzrdir, repository, branch, tree)
2165
2143
self.outf.write(gettext("Created a {0} (format: {1})\n").format(
2167
2145
if repository.is_shared():
2168
# XXX: maybe this can be refactored into transport.path_or_url()
2169
url = repository.controldir.root_transport.external_url()
2146
#XXX: maybe this can be refactored into transport.path_or_url()
2147
url = repository.bzrdir.root_transport.external_url()
2171
2149
url = urlutils.local_path_from_url(url)
2172
except urlutils.InvalidURL:
2150
except errors.InvalidURL:
2174
2152
self.outf.write(gettext("Using shared repository: %s\n") % url)
2177
class cmd_init_shared_repository(Command):
2155
class cmd_init_repository(Command):
2178
2156
__doc__ = """Create a shared repository for branches to share storage space.
2180
2158
New branches created under the repository directory will store their
2181
2159
revisions in the repository, not in the branch directory. For branches
2182
with shared history, this reduces the amount of storage needed and
2160
with shared history, this reduces the amount of storage needed and
2183
2161
speeds up the creation of new branches.
2185
2163
If the --no-trees option is given then the branches in the repository
2186
will not have working trees by default. They will still exist as
2187
directories on disk, but they will not have separate copies of the
2164
will not have working trees by default. They will still exist as
2165
directories on disk, but they will not have separate copies of the
2188
2166
files at a certain revision. This can be useful for repositories that
2189
2167
store branches which are interacted with through checkouts or remote
2190
2168
branches, such as on a server.
2205
2183
_see_also = ['init', 'branch', 'checkout', 'repositories']
2206
2184
takes_args = ["location"]
2207
2185
takes_options = [RegistryOption('format',
2208
help='Specify a format for this repository. See'
2209
' "brz help formats" for details.',
2211
'breezy.controldir', 'format_registry'),
2212
converter=lambda name: controldir.format_registry.make_controldir(
2214
value_switches=True, title='Repository format'),
2186
help='Specify a format for this repository. See'
2187
' "bzr help formats" for details.',
2188
lazy_registry=('bzrlib.controldir', 'format_registry'),
2189
converter=lambda name: controldir.format_registry.make_bzrdir(name),
2190
value_switches=True, title='Repository format'),
2215
2191
Option('no-trees',
2216
help='Branches in the repository will default to'
2217
' not having a working tree.'),
2219
aliases = ["init-shared-repo", "init-repo"]
2192
help='Branches in the repository will default to'
2193
' not having a working tree.'),
2195
aliases = ["init-repo"]
2221
2197
def run(self, location, format=None, no_trees=False):
2222
2198
if format is None:
2223
format = controldir.format_registry.make_controldir('default')
2199
format = controldir.format_registry.make_bzrdir('default')
2225
2201
if location is None:
2228
to_transport = transport.get_transport(location, purpose='write')
2230
if format.fixed_components:
2231
repo_format_name = None
2233
repo_format_name = format.repository_format.get_format_string()
2204
to_transport = transport.get_transport(location)
2235
2206
(repo, newdir, require_stacking, repository_policy) = (
2236
2207
format.initialize_on_transport_ex(to_transport,
2237
create_prefix=True, make_working_trees=not no_trees,
2238
shared_repo=True, force_new_repo=True,
2239
use_existing_dir=True,
2240
repo_format_name=repo_format_name))
2208
create_prefix=True, make_working_trees=not no_trees,
2209
shared_repo=True, force_new_repo=True,
2210
use_existing_dir=True,
2211
repo_format_name=format.repository_format.get_format_string()))
2241
2212
if not is_quiet():
2242
from .info import show_bzrdir_info
2213
from bzrlib.info import show_bzrdir_info
2243
2214
show_bzrdir_info(newdir, verbose=0, outfile=self.outf)
2339
2310
help='Set prefixes added to old and new filenames, as '
2340
2311
'two values separated by a colon. (eg "old/:new/").'),
2342
help='Branch/tree to compare from.',
2313
help='Branch/tree to compare from.',
2346
help='Branch/tree to compare to.',
2317
help='Branch/tree to compare to.',
2351
2322
Option('using',
2352
help='Use this command to compare files.',
2323
help='Use this command to compare files.',
2355
2326
RegistryOption('format',
2357
help='Diff format to use.',
2358
lazy_registry=('breezy.diff', 'format_registry'),
2359
title='Diff format'),
2328
help='Diff format to use.',
2329
lazy_registry=('bzrlib.diff', 'format_registry'),
2330
title='Diff format'),
2360
2331
Option('context',
2361
help='How many lines of context to show.',
2364
RegistryOption.from_kwargs(
2366
help='Color mode to use.',
2367
title='Color Mode', value_switches=False, enum_switch=True,
2368
never='Never colorize output.',
2369
auto='Only colorize output if terminal supports it and STDOUT is a'
2371
always='Always colorize output (default).'),
2374
help=('Warn if trailing whitespace or spurious changes have been'
2332
help='How many lines of context to show.',
2378
2336
aliases = ['di', 'dif']
2379
2337
encoding_type = 'exact'
2381
2339
@display_command
2382
2340
def run(self, revision=None, file_list=None, diff_options=None,
2383
prefix=None, old=None, new=None, using=None, format=None,
2384
context=None, color='never'):
2385
from .diff import (get_trees_and_branches_to_diff_locked,
2341
prefix=None, old=None, new=None, using=None, format=None,
2343
from bzrlib.diff import (get_trees_and_branches_to_diff_locked,
2346
if (prefix is None) or (prefix == '0'):
2389
2347
# diff -p0 format
2392
elif prefix == u'1' or prefix is None:
2393
2351
old_label = 'old/'
2394
2352
new_label = 'new/'
2395
elif u':' in prefix:
2396
old_label, new_label = prefix.split(u":")
2354
old_label, new_label = prefix.split(":")
2398
raise errors.CommandError(gettext(
2356
raise errors.BzrCommandError(gettext(
2399
2357
'--prefix expects two values separated by a colon'
2400
2358
' (eg "old/:new/")'))
2402
2360
if revision and len(revision) > 2:
2403
raise errors.CommandError(gettext('brz diff --revision takes exactly'
2404
' one or two revision specifiers'))
2361
raise errors.BzrCommandError(gettext('bzr diff --revision takes exactly'
2362
' one or two revision specifiers'))
2406
2364
if using is not None and format is not None:
2407
raise errors.CommandError(gettext(
2365
raise errors.BzrCommandError(gettext(
2408
2366
'{0} and {1} are mutually exclusive').format(
2409
2367
'--using', '--format'))
2411
2369
(old_tree, new_tree,
2412
2370
old_branch, new_branch,
2413
2371
specific_files, extra_trees) = get_trees_and_branches_to_diff_locked(
2414
file_list, revision, old, new, self._exit_stack, apply_view=True)
2372
file_list, revision, old, new, self.add_cleanup, apply_view=True)
2415
2373
# GNU diff on Windows uses ANSI encoding for filenames
2416
2374
path_encoding = osutils.get_diff_header_encoding()
2419
from .terminal import has_ansi_colors
2420
if has_ansi_colors():
2424
if 'always' == color:
2425
from .colordiff import DiffWriter
2426
outf = DiffWriter(outf)
2427
return show_diff_trees(old_tree, new_tree, outf,
2375
return show_diff_trees(old_tree, new_tree, sys.stdout,
2428
2376
specific_files=specific_files,
2429
2377
external_diff_options=diff_options,
2430
2378
old_label=old_label, new_label=new_label,
2698
2647
takes_args = ['file*']
2699
2648
_see_also = ['log-formats', 'revisionspec']
2700
2649
takes_options = [
2702
help='Show from oldest to newest.'),
2704
custom_help('verbose',
2705
help='Show files changed in each revision.'),
2709
type=breezy.option._parse_revision_str,
2711
help='Show just the specified revision.'
2712
' See also "help revisionspec".'),
2714
RegistryOption('authors',
2715
'What names to list as authors - first, all or committer.',
2718
'breezy.log', 'author_list_registry'),
2722
help='Number of levels to display - 0 for all, 1 for flat.',
2724
type=_parse_levels),
2726
help='Show revisions whose message matches this '
2727
'regular expression.',
2732
help='Limit the output to the first N revisions.',
2737
help='Show changes made in each revision as a patch.'),
2738
Option('include-merged',
2739
help='Show merged revisions like --levels 0 does.'),
2740
Option('include-merges', hidden=True,
2741
help='Historical alias for --include-merged.'),
2742
Option('omit-merges',
2743
help='Do not report commits with more than one parent.'),
2744
Option('exclude-common-ancestry',
2745
help='Display only the revisions that are not part'
2746
' of both ancestries (require -rX..Y).'
2748
Option('signatures',
2749
help='Show digital signature validity.'),
2752
help='Show revisions whose properties match this '
2755
ListOption('match-message',
2756
help='Show revisions whose message matches this '
2759
ListOption('match-committer',
2651
help='Show from oldest to newest.'),
2653
custom_help('verbose',
2654
help='Show files changed in each revision.'),
2658
type=bzrlib.option._parse_revision_str,
2660
help='Show just the specified revision.'
2661
' See also "help revisionspec".'),
2663
RegistryOption('authors',
2664
'What names to list as authors - first, all or committer.',
2666
lazy_registry=('bzrlib.log', 'author_list_registry'),
2670
help='Number of levels to display - 0 for all, 1 for flat.',
2672
type=_parse_levels),
2674
help='Show revisions whose message matches this '
2675
'regular expression.',
2680
help='Limit the output to the first N revisions.',
2685
help='Show changes made in each revision as a patch.'),
2686
Option('include-merged',
2687
help='Show merged revisions like --levels 0 does.'),
2688
Option('include-merges', hidden=True,
2689
help='Historical alias for --include-merged.'),
2690
Option('omit-merges',
2691
help='Do not report commits with more than one parent.'),
2692
Option('exclude-common-ancestry',
2693
help='Display only the revisions that are not part'
2694
' of both ancestries (require -rX..Y).'
2696
Option('signatures',
2697
help='Show digital signature validity.'),
2700
help='Show revisions whose properties match this '
2703
ListOption('match-message',
2704
help='Show revisions whose message matches this '
2707
ListOption('match-committer',
2760
2708
help='Show revisions whose committer matches this '
2763
ListOption('match-author',
2711
ListOption('match-author',
2764
2712
help='Show revisions whose authors match this '
2767
ListOption('match-bugs',
2715
ListOption('match-bugs',
2768
2716
help='Show revisions whose bugs match this '
2772
2720
encoding_type = 'replace'
2774
2722
@display_command
3018
2979
_see_also = ['status', 'cat']
3019
2980
takes_args = ['path?']
3020
2981
takes_options = [
3023
Option('recursive', short_name='R',
3024
help='Recurse into subdirectories.'),
3026
help='Print paths relative to the root of the branch.'),
3027
Option('unknown', short_name='u',
3028
help='Print unknown files.'),
3029
Option('versioned', help='Print versioned files.',
3031
Option('ignored', short_name='i',
3032
help='Print ignored files.'),
3033
Option('kind', short_name='k',
3034
help=('List entries of a particular kind: file, '
3035
'directory, symlink, tree-reference.'),
2984
Option('recursive', short_name='R',
2985
help='Recurse into subdirectories.'),
2987
help='Print paths relative to the root of the branch.'),
2988
Option('unknown', short_name='u',
2989
help='Print unknown files.'),
2990
Option('versioned', help='Print versioned files.',
2992
Option('ignored', short_name='i',
2993
help='Print ignored files.'),
2994
Option('kind', short_name='k',
2995
help='List entries of a particular kind: file, directory, symlink.',
3042
3001
@display_command
3043
3002
def run(self, revision=None, verbose=False,
3044
3003
recursive=False, from_root=False,
3045
3004
unknown=False, versioned=False, ignored=False,
3046
3005
null=False, kind=None, show_ids=False, path=None, directory=None):
3048
if kind and kind not in ('file', 'directory', 'symlink', 'tree-reference'):
3049
raise errors.CommandError(gettext('invalid kind specified'))
3007
if kind and kind not in ('file', 'directory', 'symlink'):
3008
raise errors.BzrCommandError(gettext('invalid kind specified'))
3051
3010
if verbose and null:
3052
raise errors.CommandError(
3053
gettext('Cannot set both --verbose and --null'))
3011
raise errors.BzrCommandError(gettext('Cannot set both --verbose and --null'))
3054
3012
all = not (unknown or versioned or ignored)
3056
selection = {'I': ignored, '?': unknown, 'V': versioned}
3014
selection = {'I':ignored, '?':unknown, 'V':versioned}
3058
3016
if path is None:
3062
raise errors.CommandError(gettext('cannot specify both --from-root'
3020
raise errors.BzrCommandError(gettext('cannot specify both --from-root'
3065
3023
tree, branch, relpath = \
3066
3024
_open_directory_or_containing_tree_or_branch(fs_path, directory)
3443
3378
def run(self, filename, revision=None, name_from_revision=False,
3444
3379
filters=False, directory=None):
3445
3380
if revision is not None and len(revision) != 1:
3446
raise errors.CommandError(gettext("brz cat --revision takes exactly"
3447
" one revision specifier"))
3381
raise errors.BzrCommandError(gettext("bzr cat --revision takes exactly"
3382
" one revision specifier"))
3448
3383
tree, branch, relpath = \
3449
3384
_open_directory_or_containing_tree_or_branch(filename, directory)
3450
self.enter_context(branch.lock_read())
3385
self.add_cleanup(branch.lock_read().unlock)
3451
3386
return self._run(tree, branch, relpath, filename, revision,
3452
3387
name_from_revision, filters)
3454
3389
def _run(self, tree, b, relpath, filename, revision, name_from_revision,
3457
3391
if tree is None:
3458
3392
tree = b.basis_tree()
3459
3393
rev_tree = _get_one_revision_tree('cat', revision, branch=b)
3460
self.enter_context(rev_tree.lock_read())
3394
self.add_cleanup(rev_tree.lock_read().unlock)
3396
old_file_id = rev_tree.path2id(relpath)
3398
# TODO: Split out this code to something that generically finds the
3399
# best id for a path across one or more trees; it's like
3400
# find_ids_across_trees but restricted to find just one. -- mbp
3462
3402
if name_from_revision:
3463
3403
# Try in revision if requested
3464
if not rev_tree.is_versioned(relpath):
3465
raise errors.CommandError(gettext(
3404
if old_file_id is None:
3405
raise errors.BzrCommandError(gettext(
3466
3406
"{0!r} is not present in revision {1}").format(
3467
3407
filename, rev_tree.get_revision_id()))
3468
rev_tree_path = relpath
3409
actual_file_id = old_file_id
3471
rev_tree_path = _mod_tree.find_previous_path(
3472
tree, rev_tree, relpath)
3473
except errors.NoSuchFile:
3474
rev_tree_path = None
3476
if rev_tree_path is None:
3477
# Path didn't exist in working tree
3478
if not rev_tree.is_versioned(relpath):
3479
raise errors.CommandError(gettext(
3480
"{0!r} is not present in revision {1}").format(
3481
filename, rev_tree.get_revision_id()))
3483
# Fall back to the same path in the basis tree, if present.
3484
rev_tree_path = relpath
3411
cur_file_id = tree.path2id(relpath)
3412
if cur_file_id is not None and rev_tree.has_id(cur_file_id):
3413
actual_file_id = cur_file_id
3414
elif old_file_id is not None:
3415
actual_file_id = old_file_id
3417
raise errors.BzrCommandError(gettext(
3418
"{0!r} is not present in revision {1}").format(
3419
filename, rev_tree.get_revision_id()))
3487
from .filter_tree import ContentFilterTree
3488
filter_tree = ContentFilterTree(
3489
rev_tree, rev_tree._content_filter_stack)
3490
fileobj = filter_tree.get_file(rev_tree_path)
3421
from bzrlib.filter_tree import ContentFilterTree
3422
filter_tree = ContentFilterTree(rev_tree,
3423
rev_tree._content_filter_stack)
3424
content = filter_tree.get_file_text(actual_file_id)
3492
fileobj = rev_tree.get_file(rev_tree_path)
3493
shutil.copyfileobj(fileobj, self.outf)
3426
content = rev_tree.get_file_text(actual_file_id)
3494
3427
self.cleanup_now()
3428
self.outf.write(content)
3497
3431
class cmd_local_time_offset(Command):
3498
3432
__doc__ = """Show the offset in seconds from GMT to local time."""
3501
3434
@display_command
3503
3436
self.outf.write("%s\n" % osutils.local_time_offset())
3506
3440
class cmd_commit(Command):
3507
3441
__doc__ = """Commit changes into a new revision.
3539
3473
"John Doe <jdoe@example.com>". If there is more than one author of
3540
3474
the change you can specify the option multiple times, once for each
3545
3479
A common mistake is to forget to add a new file or directory before
3546
3480
running the commit command. The --strict option checks for unknown
3547
3481
files and aborts the commit if any are found. More advanced pre-commit
3548
checks can be implemented by defining hooks. See ``brz help hooks``
3482
checks can be implemented by defining hooks. See ``bzr help hooks``
3551
3485
:Things to note:
3553
If you accidentally commit the wrong changes or make a spelling
3487
If you accidentially commit the wrong changes or make a spelling
3554
3488
mistake in the commit message say, you can use the uncommit command
3555
to undo it. See ``brz help uncommit`` for details.
3489
to undo it. See ``bzr help uncommit`` for details.
3557
3491
Hooks can also be configured to run after a commit. This allows you
3558
3492
to trigger updates to external systems like bug trackers. The --fixes
3559
3493
option can be used to record the association between a revision and
3560
one or more bugs. See ``brz help bugs`` for details.
3494
one or more bugs. See ``bzr help bugs`` for details.
3563
3497
_see_also = ['add', 'bugs', 'hooks', 'uncommit']
3564
3498
takes_args = ['selected*']
3565
3499
takes_options = [
3567
'exclude', type=str, short_name='x',
3568
help="Do not consider changes made to a given path."),
3569
Option('message', type=str,
3571
help="Description of the new revision."),
3574
help='Commit even if nothing has changed.'),
3575
Option('file', type=str,
3578
help='Take commit message from this file.'),
3580
help="Refuse to commit if there are unknown "
3581
"files in the working tree."),
3582
Option('commit-time', type=str,
3583
help="Manually set a commit time using commit date "
3584
"format, e.g. '2009-10-10 08:00:00 +0100'."),
3587
help="Link to a related bug. (see \"brz help bugs\")."),
3590
help="Mark a bug as being fixed by this revision "
3591
"(see \"brz help bugs\")."),
3594
help="Set the author's name, if it's different "
3595
"from the committer."),
3597
help="Perform a local commit in a bound "
3598
"branch. Local commits are not pushed to "
3599
"the master branch until a normal commit "
3602
Option('show-diff', short_name='p',
3603
help='When no message is supplied, show the diff along'
3604
' with the status summary in the message editor.'),
3606
help='When committing to a foreign version control '
3607
'system do not push data that can not be natively '
3500
ListOption('exclude', type=str, short_name='x',
3501
help="Do not consider changes made to a given path."),
3502
Option('message', type=unicode,
3504
help="Description of the new revision."),
3507
help='Commit even if nothing has changed.'),
3508
Option('file', type=str,
3511
help='Take commit message from this file.'),
3513
help="Refuse to commit if there are unknown "
3514
"files in the working tree."),
3515
Option('commit-time', type=str,
3516
help="Manually set a commit time using commit date "
3517
"format, e.g. '2009-10-10 08:00:00 +0100'."),
3518
ListOption('fixes', type=str,
3519
help="Mark a bug as being fixed by this revision "
3520
"(see \"bzr help bugs\")."),
3521
ListOption('author', type=unicode,
3522
help="Set the author's name, if it's different "
3523
"from the committer."),
3525
help="Perform a local commit in a bound "
3526
"branch. Local commits are not pushed to "
3527
"the master branch until a normal commit "
3530
Option('show-diff', short_name='p',
3531
help='When no message is supplied, show the diff along'
3532
' with the status summary in the message editor.'),
3534
help='When committing to a foreign version control '
3535
'system do not push data that can not be natively '
3609
3538
aliases = ['ci', 'checkin']
3611
def _iter_bug_urls(self, bugs, branch, status):
3612
default_bugtracker = None
3540
def _iter_bug_fix_urls(self, fixes, branch):
3541
default_bugtracker = None
3613
3542
# Configure the properties for bug fixing attributes.
3615
tokens = bug.split(':')
3543
for fixed_bug in fixes:
3544
tokens = fixed_bug.split(':')
3616
3545
if len(tokens) == 1:
3617
3546
if default_bugtracker is None:
3618
3547
branch_config = branch.get_config_stack()
3619
3548
default_bugtracker = branch_config.get(
3621
3550
if default_bugtracker is None:
3622
raise errors.CommandError(gettext(
3551
raise errors.BzrCommandError(gettext(
3623
3552
"No tracker specified for bug %s. Use the form "
3624
3553
"'tracker:id' or specify a default bug tracker "
3625
3554
"using the `bugtracker` option.\nSee "
3626
"\"brz help bugs\" for more information on this "
3627
"feature. Commit refused.") % bug)
3555
"\"bzr help bugs\" for more information on this "
3556
"feature. Commit refused.") % fixed_bug)
3628
3557
tag = default_bugtracker
3629
3558
bug_id = tokens[0]
3630
3559
elif len(tokens) != 2:
3631
raise errors.CommandError(gettext(
3560
raise errors.BzrCommandError(gettext(
3632
3561
"Invalid bug %s. Must be in the form of 'tracker:id'. "
3633
"See \"brz help bugs\" for more information on this "
3634
"feature.\nCommit refused.") % bug)
3562
"See \"bzr help bugs\" for more information on this "
3563
"feature.\nCommit refused.") % fixed_bug)
3636
3565
tag, bug_id = tokens
3638
yield bugtracker.get_bug_url(tag, branch, bug_id), status
3639
except bugtracker.UnknownBugTrackerAbbreviation:
3640
raise errors.CommandError(gettext(
3641
'Unrecognized bug %s. Commit refused.') % bug)
3642
except bugtracker.MalformedBugIdentifier as e:
3643
raise errors.CommandError(gettext(
3644
u"%s\nCommit refused.") % (e,))
3567
yield bugtracker.get_bug_url(tag, branch, bug_id)
3568
except errors.UnknownBugTrackerAbbreviation:
3569
raise errors.BzrCommandError(gettext(
3570
'Unrecognized bug %s. Commit refused.') % fixed_bug)
3571
except errors.MalformedBugIdentifier, e:
3572
raise errors.BzrCommandError(gettext(
3573
"%s\nCommit refused.") % (str(e),))
3646
3575
def run(self, message=None, file=None, verbose=False, selected_list=None,
3647
unchanged=False, strict=False, local=False, fixes=None, bugs=None,
3576
unchanged=False, strict=False, local=False, fixes=None,
3648
3577
author=None, show_diff=False, exclude=None, commit_time=None,
3651
from .commit import (
3579
from bzrlib.errors import (
3652
3580
PointlessCommit,
3654
from .errors import (
3655
3581
ConflictsInTree,
3656
3582
StrictCommitFailed
3658
from .msgeditor import (
3584
from bzrlib.msgeditor import (
3659
3585
edit_commit_message_encoded,
3660
3586
generate_commit_message_template,
3661
3587
make_commit_message_template_encoded,
4502
4405
change_reporter = delta._ChangeReporter(
4503
4406
unversioned_filter=tree.is_ignored, view_info=view_info)
4504
4407
pb = ui.ui_factory.nested_progress_bar()
4505
self.enter_context(pb)
4506
self.enter_context(tree.lock_write())
4408
self.add_cleanup(pb.finished)
4409
self.add_cleanup(tree.lock_write().unlock)
4507
4410
if location is not None:
4509
mergeable = _mod_mergeable.read_mergeable_from_url(
4510
location, possible_transports=possible_transports)
4412
mergeable = bundle.read_mergeable_from_url(location,
4413
possible_transports=possible_transports)
4511
4414
except errors.NotABundle:
4512
4415
mergeable = None
4514
4417
if uncommitted:
4515
raise errors.CommandError(gettext('Cannot use --uncommitted'
4516
' with bundles or merge directives.'))
4418
raise errors.BzrCommandError(gettext('Cannot use --uncommitted'
4419
' with bundles or merge directives.'))
4518
4421
if revision is not None:
4519
raise errors.CommandError(gettext(
4422
raise errors.BzrCommandError(gettext(
4520
4423
'Cannot use -r with merge directives or bundles'))
4521
4424
merger, verified = _mod_merge.Merger.from_mergeable(tree,
4524
4427
if merger is None and uncommitted:
4525
4428
if revision is not None and len(revision) > 0:
4526
raise errors.CommandError(gettext('Cannot use --uncommitted and'
4527
' --revision at the same time.'))
4429
raise errors.BzrCommandError(gettext('Cannot use --uncommitted and'
4430
' --revision at the same time.'))
4528
4431
merger = self.get_merger_from_uncommitted(tree, location, None)
4529
4432
allow_pending = False
4531
4434
if merger is None:
4532
4435
merger, allow_pending = self._get_merger_from_branch(tree,
4533
location, revision, remember, possible_transports, None)
4436
location, revision, remember, possible_transports, None)
4535
4438
merger.merge_type = merge_type
4536
4439
merger.reprocess = reprocess
4537
4440
merger.show_base = show_base
4538
4441
self.sanity_check_merger(merger)
4539
4442
if (merger.base_rev_id == merger.other_rev_id and
4540
merger.other_rev_id is not None):
4443
merger.other_rev_id is not None):
4541
4444
# check if location is a nonexistent file (and not a branch) to
4542
4445
# disambiguate the 'Nothing to do'
4543
4446
if merger.interesting_files:
4544
4447
if not merger.other_tree.has_filename(
4545
merger.interesting_files[0]):
4448
merger.interesting_files[0]):
4546
4449
note(gettext("merger: ") + str(merger))
4547
4450
raise errors.PathsDoNotExist([location])
4548
4451
note(gettext('Nothing to do.'))
4550
4453
if pull and not preview:
4551
4454
if merger.interesting_files is not None:
4552
raise errors.CommandError(
4553
gettext('Cannot pull individual files'))
4455
raise errors.BzrCommandError(gettext('Cannot pull individual files'))
4554
4456
if (merger.base_rev_id == tree.last_revision()):
4555
4457
result = tree.pull(merger.other_branch, False,
4556
4458
merger.other_rev_id)
4557
4459
result.report(self.outf)
4559
4461
if merger.this_basis is None:
4560
raise errors.CommandError(gettext(
4462
raise errors.BzrCommandError(gettext(
4561
4463
"This branch has no commits."
4562
" (perhaps you would prefer 'brz pull')"))
4464
" (perhaps you would prefer 'bzr pull')"))
4564
4466
return self._do_preview(merger)
4565
4467
elif interactive:
4771
4664
Re-do the merge of all conflicted files, and show the base text in
4772
4665
conflict regions, in addition to the usual THIS and OTHER texts::
4774
brz remerge --show-base
4667
bzr remerge --show-base
4776
4669
Re-do the merge of "foobar", using the weave merge algorithm, with
4777
4670
additional processing to reduce the size of conflict regions::
4779
brz remerge --merge-type weave --reprocess foobar
4672
bzr remerge --merge-type weave --reprocess foobar
4781
4674
takes_args = ['file*']
4782
4675
takes_options = [
4786
help="Show base revision text in conflicts."),
4679
help="Show base revision text in conflicts."),
4789
4682
def run(self, file_list=None, merge_type=None, show_base=False,
4790
4683
reprocess=False):
4791
from .conflicts import restore
4684
from bzrlib.conflicts import restore
4792
4685
if merge_type is None:
4793
4686
merge_type = _mod_merge.Merge3Merger
4794
4687
tree, file_list = WorkingTree.open_containing_paths(file_list)
4795
self.enter_context(tree.lock_write())
4688
self.add_cleanup(tree.lock_write().unlock)
4796
4689
parents = tree.get_parent_ids()
4797
4690
if len(parents) != 2:
4798
raise errors.CommandError(
4799
gettext("Sorry, remerge only works after normal"
4800
" merges. Not cherrypicking or multi-merges."))
4801
interesting_files = None
4691
raise errors.BzrCommandError(gettext("Sorry, remerge only works after normal"
4692
" merges. Not cherrypicking or"
4694
repository = tree.branch.repository
4695
interesting_ids = None
4802
4696
new_conflicts = []
4803
4697
conflicts = tree.conflicts()
4804
4698
if file_list is not None:
4805
interesting_files = set()
4699
interesting_ids = set()
4806
4700
for filename in file_list:
4807
if not tree.is_versioned(filename):
4701
file_id = tree.path2id(filename)
4808
4703
raise errors.NotVersionedError(filename)
4809
interesting_files.add(filename)
4810
if tree.kind(filename) != "directory":
4704
interesting_ids.add(file_id)
4705
if tree.kind(file_id) != "directory":
4813
for path, ie in tree.iter_entries_by_dir(
4814
specific_files=[filename]):
4815
interesting_files.add(path)
4708
# FIXME: Support nested trees
4709
for name, ie in tree.root_inventory.iter_entries(file_id):
4710
interesting_ids.add(ie.file_id)
4816
4711
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
4818
4713
# Remerge only supports resolving contents conflicts
4819
4714
allowed_conflicts = ('text conflict', 'contents conflict')
4820
4715
restore_files = [c.path for c in conflicts
4821
4716
if c.typestring in allowed_conflicts]
4822
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_files)
4717
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
4823
4718
tree.set_conflicts(ConflictList(new_conflicts))
4824
4719
if file_list is not None:
4825
4720
restore_files = file_list
5283
5189
@display_command
5284
5190
def run(self, filename, all=False, long=False, revision=None,
5285
5191
show_ids=False, directory=None):
5286
from .annotate import (
5192
from bzrlib.annotate import (
5287
5193
annotate_file_tree,
5289
5195
wt, branch, relpath = \
5290
5196
_open_directory_or_containing_tree_or_branch(filename, directory)
5291
5197
if wt is not None:
5292
self.enter_context(wt.lock_read())
5198
self.add_cleanup(wt.lock_read().unlock)
5294
self.enter_context(branch.lock_read())
5200
self.add_cleanup(branch.lock_read().unlock)
5295
5201
tree = _get_one_revision_tree('annotate', revision, branch=branch)
5296
self.enter_context(tree.lock_read())
5297
if wt is not None and revision is None:
5298
if not wt.is_versioned(relpath):
5299
raise errors.NotVersionedError(relpath)
5202
self.add_cleanup(tree.lock_read().unlock)
5203
if wt is not None and revision is None:
5204
file_id = wt.path2id(relpath)
5206
file_id = tree.path2id(relpath)
5208
raise errors.NotVersionedError(filename)
5209
if wt is not None and revision is None:
5300
5210
# If there is a tree and we're not annotating historical
5301
5211
# versions, annotate the working tree's content.
5302
annotate_file_tree(wt, relpath, self.outf, long, all,
5212
annotate_file_tree(wt, file_id, self.outf, long, all,
5305
if not tree.is_versioned(relpath):
5306
raise errors.NotVersionedError(relpath)
5307
annotate_file_tree(tree, relpath, self.outf, long, all,
5308
show_ids=show_ids, branch=branch)
5215
annotate_file_tree(tree, file_id, self.outf, long, all,
5216
show_ids=show_ids, branch=branch)
5311
5219
class cmd_re_sign(Command):
5312
5220
__doc__ = """Create a digital signature for an existing revision."""
5313
5221
# TODO be able to replace existing ones.
5315
hidden = True # is this right ?
5223
hidden = True # is this right ?
5316
5224
takes_args = ['revision_id*']
5317
5225
takes_options = ['directory', 'revision']
5319
5227
def run(self, revision_id_list=None, revision=None, directory=u'.'):
5320
5228
if revision_id_list is not None and revision is not None:
5321
raise errors.CommandError(
5322
gettext('You can only supply one of revision_id or --revision'))
5229
raise errors.BzrCommandError(gettext('You can only supply one of revision_id or --revision'))
5323
5230
if revision_id_list is None and revision is None:
5324
raise errors.CommandError(
5325
gettext('You must supply either --revision or a revision_id'))
5231
raise errors.BzrCommandError(gettext('You must supply either --revision or a revision_id'))
5326
5232
b = WorkingTree.open_containing(directory)[0].branch
5327
self.enter_context(b.lock_write())
5233
self.add_cleanup(b.lock_write().unlock)
5328
5234
return self._run(b, revision_id_list, revision)
5330
5236
def _run(self, b, revision_id_list, revision):
5331
from .repository import WriteGroup
5237
import bzrlib.gpg as gpg
5332
5238
gpg_strategy = gpg.GPGStrategy(b.get_config_stack())
5333
5239
if revision_id_list is not None:
5334
with WriteGroup(b.repository):
5240
b.repository.start_write_group()
5335
5242
for revision_id in revision_id_list:
5336
revision_id = cache_utf8.encode(revision_id)
5337
5243
b.repository.sign_revision(revision_id, gpg_strategy)
5245
b.repository.abort_write_group()
5248
b.repository.commit_write_group()
5338
5249
elif revision is not None:
5339
5250
if len(revision) == 1:
5340
5251
revno, rev_id = revision[0].in_history(b)
5341
with WriteGroup(b.repository):
5252
b.repository.start_write_group()
5342
5254
b.repository.sign_revision(rev_id, gpg_strategy)
5256
b.repository.abort_write_group()
5259
b.repository.commit_write_group()
5343
5260
elif len(revision) == 2:
5344
5261
# are they both on rh- if so we can walk between them
5345
5262
# might be nice to have a range helper for arbitrary
6342
6257
except errors.NotBranchError:
6344
6259
had_explicit_nick = False
6346
possible_transports.append(branch.user_transport)
6347
6260
if create_branch:
6348
6261
if branch is None:
6349
raise errors.CommandError(
6262
raise errors.BzrCommandError(
6350
6263
gettext('cannot create branch without source branch'))
6351
to_location = lookup_new_sibling_branch(
6352
control_dir, to_location,
6353
possible_transports=possible_transports)
6354
if revision is not None:
6355
revision = revision.as_revision_id(branch)
6356
to_branch = branch.controldir.sprout(
6358
possible_transports=possible_transports,
6359
revision_id=revision,
6360
source_branch=branch).open_branch()
6264
to_location = lookup_new_sibling_branch(control_dir, to_location,
6265
possible_transports=possible_transports)
6266
to_branch = branch.bzrdir.sprout(to_location,
6267
possible_transports=possible_transports,
6268
source_branch=branch).open_branch()
6363
to_branch = Branch.open(
6364
to_location, possible_transports=possible_transports)
6271
to_branch = Branch.open(to_location,
6272
possible_transports=possible_transports)
6365
6273
except errors.NotBranchError:
6366
to_branch = open_sibling_branch(
6367
control_dir, to_location,
6274
to_branch = open_sibling_branch(control_dir, to_location,
6368
6275
possible_transports=possible_transports)
6369
if revision is not None:
6370
revision = revision.as_revision_id(to_branch)
6371
possible_transports.append(to_branch.user_transport)
6373
switch.switch(control_dir, to_branch, force, revision_id=revision,
6374
store_uncommitted=store,
6375
possible_transports=possible_transports)
6376
except controldir.BranchReferenceLoop:
6377
raise errors.CommandError(
6378
gettext('switching would create a branch reference loop. '
6379
'Use the "bzr up" command to switch to a '
6380
'different revision.'))
6276
if revision is not None:
6277
revision = revision.as_revision_id(to_branch)
6278
switch.switch(control_dir, to_branch, force, revision_id=revision,
6279
store_uncommitted=store)
6381
6280
if had_explicit_nick:
6382
branch = control_dir.open_branch() # get the new branch!
6281
branch = control_dir.open_branch() #get the new branch!
6383
6282
branch.nick = to_branch.nick
6385
if to_branch.controldir.control_url != control_dir.control_url:
6386
note(gettext('Switched to branch %s at %s'),
6387
to_branch.name, urlutils.unescape_for_display(to_branch.base, 'utf-8'))
6389
note(gettext('Switched to branch %s'), to_branch.name)
6391
note(gettext('Switched to branch at %s'),
6392
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
6283
note(gettext('Switched to branch: %s'),
6284
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
6395
6288
class cmd_view(Command):
6815
6703
__doc__ = """Export command helps and error messages in po format."""
6818
takes_options = [Option('plugin',
6819
help='Export help text from named command '
6706
takes_options = [Option('plugin',
6707
help='Export help text from named command '\
6820
6708
'(defaults to all built in commands).',
6822
6710
Option('include-duplicates',
6823
6711
help='Output multiple copies of the same msgid '
6824
6712
'string if it appears more than once.'),
6827
6715
def run(self, plugin=None, include_duplicates=False):
6828
from .export_pot import export_pot
6716
from bzrlib.export_pot import export_pot
6829
6717
export_pot(self.outf, plugin, include_duplicates)
6832
class cmd_import(Command):
6833
__doc__ = """Import sources from a directory, tarball or zip file
6835
This command will import a directory, tarball or zip file into a bzr
6836
tree, replacing any versioned files already present. If a directory is
6837
specified, it is used as the target. If the directory does not exist, or
6838
is not versioned, it is created.
6840
Tarballs may be gzip or bzip2 compressed. This is autodetected.
6842
If the tarball or zip has a single root directory, that directory is
6843
stripped when extracting the tarball. This is not done for directories.
6846
takes_args = ['source', 'tree?']
6848
def run(self, source, tree=None):
6849
from .upstream_import import do_import
6850
do_import(source, tree)
6853
class cmd_link_tree(Command):
6854
__doc__ = """Hardlink matching files to another tree.
6856
Only files with identical content and execute bit will be linked.
6859
takes_args = ['location']
6861
def run(self, location):
6862
from .transform import link_tree
6863
target_tree = WorkingTree.open_containing(".")[0]
6864
source_tree = WorkingTree.open(location)
6865
with target_tree.lock_write(), source_tree.lock_read():
6866
link_tree(target_tree, source_tree)
6869
class cmd_fetch_ghosts(Command):
6870
__doc__ = """Attempt to retrieve ghosts from another branch.
6872
If the other branch is not supplied, the last-pulled branch is used.
6876
aliases = ['fetch-missing']
6877
takes_args = ['branch?']
6878
takes_options = [Option('no-fix', help="Skip additional synchonization.")]
6880
def run(self, branch=None, no_fix=False):
6881
from .fetch_ghosts import GhostFetcher
6882
installed, failed = GhostFetcher.from_cmdline(branch).run()
6883
if len(installed) > 0:
6884
self.outf.write("Installed:\n")
6885
for rev in installed:
6886
self.outf.write(rev.decode('utf-8') + "\n")
6888
self.outf.write("Still missing:\n")
6890
self.outf.write(rev.decode('utf-8') + "\n")
6891
if not no_fix and len(installed) > 0:
6892
cmd_reconcile().run(".")
6895
class cmd_grep(Command):
6896
"""Print lines matching PATTERN for specified files and revisions.
6898
This command searches the specified files and revisions for a given
6899
pattern. The pattern is specified as a Python regular expressions[1].
6901
If the file name is not specified, the revisions starting with the
6902
current directory are searched recursively. If the revision number is
6903
not specified, the working copy is searched. To search the last committed
6904
revision, use the '-r -1' or '-r last:1' option.
6906
Unversioned files are not searched unless explicitly specified on the
6907
command line. Unversioned directores are not searched.
6909
When searching a pattern, the output is shown in the 'filepath:string'
6910
format. If a revision is explicitly searched, the output is shown as
6911
'filepath~N:string', where N is the revision number.
6913
--include and --exclude options can be used to search only (or exclude
6914
from search) files with base name matches the specified Unix style GLOB
6915
pattern. The GLOB pattern an use *, ?, and [...] as wildcards, and \\
6916
to quote wildcard or backslash character literally. Note that the glob
6917
pattern is not a regular expression.
6919
[1] http://docs.python.org/library/re.html#regular-expression-syntax
6922
encoding_type = 'replace'
6923
takes_args = ['pattern', 'path*']
6927
Option('color', type=str, argname='when',
6928
help='Show match in color. WHEN is never, always or auto.'),
6929
Option('diff', short_name='p',
6930
help='Grep for pattern in changeset for each revision.'),
6931
ListOption('exclude', type=str, argname='glob', short_name='X',
6932
help="Skip files whose base name matches GLOB."),
6933
ListOption('include', type=str, argname='glob', short_name='I',
6934
help="Search only files whose base name matches GLOB."),
6935
Option('files-with-matches', short_name='l',
6936
help='Print only the name of each input file in '
6937
'which PATTERN is found.'),
6938
Option('files-without-match', short_name='L',
6939
help='Print only the name of each input file in '
6940
'which PATTERN is not found.'),
6941
Option('fixed-string', short_name='F',
6942
help='Interpret PATTERN is a single fixed string (not regex).'),
6944
help='Search for pattern starting from the root of the branch. '
6945
'(implies --recursive)'),
6946
Option('ignore-case', short_name='i',
6947
help='Ignore case distinctions while matching.'),
6949
help='Number of levels to display - 0 for all, 1 for collapsed '
6952
type=_parse_levels),
6953
Option('line-number', short_name='n',
6954
help='Show 1-based line number.'),
6955
Option('no-recursive',
6956
help="Don't recurse into subdirectories. (default is --recursive)"),
6957
Option('null', short_name='Z',
6958
help='Write an ASCII NUL (\\0) separator '
6959
'between output lines rather than a newline.'),
6963
def run(self, verbose=False, ignore_case=False, no_recursive=False,
6964
from_root=False, null=False, levels=None, line_number=False,
6965
path_list=None, revision=None, pattern=None, include=None,
6966
exclude=None, fixed_string=False, files_with_matches=False,
6967
files_without_match=False, color=None, diff=False):
6968
from breezy import _termcolor
6971
if path_list is None:
6975
raise errors.CommandError(
6976
'cannot specify both --from-root and PATH.')
6978
if files_with_matches and files_without_match:
6979
raise errors.CommandError(
6980
'cannot specify both '
6981
'-l/--files-with-matches and -L/--files-without-matches.')
6983
global_config = _mod_config.GlobalConfig()
6986
color = global_config.get_user_option('grep_color')
6991
if color not in ['always', 'never', 'auto']:
6992
raise errors.CommandError('Valid values for --color are '
6993
'"always", "never" or "auto".')
6999
if revision is not None or levels == 0:
7000
# print revision numbers as we may be showing multiple revisions
7007
if not ignore_case and grep.is_fixed_string(pattern):
7008
# if the pattern isalnum, implicitly use to -F for faster grep
7010
elif ignore_case and fixed_string:
7011
# GZ 2010-06-02: Fall back to regexp rather than lowercasing
7012
# pattern and text which will cause pain later
7013
fixed_string = False
7014
pattern = re.escape(pattern)
7017
re_flags = re.MULTILINE
7019
re_flags |= re.IGNORECASE
7021
if not fixed_string:
7022
patternc = grep.compile_pattern(
7023
pattern.encode(grep._user_encoding), re_flags)
7025
if color == 'always':
7027
elif color == 'never':
7029
elif color == 'auto':
7030
show_color = _termcolor.allow_color()
7032
opts = grep.GrepOptions()
7034
opts.verbose = verbose
7035
opts.ignore_case = ignore_case
7036
opts.no_recursive = no_recursive
7037
opts.from_root = from_root
7039
opts.levels = levels
7040
opts.line_number = line_number
7041
opts.path_list = path_list
7042
opts.revision = revision
7043
opts.pattern = pattern
7044
opts.include = include
7045
opts.exclude = exclude
7046
opts.fixed_string = fixed_string
7047
opts.files_with_matches = files_with_matches
7048
opts.files_without_match = files_without_match
7052
opts.eol_marker = eol_marker
7053
opts.print_revno = print_revno
7054
opts.patternc = patternc
7055
opts.recursive = not no_recursive
7056
opts.fixed_string = fixed_string
7057
opts.outf = self.outf
7058
opts.show_color = show_color
7062
# files_with_matches, files_without_match
7063
# levels(?), line_number, from_root
7065
# These are silently ignored.
7066
grep.grep_diff(opts)
7067
elif revision is None:
7068
grep.workingtree_grep(opts)
7070
grep.versioned_grep(opts)
7073
class cmd_patch(Command):
7074
"""Apply a named patch to the current tree.
7078
takes_args = ['filename?']
7079
takes_options = [Option('strip', type=int, short_name='p',
7080
help=("Strip the smallest prefix containing num "
7081
"leading slashes from filenames.")),
7082
Option('silent', help='Suppress chatter.')]
7084
def run(self, filename=None, strip=None, silent=False):
7085
from .patch import patch_tree
7086
wt = WorkingTree.open_containing('.')[0]
7090
if filename is None:
7091
my_file = getattr(sys.stdin, 'buffer', sys.stdin)
7093
my_file = open(filename, 'rb')
7094
patches = [my_file.read()]
7095
return patch_tree(wt, patches, strip, quiet=is_quiet(), out=self.outf)
7098
class cmd_resolve_location(Command):
7099
__doc__ = """Expand a location to a full URL.
7102
Look up a Launchpad URL.
7104
brz resolve-location lp:brz
7106
takes_args = ['location']
7109
def run(self, location):
7110
from .location import location_to_url
7111
url = location_to_url(location)
7112
display_url = urlutils.unescape_for_display(url, self.outf.encoding)
7113
self.outf.write('%s\n' % display_url)
7116
6720
def _register_lazy_builtins():
7117
6721
# register lazy builtins from other modules; called at startup and should
7118
6722
# be only called once.
7119
6723
for (name, aliases, module_name) in [
7120
('cmd_bisect', [], 'breezy.bisect'),
7121
('cmd_bundle_info', [], 'breezy.bzr.bundle.commands'),
7122
('cmd_config', [], 'breezy.config'),
7123
('cmd_dump_btree', [], 'breezy.bzr.debug_commands'),
7124
('cmd_file_id', [], 'breezy.bzr.debug_commands'),
7125
('cmd_file_path', [], 'breezy.bzr.debug_commands'),
7126
('cmd_version_info', [], 'breezy.cmd_version_info'),
7127
('cmd_resolve', ['resolved'], 'breezy.conflicts'),
7128
('cmd_conflicts', [], 'breezy.conflicts'),
7129
('cmd_ping', [], 'breezy.bzr.smart.ping'),
7130
('cmd_sign_my_commits', [], 'breezy.commit_signature_commands'),
7131
('cmd_verify_signatures', [], 'breezy.commit_signature_commands'),
7132
('cmd_test_script', [], 'breezy.cmd_test_script'),
6724
('cmd_bundle_info', [], 'bzrlib.bundle.commands'),
6725
('cmd_config', [], 'bzrlib.config'),
6726
('cmd_dpush', [], 'bzrlib.foreign'),
6727
('cmd_version_info', [], 'bzrlib.cmd_version_info'),
6728
('cmd_resolve', ['resolved'], 'bzrlib.conflicts'),
6729
('cmd_conflicts', [], 'bzrlib.conflicts'),
6730
('cmd_ping', [], 'bzrlib.smart.ping'),
6731
('cmd_sign_my_commits', [], 'bzrlib.commit_signature_commands'),
6732
('cmd_verify_signatures', [], 'bzrlib.commit_signature_commands'),
6733
('cmd_test_script', [], 'bzrlib.cmd_test_script'),
7134
6735
builtin_command_registry.register_lazy(name, aliases, module_name)