29
29
from bzrlib import (
41
39
merge as _mod_merge,
46
43
revision as _mod_revision,
55
50
from bzrlib.branch import Branch
56
51
from bzrlib.conflicts import ConflictList
57
from bzrlib.transport import memory
58
from bzrlib.revisionspec import RevisionSpec, RevisionInfo
52
from bzrlib.revisionspec import RevisionSpec
59
53
from bzrlib.smtp_connection import SMTPConnection
60
54
from bzrlib.workingtree import WorkingTree
63
57
from bzrlib.commands import Command, display_command
64
from bzrlib.option import (
71
from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
74
def tree_files(file_list, default_branch=u'.', canonicalize=True,
58
from bzrlib.option import ListOption, Option, RegistryOption, custom_help
59
from bzrlib.trace import mutter, note, warning, is_quiet, info
62
def tree_files(file_list, default_branch=u'.'):
77
return internal_tree_files(file_list, default_branch, canonicalize,
64
return internal_tree_files(file_list, default_branch)
79
65
except errors.FileInWrongBranch, e:
80
66
raise errors.BzrCommandError("%s is not in the same branch as %s" %
81
67
(e.path, file_list[0]))
84
def tree_files_for_add(file_list):
86
Return a tree and list of absolute paths from a file list.
88
Similar to tree_files, but add handles files a bit differently, so it a
89
custom implementation. In particular, MutableTreeTree.smart_add expects
90
absolute paths, which it immediately converts to relative paths.
92
# FIXME Would be nice to just return the relative paths like
93
# internal_tree_files does, but there are a large number of unit tests
94
# that assume the current interface to mutabletree.smart_add
96
tree, relpath = WorkingTree.open_containing(file_list[0])
97
if tree.supports_views():
98
view_files = tree.views.lookup_view()
100
for filename in file_list:
101
if not osutils.is_inside_any(view_files, filename):
102
raise errors.FileOutsideView(filename, view_files)
103
file_list = file_list[:]
104
file_list[0] = tree.abspath(relpath)
106
tree = WorkingTree.open_containing(u'.')[0]
107
if tree.supports_views():
108
view_files = tree.views.lookup_view()
110
file_list = view_files
111
view_str = views.view_display_str(view_files)
112
note("Ignoring files outside view. View is %s" % view_str)
113
return tree, file_list
116
def _get_one_revision(command_name, revisions):
117
if revisions is None:
119
if len(revisions) != 1:
120
raise errors.BzrCommandError(
121
'bzr %s --revision takes exactly one revision identifier' % (
126
def _get_one_revision_tree(command_name, revisions, branch=None, tree=None):
127
"""Get a revision tree. Not suitable for commands that change the tree.
129
Specifically, the basis tree in dirstate trees is coupled to the dirstate
130
and doing a commit/uncommit/pull will at best fail due to changing the
133
If tree is passed in, it should be already locked, for lifetime management
134
of the trees internal cached state.
138
if revisions is None:
140
rev_tree = tree.basis_tree()
142
rev_tree = branch.basis_tree()
144
revision = _get_one_revision(command_name, revisions)
145
rev_tree = revision.as_tree(branch)
149
70
# XXX: Bad function name; should possibly also be a class method of
150
71
# WorkingTree rather than a function.
151
def internal_tree_files(file_list, default_branch=u'.', canonicalize=True,
72
def internal_tree_files(file_list, default_branch=u'.'):
153
73
"""Convert command-line paths to a WorkingTree and relative paths.
155
75
This is typically used for command-line processors that take one or
367
235
rev_id = rev.as_revision_id(b)
368
236
self.outf.write(b.repository.get_revision_xml(rev_id).decode('utf-8'))
371
class cmd_dump_btree(Command):
372
"""Dump the contents of a btree index file to stdout.
374
PATH is a btree index file, it can be any URL. This includes things like
375
.bzr/repository/pack-names, or .bzr/repository/indices/a34b3a...ca4a4.iix
377
By default, the tuples stored in the index file will be displayed. With
378
--raw, we will uncompress the pages, but otherwise display the raw bytes
382
# TODO: Do we want to dump the internal nodes as well?
383
# TODO: It would be nice to be able to dump the un-parsed information,
384
# rather than only going through iter_all_entries. However, this is
385
# good enough for a start
387
encoding_type = 'exact'
388
takes_args = ['path']
389
takes_options = [Option('raw', help='Write the uncompressed bytes out,'
390
' rather than the parsed tuples.'),
393
def run(self, path, raw=False):
394
dirname, basename = osutils.split(path)
395
t = transport.get_transport(dirname)
397
self._dump_raw_bytes(t, basename)
399
self._dump_entries(t, basename)
401
def _get_index_and_bytes(self, trans, basename):
402
"""Create a BTreeGraphIndex and raw bytes."""
403
bt = btree_index.BTreeGraphIndex(trans, basename, None)
404
bytes = trans.get_bytes(basename)
405
bt._file = cStringIO.StringIO(bytes)
406
bt._size = len(bytes)
409
def _dump_raw_bytes(self, trans, basename):
412
# We need to parse at least the root node.
413
# This is because the first page of every row starts with an
414
# uncompressed header.
415
bt, bytes = self._get_index_and_bytes(trans, basename)
416
for page_idx, page_start in enumerate(xrange(0, len(bytes),
417
btree_index._PAGE_SIZE)):
418
page_end = min(page_start + btree_index._PAGE_SIZE, len(bytes))
419
page_bytes = bytes[page_start:page_end]
421
self.outf.write('Root node:\n')
422
header_end, data = bt._parse_header_from_bytes(page_bytes)
423
self.outf.write(page_bytes[:header_end])
425
self.outf.write('\nPage %d\n' % (page_idx,))
426
decomp_bytes = zlib.decompress(page_bytes)
427
self.outf.write(decomp_bytes)
428
self.outf.write('\n')
430
def _dump_entries(self, trans, basename):
432
st = trans.stat(basename)
433
except errors.TransportNotPossible:
434
# We can't stat, so we'll fake it because we have to do the 'get()'
436
bt, _ = self._get_index_and_bytes(trans, basename)
438
bt = btree_index.BTreeGraphIndex(trans, basename, st.st_size)
439
for node in bt.iter_all_entries():
440
# Node is made up of:
441
# (index, key, value, [references])
442
refs_as_tuples = static_tuple.as_tuples(node[3])
443
as_tuple = (tuple(node[1]), node[2], refs_as_tuples)
444
self.outf.write('%s\n' % (as_tuple,))
447
239
class cmd_remove_tree(Command):
448
240
"""Remove the working tree from a given branch/checkout.
833
564
into_existing = False
835
566
inv = tree.inventory
836
# 'fix' the case of a potential 'from'
837
from_id = tree.path2id(
838
tree.get_canonical_inventory_path(rel_names[0]))
567
from_id = tree.path2id(rel_names[0])
839
568
if (not osutils.lexists(names_list[0]) and
840
569
from_id and inv.get_file_kind(from_id) == "directory"):
841
570
into_existing = False
843
572
if into_existing:
844
573
# move into existing directory
845
# All entries reference existing inventory items, so fix them up
846
# for cicp file-systems.
847
rel_names = tree.get_canonical_inventory_paths(rel_names)
848
for src, dest in tree.move(rel_names[:-1], rel_names[-1], after=after):
850
self.outf.write("%s => %s\n" % (src, dest))
574
for pair in tree.move(rel_names[:-1], rel_names[-1], after=after):
575
self.outf.write("%s => %s\n" % pair)
852
577
if len(names_list) != 2:
853
578
raise errors.BzrCommandError('to mv multiple files the'
854
579
' destination must be a versioned'
857
# for cicp file-systems: the src references an existing inventory
859
src = tree.get_canonical_inventory_path(rel_names[0])
860
# Find the canonical version of the destination: In all cases, the
861
# parent of the target must be in the inventory, so we fetch the
862
# canonical version from there (we do not always *use* the
863
# canonicalized tail portion - we may be attempting to rename the
865
canon_dest = tree.get_canonical_inventory_path(rel_names[1])
866
dest_parent = osutils.dirname(canon_dest)
867
spec_tail = osutils.basename(rel_names[1])
868
# For a CICP file-system, we need to avoid creating 2 inventory
869
# entries that differ only by case. So regardless of the case
870
# we *want* to use (ie, specified by the user or the file-system),
871
# we must always choose to use the case of any existing inventory
872
# items. The only exception to this is when we are attempting a
873
# case-only rename (ie, canonical versions of src and dest are
875
dest_id = tree.path2id(canon_dest)
876
if dest_id is None or tree.path2id(src) == dest_id:
877
# No existing item we care about, so work out what case we
878
# are actually going to use.
880
# If 'after' is specified, the tail must refer to a file on disk.
882
dest_parent_fq = osutils.pathjoin(tree.basedir, dest_parent)
884
# pathjoin with an empty tail adds a slash, which breaks
886
dest_parent_fq = tree.basedir
888
dest_tail = osutils.canonical_relpath(
890
osutils.pathjoin(dest_parent_fq, spec_tail))
892
# not 'after', so case as specified is used
893
dest_tail = spec_tail
895
# Use the existing item so 'mv' fails with AlreadyVersioned.
896
dest_tail = os.path.basename(canon_dest)
897
dest = osutils.pathjoin(dest_parent, dest_tail)
898
mutter("attempting to move %s => %s", src, dest)
899
tree.rename_one(src, dest, after=after)
901
self.outf.write("%s => %s\n" % (src, dest))
581
tree.rename_one(rel_names[0], rel_names[1], after=after)
582
self.outf.write("%s => %s\n" % (rel_names[0], rel_names[1]))
904
585
class cmd_pull(Command):
905
586
"""Turn this branch into a mirror of another branch.
907
By default, this command only works on branches that have not diverged.
908
Branches are considered diverged if the destination branch's most recent
909
commit is one that has not been merged (directly or indirectly) into the
588
This command only works on branches that have not diverged. Branches are
589
considered diverged if the destination branch's most recent commit is one
590
that has not been merged (directly or indirectly) into the parent.
912
592
If branches have diverged, you can use 'bzr merge' to integrate the changes
913
593
from one into the other. Once one branch has merged, the other should
914
594
be able to pull it again.
916
If you want to replace your local changes and just want your branch to
917
match the remote one, use pull --overwrite. This will work even if the two
918
branches have diverged.
596
If you want to forget your local changes and just update your branch to
597
match the remote one, use pull --overwrite.
920
599
If there is no default location set, the first pull will set it. After
921
600
that, you can omit the location to use the default. To change the
1169
828
takes_args = ['from_location', 'to_location?']
1170
829
takes_options = ['revision', Option('hardlink',
1171
830
help='Hard-link working tree files where possible.'),
1173
help="Create a branch without a working-tree."),
1175
help="Switch the checkout in the current directory "
1176
"to the new branch."),
1177
831
Option('stacked',
1178
832
help='Create a stacked branch referring to the source branch. '
1179
833
'The new branch will depend on the availability of the source '
1180
834
'branch for all operations.'),
1181
Option('standalone',
1182
help='Do not use a shared repository, even if available.'),
1183
Option('use-existing-dir',
1184
help='By default branch will fail if the target'
1185
' directory exists, but does not already'
1186
' have a control directory. This flag will'
1187
' allow branch to proceed.'),
1189
help="Bind new branch to from location."),
1191
836
aliases = ['get', 'clone']
1193
838
def run(self, from_location, to_location=None, revision=None,
1194
hardlink=False, stacked=False, standalone=False, no_tree=False,
1195
use_existing_dir=False, switch=False, bind=False):
1196
from bzrlib import switch as _mod_switch
839
hardlink=False, stacked=False):
1197
840
from bzrlib.tag import _merge_tags_if_possible
843
elif len(revision) > 1:
844
raise errors.BzrCommandError(
845
'bzr branch --revision takes exactly 1 revision value')
1198
847
accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1200
revision = _get_one_revision('branch', revision)
1201
849
br_from.lock_read()
1202
self.add_cleanup(br_from.unlock)
1203
if revision is not None:
1204
revision_id = revision.as_revision_id(br_from)
1206
# FIXME - wt.last_revision, fallback to branch, fall back to
1207
# None or perhaps NULL_REVISION to mean copy nothing
1209
revision_id = br_from.last_revision()
1210
if to_location is None:
1211
to_location = urlutils.derive_to_location(from_location)
1212
to_transport = transport.get_transport(to_location)
1214
to_transport.mkdir('.')
1215
except errors.FileExists:
1216
if not use_existing_dir:
1217
raise errors.BzrCommandError('Target directory "%s" '
1218
'already exists.' % to_location)
851
if len(revision) == 1 and revision[0] is not None:
852
revision_id = revision[0].as_revision_id(br_from)
1221
bzrdir.BzrDir.open_from_transport(to_transport)
1222
except errors.NotBranchError:
1225
raise errors.AlreadyBranchError(to_location)
1226
except errors.NoSuchFile:
1227
raise errors.BzrCommandError('Parent of "%s" does not exist.'
1230
# preserve whatever source format we have.
1231
dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
1232
possible_transports=[to_transport],
1233
accelerator_tree=accelerator_tree,
1234
hardlink=hardlink, stacked=stacked,
1235
force_new_repo=standalone,
1236
create_tree_if_local=not no_tree,
1237
source_branch=br_from)
1238
branch = dir.open_branch()
1239
except errors.NoSuchRevision:
1240
to_transport.delete_tree('.')
1241
msg = "The branch %s has no revision %s." % (from_location,
1243
raise errors.BzrCommandError(msg)
1244
_merge_tags_if_possible(br_from, branch)
1245
# If the source branch is stacked, the new branch may
1246
# be stacked whether we asked for that explicitly or not.
1247
# We therefore need a try/except here and not just 'if stacked:'
1249
note('Created new stacked branch referring to %s.' %
1250
branch.get_stacked_on_url())
1251
except (errors.NotStacked, errors.UnstackableBranchFormat,
1252
errors.UnstackableRepositoryFormat), e:
1253
note('Branched %d revision(s).' % branch.revno())
1255
# Bind to the parent
1256
parent_branch = Branch.open(from_location)
1257
branch.bind(parent_branch)
1258
note('New branch bound to %s' % from_location)
1260
# Switch to the new branch
1261
wt, _ = WorkingTree.open_containing('.')
1262
_mod_switch.switch(wt.bzrdir, branch)
1263
note('Switched to branch: %s',
1264
urlutils.unescape_for_display(branch.base, 'utf-8'))
854
# FIXME - wt.last_revision, fallback to branch, fall back to
855
# None or perhaps NULL_REVISION to mean copy nothing
857
revision_id = br_from.last_revision()
858
if to_location is None:
859
to_location = urlutils.derive_to_location(from_location)
860
to_transport = transport.get_transport(to_location)
862
to_transport.mkdir('.')
863
except errors.FileExists:
864
raise errors.BzrCommandError('Target directory "%s" already'
865
' exists.' % to_location)
866
except errors.NoSuchFile:
867
raise errors.BzrCommandError('Parent of "%s" does not exist.'
870
# preserve whatever source format we have.
871
dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
872
possible_transports=[to_transport],
873
accelerator_tree=accelerator_tree,
874
hardlink=hardlink, stacked=stacked)
875
branch = dir.open_branch()
876
except errors.NoSuchRevision:
877
to_transport.delete_tree('.')
878
msg = "The branch %s has no revision %s." % (from_location,
880
raise errors.BzrCommandError(msg)
881
_merge_tags_if_possible(br_from, branch)
882
# If the source branch is stacked, the new branch may
883
# be stacked whether we asked for that explicitly or not.
884
# We therefore need a try/except here and not just 'if stacked:'
886
note('Created new stacked branch referring to %s.' %
887
branch.get_stacked_on_url())
888
except (errors.NotStacked, errors.UnstackableBranchFormat,
889
errors.UnstackableRepositoryFormat), e:
890
note('Branched %d revision(s).' % branch.revno())
1267
895
class cmd_checkout(Command):
1346
978
def run(self, dir=u'.'):
1347
979
tree = WorkingTree.open_containing(dir)[0]
1348
980
tree.lock_read()
1349
self.add_cleanup(tree.unlock)
1350
new_inv = tree.inventory
1351
old_tree = tree.basis_tree()
1352
old_tree.lock_read()
1353
self.add_cleanup(old_tree.unlock)
1354
old_inv = old_tree.inventory
1356
iterator = tree.iter_changes(old_tree, include_unchanged=True)
1357
for f, paths, c, v, p, n, k, e in iterator:
1358
if paths[0] == paths[1]:
1362
renames.append(paths)
1364
for old_name, new_name in renames:
1365
self.outf.write("%s => %s\n" % (old_name, new_name))
982
new_inv = tree.inventory
983
old_tree = tree.basis_tree()
986
old_inv = old_tree.inventory
987
renames = list(_mod_tree.find_renames(old_inv, new_inv))
989
for old_name, new_name in renames:
990
self.outf.write("%s => %s\n" % (old_name, new_name))
1368
997
class cmd_update(Command):
1369
998
"""Update a tree to have the latest code committed to its branch.
1371
1000
This will perform a merge into the working tree, and may generate
1372
conflicts. If you have any local changes, you will still
1001
conflicts. If you have any local changes, you will still
1373
1002
need to commit them after the update for the update to be complete.
1375
If you want to discard your local changes, you can just do a
1004
If you want to discard your local changes, you can just do a
1376
1005
'bzr revert' instead of 'bzr commit' after the update.
1378
If the tree's branch is bound to a master branch, it will also update
1379
the branch from the master.
1382
1008
_see_also = ['pull', 'working-trees', 'status-flags']
1383
1009
takes_args = ['dir?']
1384
takes_options = ['revision']
1385
1010
aliases = ['up']
1387
def run(self, dir='.', revision=None):
1388
if revision is not None and len(revision) != 1:
1389
raise errors.BzrCommandError(
1390
"bzr update --revision takes exactly one revision")
1012
def run(self, dir='.'):
1391
1013
tree = WorkingTree.open_containing(dir)[0]
1392
branch = tree.branch
1393
1014
possible_transports = []
1394
master = branch.get_master_branch(
1015
master = tree.branch.get_master_branch(
1395
1016
possible_transports=possible_transports)
1396
1017
if master is not None:
1397
1018
tree.lock_write()
1398
branch_location = master.base
1400
1020
tree.lock_tree_write()
1401
branch_location = tree.branch.base
1402
self.add_cleanup(tree.unlock)
1403
# get rid of the final '/' and be ready for display
1404
branch_location = urlutils.unescape_for_display(branch_location[:-1],
1406
existing_pending_merges = tree.get_parent_ids()[1:]
1410
# may need to fetch data into a heavyweight checkout
1411
# XXX: this may take some time, maybe we should display a
1413
old_tip = branch.update(possible_transports)
1414
if revision is not None:
1415
revision_id = revision[0].as_revision_id(branch)
1417
revision_id = branch.last_revision()
1418
if revision_id == _mod_revision.ensure_null(tree.last_revision()):
1419
revno = branch.revision_id_to_revno(revision_id)
1420
note("Tree is up to date at revision %d of branch %s" %
1421
(revno, branch_location))
1423
view_info = _get_view_info_for_change_reporter(tree)
1424
change_reporter = delta._ChangeReporter(
1425
unversioned_filter=tree.is_ignored,
1426
view_info=view_info)
1022
existing_pending_merges = tree.get_parent_ids()[1:]
1023
last_rev = _mod_revision.ensure_null(tree.last_revision())
1024
if last_rev == _mod_revision.ensure_null(
1025
tree.branch.last_revision()):
1026
# may be up to date, check master too.
1027
if master is None or last_rev == _mod_revision.ensure_null(
1028
master.last_revision()):
1029
revno = tree.branch.revision_id_to_revno(last_rev)
1030
note("Tree is up to date at revision %d." % (revno,))
1428
1032
conflicts = tree.update(
1430
possible_transports=possible_transports,
1431
revision=revision_id,
1433
except errors.NoSuchRevision, e:
1434
raise errors.BzrCommandError(
1435
"branch has no revision %s\n"
1436
"bzr update --revision only works"
1437
" for a revision in the branch history"
1439
revno = tree.branch.revision_id_to_revno(
1440
_mod_revision.ensure_null(tree.last_revision()))
1441
note('Updated to revision %d of branch %s' %
1442
(revno, branch_location))
1443
if tree.get_parent_ids()[1:] != existing_pending_merges:
1444
note('Your local commits will now show as pending merges with '
1445
"'bzr status', and can be committed with 'bzr commit'.")
1033
delta._ChangeReporter(unversioned_filter=tree.is_ignored),
1034
possible_transports=possible_transports)
1035
revno = tree.branch.revision_id_to_revno(
1036
_mod_revision.ensure_null(tree.last_revision()))
1037
note('Updated to revision %d.' % (revno,))
1038
if tree.get_parent_ids()[1:] != existing_pending_merges:
1039
note('Your local commits will now show as pending merges with '
1040
"'bzr status', and can be committed with 'bzr commit'.")
1452
1049
class cmd_info(Command):
1453
1050
"""Show information about a working tree, branch or repository.
1455
1052
This command will show all known locations and formats associated to the
1456
tree, branch or repository.
1458
In verbose mode, statistical information is included with each report.
1459
To see extended statistic information, use a verbosity level of 2 or
1460
higher by specifying the verbose option multiple times, e.g. -vv.
1053
tree, branch or repository. Statistical information is included with
1462
1056
Branches and working trees will also report any missing revisions.
1466
Display information on the format and related locations:
1470
Display the above together with extended format information and
1471
basic statistics (like the number of files in the working tree and
1472
number of revisions in the branch and repository):
1476
Display the above together with number of committers to the branch:
1480
1058
_see_also = ['revno', 'working-trees', 'repositories']
1481
1059
takes_args = ['location?']
1724
1304
"\nYou may supply --create-prefix to create all"
1725
1305
" leading parent directories."
1727
to_transport.create_prefix()
1307
_create_prefix(to_transport)
1730
a_bzrdir = bzrdir.BzrDir.open_from_transport(to_transport)
1310
existing_bzrdir = bzrdir.BzrDir.open_from_transport(to_transport)
1731
1311
except errors.NotBranchError:
1732
1312
# really a NotBzrDir error...
1733
1313
create_branch = bzrdir.BzrDir.create_branch_convenience
1734
1314
branch = create_branch(to_transport.base, format=format,
1735
1315
possible_transports=[to_transport])
1736
a_bzrdir = branch.bzrdir
1738
1317
from bzrlib.transport.local import LocalTransport
1739
if a_bzrdir.has_branch():
1318
if existing_bzrdir.has_branch():
1740
1319
if (isinstance(to_transport, LocalTransport)
1741
and not a_bzrdir.has_workingtree()):
1320
and not existing_bzrdir.has_workingtree()):
1742
1321
raise errors.BranchExistsWithoutWorkingTree(location)
1743
1322
raise errors.AlreadyBranchError(location)
1744
branch = a_bzrdir.create_branch()
1745
a_bzrdir.create_workingtree()
1324
branch = existing_bzrdir.create_branch()
1325
existing_bzrdir.create_workingtree()
1746
1326
if append_revisions_only:
1748
1328
branch.set_append_revisions_only(True)
1749
1329
except errors.UpgradeRequired:
1750
1330
raise errors.BzrCommandError('This branch format cannot be set'
1751
' to append-revisions-only. Try --default.')
1331
' to append-revisions-only. Try --experimental-branch6')
1752
1332
if not is_quiet():
1753
from bzrlib.info import describe_layout, describe_format
1755
tree = a_bzrdir.open_workingtree(recommend_upgrade=False)
1756
except (errors.NoWorkingTree, errors.NotLocalUrl):
1758
repository = branch.repository
1759
layout = describe_layout(repository, branch, tree).lower()
1760
format = describe_format(a_bzrdir, repository, branch, tree)
1761
self.outf.write("Created a %s (format: %s)\n" % (layout, format))
1762
if repository.is_shared():
1763
#XXX: maybe this can be refactored into transport.path_or_url()
1764
url = repository.bzrdir.root_transport.external_url()
1766
url = urlutils.local_path_from_url(url)
1767
except errors.InvalidURL:
1769
self.outf.write("Using shared repository: %s\n" % url)
1333
from bzrlib.info import show_bzrdir_info
1334
show_bzrdir_info(bzrdir.BzrDir.open_containing_from_transport(
1335
to_transport)[0], verbose=0, outfile=self.outf)
1772
1338
class cmd_init_repository(Command):
1773
"""Create a shared repository for branches to share storage space.
1339
"""Create a shared repository to hold branches.
1775
1341
New branches created under the repository directory will store their
1776
revisions in the repository, not in the branch directory. For branches
1777
with shared history, this reduces the amount of storage needed and
1778
speeds up the creation of new branches.
1342
revisions in the repository, not in the branch directory.
1780
If the --no-trees option is given then the branches in the repository
1781
will not have working trees by default. They will still exist as
1782
directories on disk, but they will not have separate copies of the
1783
files at a certain revision. This can be useful for repositories that
1784
store branches which are interacted with through checkouts or remote
1785
branches, such as on a server.
1344
If the --no-trees option is used then the branches in the repository
1345
will not have working trees by default.
1788
Create a shared repository holding just branches::
1348
Create a shared repositories holding just branches::
1790
1350
bzr init-repo --no-trees repo
1791
1351
bzr init repo/trunk
2070
1623
raise errors.BzrCommandError(msg)
2073
def _parse_levels(s):
2077
msg = "The levels argument must be an integer."
2078
raise errors.BzrCommandError(msg)
2081
1626
class cmd_log(Command):
2082
"""Show historical log for a branch or subset of a branch.
2084
log is bzr's default tool for exploring the history of a branch.
2085
The branch to use is taken from the first parameter. If no parameters
2086
are given, the branch containing the working directory is logged.
2087
Here are some simple examples::
2089
bzr log log the current branch
2090
bzr log foo.py log a file in its branch
2091
bzr log http://server/branch log a branch on a server
2093
The filtering, ordering and information shown for each revision can
2094
be controlled as explained below. By default, all revisions are
2095
shown sorted (topologically) so that newer revisions appear before
2096
older ones and descendants always appear before ancestors. If displayed,
2097
merged revisions are shown indented under the revision in which they
2102
The log format controls how information about each revision is
2103
displayed. The standard log formats are called ``long``, ``short``
2104
and ``line``. The default is long. See ``bzr help log-formats``
2105
for more details on log formats.
2107
The following options can be used to control what information is
2110
-l N display a maximum of N revisions
2111
-n N display N levels of revisions (0 for all, 1 for collapsed)
2112
-v display a status summary (delta) for each revision
2113
-p display a diff (patch) for each revision
2114
--show-ids display revision-ids (and file-ids), not just revnos
2116
Note that the default number of levels to display is a function of the
2117
log format. If the -n option is not used, the standard log formats show
2118
just the top level (mainline).
2120
Status summaries are shown using status flags like A, M, etc. To see
2121
the changes explained using words like ``added`` and ``modified``
2122
instead, use the -vv option.
2126
To display revisions from oldest to newest, use the --forward option.
2127
In most cases, using this option will have little impact on the total
2128
time taken to produce a log, though --forward does not incrementally
2129
display revisions like --reverse does when it can.
2131
:Revision filtering:
2133
The -r option can be used to specify what revision or range of revisions
2134
to filter against. The various forms are shown below::
2136
-rX display revision X
2137
-rX.. display revision X and later
2138
-r..Y display up to and including revision Y
2139
-rX..Y display from X to Y inclusive
2141
See ``bzr help revisionspec`` for details on how to specify X and Y.
2142
Some common examples are given below::
2144
-r-1 show just the tip
2145
-r-10.. show the last 10 mainline revisions
2146
-rsubmit:.. show what's new on this branch
2147
-rancestor:path.. show changes since the common ancestor of this
2148
branch and the one at location path
2149
-rdate:yesterday.. show changes since yesterday
2151
When logging a range of revisions using -rX..Y, log starts at
2152
revision Y and searches back in history through the primary
2153
("left-hand") parents until it finds X. When logging just the
2154
top level (using -n1), an error is reported if X is not found
2155
along the way. If multi-level logging is used (-n0), X may be
2156
a nested merge revision and the log will be truncated accordingly.
2160
If parameters are given and the first one is not a branch, the log
2161
will be filtered to show only those revisions that changed the
2162
nominated files or directories.
2164
Filenames are interpreted within their historical context. To log a
2165
deleted file, specify a revision range so that the file existed at
2166
the end or start of the range.
2168
Historical context is also important when interpreting pathnames of
2169
renamed files/directories. Consider the following example:
2171
* revision 1: add tutorial.txt
2172
* revision 2: modify tutorial.txt
2173
* revision 3: rename tutorial.txt to guide.txt; add tutorial.txt
2177
* ``bzr log guide.txt`` will log the file added in revision 1
2179
* ``bzr log tutorial.txt`` will log the new file added in revision 3
2181
* ``bzr log -r2 -p tutorial.txt`` will show the changes made to
2182
the original file in revision 2.
2184
* ``bzr log -r2 -p guide.txt`` will display an error message as there
2185
was no file called guide.txt in revision 2.
2187
Renames are always followed by log. By design, there is no need to
2188
explicitly ask for this (and no way to stop logging a file back
2189
until it was last renamed).
2193
The --message option can be used for finding revisions that match a
2194
regular expression in a commit message.
2198
GUI tools and IDEs are often better at exploring history than command
2199
line tools: you may prefer qlog or viz from qbzr or bzr-gtk, the
2200
bzr-explorer shell, or the Loggerhead web interface. See the Plugin
2201
Guide <http://doc.bazaar.canonical.com/plugins/en/> and
2202
<http://wiki.bazaar.canonical.com/IDEIntegration>.
2204
You may find it useful to add the aliases below to ``bazaar.conf``::
2208
top = log -l10 --line
2211
``bzr tip`` will then show the latest revision while ``bzr top``
2212
will show the last 10 mainline revisions. To see the details of a
2213
particular revision X, ``bzr show -rX``.
2215
If you are interested in looking deeper into a particular merge X,
2216
use ``bzr log -n0 -rX``.
2218
``bzr log -v`` on a branch with lots of history is currently
2219
very slow. A fix for this issue is currently under development.
2220
With or without that fix, it is recommended that a revision range
2221
be given when using the -v option.
2223
bzr has a generic full-text matching plugin, bzr-search, that can be
2224
used to find revisions matching user names, commit messages, etc.
2225
Among other features, this plugin can find all revisions containing
2226
a list of words but not others.
2228
When exploring non-mainline history on large projects with deep
2229
history, the performance of log can be greatly improved by installing
2230
the historycache plugin. This plugin buffers historical information
2231
trading disk space for faster speed.
1627
"""Show log of a branch, file, or directory.
1629
By default show the log of the branch containing the working directory.
1631
To request a range of logs, you can use the command -r begin..end
1632
-r revision requests a specific revision, -r ..end or -r begin.. are
1636
Log the current branch::
1644
Log the last 10 revisions of a branch::
1646
bzr log -r -10.. http://server/branch
2233
takes_args = ['file*']
2234
_see_also = ['log-formats', 'revisionspec']
1649
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
1651
takes_args = ['location?']
2235
1652
takes_options = [
2236
1653
Option('forward',
2237
1654
help='Show from oldest to newest.'),
1657
help='Display timezone as local, original, or utc.'),
2239
1658
custom_help('verbose',
2240
1659
help='Show files changed in each revision.'),
2244
type=bzrlib.option._parse_revision_str,
2246
help='Show just the specified revision.'
2247
' See also "help revisionspec".'),
2251
help='Number of levels to display - 0 for all, 1 for flat.',
2253
type=_parse_levels),
2254
1663
Option('message',
2255
1664
short_name='m',
2256
1665
help='Show revisions whose message matches this '
2335
1711
dir, relpath = bzrdir.BzrDir.open_containing(location)
2336
1712
b = dir.open_branch()
2338
self.add_cleanup(b.unlock)
2339
rev1, rev2 = _get_revision_range(revision, b, self.name())
2341
# Decide on the type of delta & diff filtering to use
2342
# TODO: add an --all-files option to make this configurable & consistent
2350
diff_type = 'partial'
2354
# Build the log formatter
2355
if log_format is None:
2356
log_format = log.log_formatter_registry.get_default(b)
2357
# Make a non-encoding output to include the diffs - bug 328007
2358
unencoded_output = ui.ui_factory.make_output_stream(encoding_type='exact')
2359
lf = log_format(show_ids=show_ids, to_file=self.outf,
2360
to_exact_file=unencoded_output,
2361
show_timezone=timezone,
2362
delta_format=get_verbosity_level(),
2364
show_advice=levels is None)
2366
# Choose the algorithm for doing the logging. It's annoying
2367
# having multiple code paths like this but necessary until
2368
# the underlying repository format is faster at generating
2369
# deltas or can provide everything we need from the indices.
2370
# The default algorithm - match-using-deltas - works for
2371
# multiple files and directories and is faster for small
2372
# amounts of history (200 revisions say). However, it's too
2373
# slow for logging a single file in a repository with deep
2374
# history, i.e. > 10K revisions. In the spirit of "do no
2375
# evil when adding features", we continue to use the
2376
# original algorithm - per-file-graph - for the "single
2377
# file that isn't a directory without showing a delta" case.
2378
partial_history = revision and b.repository._format.supports_chks
2379
match_using_deltas = (len(file_ids) != 1 or filter_by_dir
2380
or delta_type or partial_history)
2382
# Build the LogRequest and execute it
2383
if len(file_ids) == 0:
2385
rqst = make_log_request_dict(
2386
direction=direction, specific_fileids=file_ids,
2387
start_revision=rev1, end_revision=rev2, limit=limit,
2388
message_search=message, delta_type=delta_type,
2389
diff_type=diff_type, _match_using_deltas=match_using_deltas)
2390
Logger(b, rqst).show(lf)
2393
def _get_revision_range(revisionspec_list, branch, command_name):
2394
"""Take the input of a revision option and turn it into a revision range.
2396
It returns RevisionInfo objects which can be used to obtain the rev_id's
2397
of the desired revisions. It does some user input validations.
2399
if revisionspec_list is None:
2402
elif len(revisionspec_list) == 1:
2403
rev1 = rev2 = revisionspec_list[0].in_history(branch)
2404
elif len(revisionspec_list) == 2:
2405
start_spec = revisionspec_list[0]
2406
end_spec = revisionspec_list[1]
2407
if end_spec.get_branch() != start_spec.get_branch():
2408
# b is taken from revision[0].get_branch(), and
2409
# show_log will use its revision_history. Having
2410
# different branches will lead to weird behaviors.
2411
raise errors.BzrCommandError(
2412
"bzr %s doesn't accept two revisions in different"
2413
" branches." % command_name)
2414
rev1 = start_spec.in_history(branch)
2415
# Avoid loading all of history when we know a missing
2416
# end of range means the last revision ...
2417
if end_spec.spec is None:
2418
last_revno, last_revision_id = branch.last_revision_info()
2419
rev2 = RevisionInfo(branch, last_revno, last_revision_id)
2421
rev2 = end_spec.in_history(branch)
2423
raise errors.BzrCommandError(
2424
'bzr %s --revision takes one or two values.' % command_name)
2428
def _revision_range_to_revid_range(revision_range):
2431
if revision_range[0] is not None:
2432
rev_id1 = revision_range[0].rev_id
2433
if revision_range[1] is not None:
2434
rev_id2 = revision_range[1].rev_id
2435
return rev_id1, rev_id2
1716
if revision is None:
1719
elif len(revision) == 1:
1720
rev1 = rev2 = revision[0].in_history(b)
1721
elif len(revision) == 2:
1722
if revision[1].get_branch() != revision[0].get_branch():
1723
# b is taken from revision[0].get_branch(), and
1724
# show_log will use its revision_history. Having
1725
# different branches will lead to weird behaviors.
1726
raise errors.BzrCommandError(
1727
"Log doesn't accept two revisions in different"
1729
rev1 = revision[0].in_history(b)
1730
rev2 = revision[1].in_history(b)
1732
raise errors.BzrCommandError(
1733
'bzr log --revision takes one or two values.')
1735
if log_format is None:
1736
log_format = log.log_formatter_registry.get_default(b)
1738
lf = log_format(show_ids=show_ids, to_file=self.outf,
1739
show_timezone=timezone)
1745
direction=direction,
1746
start_revision=rev1,
2437
1754
def get_log_format(long=False, short=False, line=False, default='long'):
2438
1755
log_format = default
2809
2085
If no revision is nominated, the last revision is used.
2811
2087
Note: Take care to redirect standard output when using this command on a
2815
2091
_see_also = ['ls']
2816
2092
takes_options = [
2817
2093
Option('name-from-revision', help='The path name in the old tree.'),
2818
Option('filters', help='Apply content filters to display the '
2819
'convenience form.'),
2822
2096
takes_args = ['filename']
2823
2097
encoding_type = 'exact'
2825
2099
@display_command
2826
def run(self, filename, revision=None, name_from_revision=False,
2100
def run(self, filename, revision=None, name_from_revision=False):
2828
2101
if revision is not None and len(revision) != 1:
2829
2102
raise errors.BzrCommandError("bzr cat --revision takes exactly"
2830
2103
" one revision specifier")
2831
2104
tree, branch, relpath = \
2832
2105
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2833
2106
branch.lock_read()
2834
self.add_cleanup(branch.unlock)
2835
return self._run(tree, branch, relpath, filename, revision,
2836
name_from_revision, filters)
2108
return self._run(tree, branch, relpath, filename, revision,
2838
def _run(self, tree, b, relpath, filename, revision, name_from_revision,
2113
def _run(self, tree, b, relpath, filename, revision, name_from_revision):
2840
2114
if tree is None:
2841
2115
tree = b.basis_tree()
2842
rev_tree = _get_one_revision_tree('cat', revision, branch=b)
2843
rev_tree.lock_read()
2844
self.add_cleanup(rev_tree.unlock)
2116
if revision is None:
2117
revision_id = b.last_revision()
2119
revision_id = revision[0].as_revision_id(b)
2121
cur_file_id = tree.path2id(relpath)
2122
rev_tree = b.repository.revision_tree(revision_id)
2846
2123
old_file_id = rev_tree.path2id(relpath)
2848
2125
if name_from_revision:
2849
# Try in revision if requested
2850
2126
if old_file_id is None:
2851
raise errors.BzrCommandError(
2852
"%r is not present in revision %s" % (
2853
filename, rev_tree.get_revision_id()))
2127
raise errors.BzrCommandError("%r is not present in revision %s"
2128
% (filename, revision_id))
2855
2130
content = rev_tree.get_file_text(old_file_id)
2857
cur_file_id = tree.path2id(relpath)
2859
if cur_file_id is not None:
2860
# Then try with the actual file id
2862
content = rev_tree.get_file_text(cur_file_id)
2864
except errors.NoSuchId:
2865
# The actual file id didn't exist at that time
2867
if not found and old_file_id is not None:
2868
# Finally try with the old file id
2869
content = rev_tree.get_file_text(old_file_id)
2872
# Can't be found anywhere
2873
raise errors.BzrCommandError(
2874
"%r is not present in revision %s" % (
2875
filename, rev_tree.get_revision_id()))
2877
from bzrlib.filters import (
2878
ContentFilterContext,
2879
filtered_output_bytes,
2881
filters = rev_tree._content_filter_stack(relpath)
2882
chunks = content.splitlines(True)
2883
content = filtered_output_bytes(chunks, filters,
2884
ContentFilterContext(relpath, rev_tree))
2886
self.outf.writelines(content)
2889
self.outf.write(content)
2131
elif cur_file_id is not None:
2132
content = rev_tree.get_file_text(cur_file_id)
2133
elif old_file_id is not None:
2134
content = rev_tree.get_file_text(old_file_id)
2136
raise errors.BzrCommandError("%r is not present in revision %s" %
2137
(filename, revision_id))
2138
self.outf.write(content)
2892
2141
class cmd_local_time_offset(Command):
2893
2142
"""Show the offset in seconds from GMT to local time."""
2895
2144
@display_command
2897
2146
print osutils.local_time_offset()
2901
2150
class cmd_commit(Command):
2902
2151
"""Commit changes into a new revision.
2904
An explanatory message needs to be given for each commit. This is
2905
often done by using the --message option (getting the message from the
2906
command line) or by using the --file option (getting the message from
2907
a file). If neither of these options is given, an editor is opened for
2908
the user to enter the message. To see the changed files in the
2909
boilerplate text loaded into the editor, use the --show-diff option.
2911
By default, the entire tree is committed and the person doing the
2912
commit is assumed to be the author. These defaults can be overridden
2917
If selected files are specified, only changes to those files are
2918
committed. If a directory is specified then the directory and
2919
everything within it is committed.
2921
When excludes are given, they take precedence over selected files.
2922
For example, to commit only changes within foo, but not changes
2925
bzr commit foo -x foo/bar
2927
A selective commit after a merge is not yet supported.
2931
If the author of the change is not the same person as the committer,
2932
you can specify the author's name using the --author option. The
2933
name should be in the same format as a committer-id, e.g.
2934
"John Doe <jdoe@example.com>". If there is more than one author of
2935
the change you can specify the option multiple times, once for each
2940
A common mistake is to forget to add a new file or directory before
2941
running the commit command. The --strict option checks for unknown
2942
files and aborts the commit if any are found. More advanced pre-commit
2943
checks can be implemented by defining hooks. See ``bzr help hooks``
2948
If you accidentially commit the wrong changes or make a spelling
2949
mistake in the commit message say, you can use the uncommit command
2950
to undo it. See ``bzr help uncommit`` for details.
2952
Hooks can also be configured to run after a commit. This allows you
2953
to trigger updates to external systems like bug trackers. The --fixes
2954
option can be used to record the association between a revision and
2955
one or more bugs. See ``bzr help bugs`` for details.
2957
A selective commit may fail in some cases where the committed
2958
tree would be invalid. Consider::
2963
bzr commit foo -m "committing foo"
2964
bzr mv foo/bar foo/baz
2967
bzr commit foo/bar -m "committing bar but not baz"
2969
In the example above, the last commit will fail by design. This gives
2970
the user the opportunity to decide whether they want to commit the
2971
rename at the same time, separately first, or not at all. (As a general
2972
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2153
If no arguments are given, the entire tree is committed.
2155
If selected files are specified, only changes to those files are
2156
committed. If a directory is specified then the directory and everything
2157
within it is committed.
2159
When excludes are given, they take precedence over selected files.
2160
For example, too commit only changes within foo, but not changes within
2163
bzr commit foo -x foo/bar
2165
If author of the change is not the same person as the committer, you can
2166
specify the author's name using the --author option. The name should be
2167
in the same format as a committer-id, e.g. "John Doe <jdoe@example.com>".
2169
A selected-file commit may fail in some cases where the committed
2170
tree would be invalid. Consider::
2175
bzr commit foo -m "committing foo"
2176
bzr mv foo/bar foo/baz
2179
bzr commit foo/bar -m "committing bar but not baz"
2181
In the example above, the last commit will fail by design. This gives
2182
the user the opportunity to decide whether they want to commit the
2183
rename at the same time, separately first, or not at all. (As a general
2184
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2186
Note: A selected-file commit after a merge is not yet supported.
2974
2188
# TODO: Run hooks on tree to-be-committed, and after commit.
3749
2887
allow_pending = True
3750
2888
verified = 'inapplicable'
3751
2889
tree = WorkingTree.open_containing(directory)[0]
2890
change_reporter = delta._ChangeReporter(
2891
unversioned_filter=tree.is_ignored)
3754
basis_tree = tree.revision_tree(tree.last_revision())
3755
except errors.NoSuchRevision:
3756
basis_tree = tree.basis_tree()
3758
# die as quickly as possible if there are uncommitted changes
3760
if tree.has_changes():
3761
raise errors.UncommittedChanges(tree)
3763
view_info = _get_view_info_for_change_reporter(tree)
3764
change_reporter = delta._ChangeReporter(
3765
unversioned_filter=tree.is_ignored, view_info=view_info)
3766
pb = ui.ui_factory.nested_progress_bar()
3767
self.add_cleanup(pb.finished)
3769
self.add_cleanup(tree.unlock)
3770
if location is not None:
3772
mergeable = bundle.read_mergeable_from_url(location,
3773
possible_transports=possible_transports)
3774
except errors.NotABundle:
2894
pb = ui.ui_factory.nested_progress_bar()
2895
cleanups.append(pb.finished)
2897
cleanups.append(tree.unlock)
2898
if location is not None:
2900
mergeable = bundle.read_mergeable_from_url(location,
2901
possible_transports=possible_transports)
2902
except errors.NotABundle:
2906
raise errors.BzrCommandError('Cannot use --uncommitted'
2907
' with bundles or merge directives.')
2909
if revision is not None:
2910
raise errors.BzrCommandError(
2911
'Cannot use -r with merge directives or bundles')
2912
merger, verified = _mod_merge.Merger.from_mergeable(tree,
2915
if merger is None and uncommitted:
2916
if revision is not None and len(revision) > 0:
2917
raise errors.BzrCommandError('Cannot use --uncommitted and'
2918
' --revision at the same time.')
2919
location = self._select_branch_location(tree, location)[0]
2920
other_tree, other_path = WorkingTree.open_containing(location)
2921
merger = _mod_merge.Merger.from_uncommitted(tree, other_tree,
2923
allow_pending = False
2924
if other_path != '':
2925
merger.interesting_files = [other_path]
2928
merger, allow_pending = self._get_merger_from_branch(tree,
2929
location, revision, remember, possible_transports, pb)
2931
merger.merge_type = merge_type
2932
merger.reprocess = reprocess
2933
merger.show_base = show_base
2934
self.sanity_check_merger(merger)
2935
if (merger.base_rev_id == merger.other_rev_id and
2936
merger.other_rev_id is not None):
2937
note('Nothing to do.')
2940
if merger.interesting_files is not None:
2941
raise errors.BzrCommandError('Cannot pull individual files')
2942
if (merger.base_rev_id == tree.last_revision()):
2943
result = tree.pull(merger.other_branch, False,
2944
merger.other_rev_id)
2945
result.report(self.outf)
2947
merger.check_basis(not force)
2949
return self._do_preview(merger)
3778
raise errors.BzrCommandError('Cannot use --uncommitted'
3779
' with bundles or merge directives.')
3781
if revision is not None:
3782
raise errors.BzrCommandError(
3783
'Cannot use -r with merge directives or bundles')
3784
merger, verified = _mod_merge.Merger.from_mergeable(tree,
3787
if merger is None and uncommitted:
3788
if revision is not None and len(revision) > 0:
3789
raise errors.BzrCommandError('Cannot use --uncommitted and'
3790
' --revision at the same time.')
3791
merger = self.get_merger_from_uncommitted(tree, location, None)
3792
allow_pending = False
3795
merger, allow_pending = self._get_merger_from_branch(tree,
3796
location, revision, remember, possible_transports, None)
3798
merger.merge_type = merge_type
3799
merger.reprocess = reprocess
3800
merger.show_base = show_base
3801
self.sanity_check_merger(merger)
3802
if (merger.base_rev_id == merger.other_rev_id and
3803
merger.other_rev_id is not None):
3804
note('Nothing to do.')
3807
if merger.interesting_files is not None:
3808
raise errors.BzrCommandError('Cannot pull individual files')
3809
if (merger.base_rev_id == tree.last_revision()):
3810
result = tree.pull(merger.other_branch, False,
3811
merger.other_rev_id)
3812
result.report(self.outf)
3814
if merger.this_basis is None:
3815
raise errors.BzrCommandError(
3816
"This branch has no commits."
3817
" (perhaps you would prefer 'bzr pull')")
3819
return self._do_preview(merger)
3821
return self._do_interactive(merger)
3823
return self._do_merge(merger, change_reporter, allow_pending,
3826
def _get_preview(self, merger):
2951
return self._do_merge(merger, change_reporter, allow_pending,
2954
for cleanup in reversed(cleanups):
2957
def _do_preview(self, merger):
2958
from bzrlib.diff import show_diff_trees
3827
2959
tree_merger = merger.make_merger()
3828
2960
tt = tree_merger.make_preview_transform()
3829
self.add_cleanup(tt.finalize)
3830
result_tree = tt.get_preview_tree()
3833
def _do_preview(self, merger):
3834
from bzrlib.diff import show_diff_trees
3835
result_tree = self._get_preview(merger)
3836
show_diff_trees(merger.this_tree, result_tree, self.outf,
3837
old_label='', new_label='')
2962
result_tree = tt.get_preview_tree()
2963
show_diff_trees(merger.this_tree, result_tree, self.outf,
2964
old_label='', new_label='')
3839
2968
def _do_merge(self, merger, change_reporter, allow_pending, verified):
3840
2969
merger.change_reporter = change_reporter
4028
3119
merge_type = _mod_merge.Merge3Merger
4029
3120
tree, file_list = tree_files(file_list)
4030
3121
tree.lock_write()
4031
self.add_cleanup(tree.unlock)
4032
parents = tree.get_parent_ids()
4033
if len(parents) != 2:
4034
raise errors.BzrCommandError("Sorry, remerge only works after normal"
4035
" merges. Not cherrypicking or"
4037
repository = tree.branch.repository
4038
interesting_ids = None
4040
conflicts = tree.conflicts()
4041
if file_list is not None:
4042
interesting_ids = set()
4043
for filename in file_list:
4044
file_id = tree.path2id(filename)
4046
raise errors.NotVersionedError(filename)
4047
interesting_ids.add(file_id)
4048
if tree.kind(file_id) != "directory":
4051
for name, ie in tree.inventory.iter_entries(file_id):
4052
interesting_ids.add(ie.file_id)
4053
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
4055
# Remerge only supports resolving contents conflicts
4056
allowed_conflicts = ('text conflict', 'contents conflict')
4057
restore_files = [c.path for c in conflicts
4058
if c.typestring in allowed_conflicts]
4059
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
4060
tree.set_conflicts(ConflictList(new_conflicts))
4061
if file_list is not None:
4062
restore_files = file_list
4063
for filename in restore_files:
3123
parents = tree.get_parent_ids()
3124
if len(parents) != 2:
3125
raise errors.BzrCommandError("Sorry, remerge only works after normal"
3126
" merges. Not cherrypicking or"
3128
repository = tree.branch.repository
3129
interesting_ids = None
3131
conflicts = tree.conflicts()
3132
if file_list is not None:
3133
interesting_ids = set()
3134
for filename in file_list:
3135
file_id = tree.path2id(filename)
3137
raise errors.NotVersionedError(filename)
3138
interesting_ids.add(file_id)
3139
if tree.kind(file_id) != "directory":
3142
for name, ie in tree.inventory.iter_entries(file_id):
3143
interesting_ids.add(ie.file_id)
3144
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
3146
# Remerge only supports resolving contents conflicts
3147
allowed_conflicts = ('text conflict', 'contents conflict')
3148
restore_files = [c.path for c in conflicts
3149
if c.typestring in allowed_conflicts]
3150
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
3151
tree.set_conflicts(ConflictList(new_conflicts))
3152
if file_list is not None:
3153
restore_files = file_list
3154
for filename in restore_files:
3156
restore(tree.abspath(filename))
3157
except errors.NotConflicted:
3159
# Disable pending merges, because the file texts we are remerging
3160
# have not had those merges performed. If we use the wrong parents
3161
# list, we imply that the working tree text has seen and rejected
3162
# all the changes from the other tree, when in fact those changes
3163
# have not yet been seen.
3164
pb = ui.ui_factory.nested_progress_bar()
3165
tree.set_parent_ids(parents[:1])
4065
restore(tree.abspath(filename))
4066
except errors.NotConflicted:
4068
# Disable pending merges, because the file texts we are remerging
4069
# have not had those merges performed. If we use the wrong parents
4070
# list, we imply that the working tree text has seen and rejected
4071
# all the changes from the other tree, when in fact those changes
4072
# have not yet been seen.
4073
tree.set_parent_ids(parents[:1])
4075
merger = _mod_merge.Merger.from_revision_ids(None, tree, parents[1])
4076
merger.interesting_ids = interesting_ids
4077
merger.merge_type = merge_type
4078
merger.show_base = show_base
4079
merger.reprocess = reprocess
4080
conflicts = merger.do_merge()
3167
merger = _mod_merge.Merger.from_revision_ids(pb,
3169
merger.interesting_ids = interesting_ids
3170
merger.merge_type = merge_type
3171
merger.show_base = show_base
3172
merger.reprocess = reprocess
3173
conflicts = merger.do_merge()
3175
tree.set_parent_ids(parents)
4082
tree.set_parent_ids(parents)
4083
3179
if conflicts > 0:
4295
3344
" or specified.")
4296
3345
display_url = urlutils.unescape_for_display(parent,
4297
3346
self.outf.encoding)
4298
message("Using saved parent location: "
3347
self.outf.write("Using saved parent location: "
4299
3348
+ display_url + "\n")
4301
3350
remote_branch = Branch.open(other_branch)
4302
3351
if remote_branch.base == local_branch.base:
4303
3352
remote_branch = local_branch
4305
3353
local_branch.lock_read()
4306
self.add_cleanup(local_branch.unlock)
4307
local_revid_range = _revision_range_to_revid_range(
4308
_get_revision_range(my_revision, local_branch,
4311
remote_branch.lock_read()
4312
self.add_cleanup(remote_branch.unlock)
4313
remote_revid_range = _revision_range_to_revid_range(
4314
_get_revision_range(revision,
4315
remote_branch, self.name()))
4317
local_extra, remote_extra = find_unmerged(
4318
local_branch, remote_branch, restrict,
4319
backward=not reverse,
4320
include_merges=include_merges,
4321
local_revid_range=local_revid_range,
4322
remote_revid_range=remote_revid_range)
4324
if log_format is None:
4325
registry = log.log_formatter_registry
4326
log_format = registry.get_default(local_branch)
4327
lf = log_format(to_file=self.outf,
4329
show_timezone='original')
4332
if local_extra and not theirs_only:
4333
message("You have %d extra revision(s):\n" %
4335
for revision in iter_log_revisions(local_extra,
4336
local_branch.repository,
4338
lf.log_revision(revision)
4339
printed_local = True
4342
printed_local = False
4344
if remote_extra and not mine_only:
4345
if printed_local is True:
4347
message("You are missing %d revision(s):\n" %
4349
for revision in iter_log_revisions(remote_extra,
4350
remote_branch.repository,
4352
lf.log_revision(revision)
4355
if mine_only and not local_extra:
4356
# We checked local, and found nothing extra
4357
message('This branch is up to date.\n')
4358
elif theirs_only and not remote_extra:
4359
# We checked remote, and found nothing extra
4360
message('Other branch is up to date.\n')
4361
elif not (mine_only or theirs_only or local_extra or
4363
# We checked both branches, and neither one had extra
4365
message("Branches are up to date.\n")
3355
remote_branch.lock_read()
3357
local_extra, remote_extra = find_unmerged(
3358
local_branch, remote_branch, restrict)
3360
if log_format is None:
3361
registry = log.log_formatter_registry
3362
log_format = registry.get_default(local_branch)
3363
lf = log_format(to_file=self.outf,
3365
show_timezone='original')
3366
if reverse is False:
3367
if local_extra is not None:
3368
local_extra.reverse()
3369
if remote_extra is not None:
3370
remote_extra.reverse()
3373
if local_extra and not theirs_only:
3374
self.outf.write("You have %d extra revision(s):\n" %
3376
for revision in iter_log_revisions(local_extra,
3377
local_branch.repository,
3379
lf.log_revision(revision)
3380
printed_local = True
3383
printed_local = False
3385
if remote_extra and not mine_only:
3386
if printed_local is True:
3387
self.outf.write("\n\n\n")
3388
self.outf.write("You are missing %d revision(s):\n" %
3390
for revision in iter_log_revisions(remote_extra,
3391
remote_branch.repository,
3393
lf.log_revision(revision)
3396
if mine_only and not local_extra:
3397
# We checked local, and found nothing extra
3398
self.outf.write('This branch is up to date.\n')
3399
elif theirs_only and not remote_extra:
3400
# We checked remote, and found nothing extra
3401
self.outf.write('Other branch is up to date.\n')
3402
elif not (mine_only or theirs_only or local_extra or
3404
# We checked both branches, and neither one had extra
3406
self.outf.write("Branches are up to date.\n")
3408
remote_branch.unlock()
3410
local_branch.unlock()
4367
3411
if not status_code and parent is None and other_branch is not None:
4368
3412
local_branch.lock_write()
4369
self.add_cleanup(local_branch.unlock)
4370
# handle race conditions - a parent might be set while we run.
4371
if local_branch.get_parent() is None:
4372
local_branch.set_parent(remote_branch.base)
3414
# handle race conditions - a parent might be set while we run.
3415
if local_branch.get_parent() is None:
3416
local_branch.set_parent(remote_branch.base)
3418
local_branch.unlock()
4373
3419
return status_code
4813
3856
Option('allow-writes',
4814
3857
help='By default the server is a readonly server. Supplying '
4815
3858
'--allow-writes enables write access to the contents of '
4816
'the served directory and below. Note that ``bzr serve`` '
4817
'does not perform authentication, so unless some form of '
4818
'external authentication is arranged supplying this '
4819
'option leads to global uncontrolled write access to your '
3859
'the served directory and below.'
4824
def get_host_and_port(self, port):
4825
"""Return the host and port to run the smart server on.
4827
If 'port' is None, None will be returned for the host and port.
4829
If 'port' has a colon in it, the string before the colon will be
4830
interpreted as the host.
4832
:param port: A string of the port to run the server on.
4833
:return: A tuple of (host, port), where 'host' is a host name or IP,
4834
and port is an integer TCP/IP port.
4837
if port is not None:
4839
host, port = port.split(':')
4843
def run(self, port=None, inet=False, directory=None, allow_writes=False,
4845
from bzrlib.transport import get_transport, transport_server_registry
3863
def run(self, port=None, inet=False, directory=None, allow_writes=False):
3864
from bzrlib import lockdir
3865
from bzrlib.smart import medium, server
3866
from bzrlib.transport import get_transport
3867
from bzrlib.transport.chroot import ChrootServer
4846
3868
if directory is None:
4847
3869
directory = os.getcwd()
4848
if protocol is None:
4849
protocol = transport_server_registry.get()
4850
host, port = self.get_host_and_port(port)
4851
3870
url = urlutils.local_path_to_url(directory)
4852
3871
if not allow_writes:
4853
3872
url = 'readonly+' + url
4854
transport = get_transport(url)
4855
protocol(transport, host, port, inet)
3873
chroot_server = ChrootServer(get_transport(url))
3874
chroot_server.setUp()
3875
t = get_transport(chroot_server.get_url())
3877
smart_server = medium.SmartServerPipeStreamMedium(
3878
sys.stdin, sys.stdout, t)
3880
host = medium.BZR_DEFAULT_INTERFACE
3882
port = medium.BZR_DEFAULT_PORT
3885
host, port = port.split(':')
3887
smart_server = server.SmartTCPServer(t, host=host, port=port)
3888
print 'listening on port: ', smart_server.port
3890
# for the duration of this server, no UI output is permitted.
3891
# note that this may cause problems with blackbox tests. This should
3892
# be changed with care though, as we dont want to use bandwidth sending
3893
# progress over stderr to smart server clients!
3894
old_factory = ui.ui_factory
3895
old_lockdir_timeout = lockdir._DEFAULT_TIMEOUT_SECONDS
3897
ui.ui_factory = ui.SilentUIFactory()
3898
lockdir._DEFAULT_TIMEOUT_SECONDS = 0
3899
smart_server.serve()
3901
ui.ui_factory = old_factory
3902
lockdir._DEFAULT_TIMEOUT_SECONDS = old_lockdir_timeout
4858
3905
class cmd_join(Command):
4859
"""Combine a tree into its containing tree.
4861
This command requires the target tree to be in a rich-root format.
3906
"""Combine a subtree into its containing tree.
3908
This command is for experimental use only. It requires the target tree
3909
to be in dirstate-with-subtree format, which cannot be converted into
4863
3912
The TREE argument should be an independent tree, inside another tree, but
4864
3913
not part of it. (Such trees can be produced by "bzr split", but also by
5039
4095
directly from the merge directive, without retrieving data from a
5042
`bzr send` creates a compact data set that, when applied using bzr
5043
merge, has the same effect as merging from the source branch.
5045
By default the merge directive is self-contained and can be applied to any
5046
branch containing submit_branch in its ancestory without needing access to
5049
If --no-bundle is specified, then Bazaar doesn't send the contents of the
5050
revisions, but only a structured request to merge from the
5051
public_location. In that case the public_branch is needed and it must be
5052
up-to-date and accessible to the recipient. The public_branch is always
5053
included if known, so that people can check it later.
5055
The submit branch defaults to the parent of the source branch, but can be
5056
overridden. Both submit branch and public branch will be remembered in
5057
branch.conf the first time they are used for a particular branch. The
5058
source branch defaults to that containing the working directory, but can
5059
be changed using --from.
5061
In order to calculate those changes, bzr must analyse the submit branch.
5062
Therefore it is most efficient for the submit branch to be a local mirror.
5063
If a public location is known for the submit_branch, that location is used
5064
in the merge directive.
5066
The default behaviour is to send the merge directive by mail, unless -o is
5067
given, in which case it is sent to a file.
4098
If --no-bundle is specified, then public_branch is needed (and must be
4099
up-to-date), so that the receiver can perform the merge using the
4100
public_branch. The public_branch is always included if known, so that
4101
people can check it later.
4103
The submit branch defaults to the parent, but can be overridden. Both
4104
submit branch and public branch will be remembered if supplied.
4106
If a public_branch is known for the submit_branch, that public submit
4107
branch is used in the merge instructions. This means that a local mirror
4108
can be used as your actual submit branch, once you have set public_branch
5069
4111
Mail is sent using your preferred mail program. This should be transparent
5070
4112
on Windows (it uses MAPI). On Linux, it requires the xdg-email utility.
5071
4113
If the preferred client can't be found (or used), your editor will be used.
5073
4115
To use a specific mail program, set the mail_client configuration option.
5074
4116
(For Thunderbird 1.5, this works around some bugs.) Supported values for
5075
specific clients are "claws", "evolution", "kmail", "mail.app" (MacOS X's
5076
Mail.app), "mutt", and "thunderbird"; generic options are "default",
5077
"editor", "emacsclient", "mapi", and "xdg-email". Plugins may also add
4117
specific clients are "evolution", "kmail", "mutt", and "thunderbird";
4118
generic options are "default", "editor", "emacsclient", "mapi", and
4119
"xdg-email". Plugins may also add supported clients.
5080
4121
If mail is being sent, a to address is required. This can be supplied
5081
4122
either on the commandline, by setting the submit_to configuration
5082
option in the branch itself or the child_submit_to configuration option
4123
option in the branch itself or the child_submit_to configuration option
5083
4124
in the submit branch.
5085
4126
Two formats are currently supported: "4" uses revision bundle format 4 and
5118
4154
help='Write merge directive to this file; '
5119
4155
'use - for stdout.',
5122
help='Refuse to send if there are uncommitted changes in'
5123
' the working tree, --no-strict disables the check.'),
5124
4157
Option('mail-to', help='Mail the request to this address.',
5128
Option('body', help='Body for the email.', type=unicode),
5129
RegistryOption('format',
5130
help='Use the specified output format.',
5131
lazy_registry=('bzrlib.send', 'format_registry')),
4161
RegistryOption.from_kwargs('format',
4162
'Use the specified output format.',
4163
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4164
'0.9': 'Bundle format 0.9, Merge Directive 1',})
5134
4167
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
5135
4168
no_patch=False, revision=None, remember=False, output=None,
5136
format=None, mail_to=None, message=None, body=None,
5137
strict=None, **kwargs):
5138
from bzrlib.send import send
5139
return send(submit_branch, revision, public_branch, remember,
5140
format, no_bundle, no_patch, output,
5141
kwargs.get('from', '.'), mail_to, message, body,
4169
format='4', mail_to=None, message=None, **kwargs):
4170
return self._run(submit_branch, revision, public_branch, remember,
4171
format, no_bundle, no_patch, output,
4172
kwargs.get('from', '.'), mail_to, message)
4174
def _run(self, submit_branch, revision, public_branch, remember, format,
4175
no_bundle, no_patch, output, from_, mail_to, message):
4176
from bzrlib.revision import NULL_REVISION
4177
branch = Branch.open_containing(from_)[0]
4179
outfile = StringIO()
4183
outfile = open(output, 'wb')
4184
# we may need to write data into branch's repository to calculate
4189
config = branch.get_config()
4191
mail_to = config.get_user_option('submit_to')
4192
mail_client = config.get_mail_client()
4193
if remember and submit_branch is None:
4194
raise errors.BzrCommandError(
4195
'--remember requires a branch to be specified.')
4196
stored_submit_branch = branch.get_submit_branch()
4197
remembered_submit_branch = None
4198
if submit_branch is None:
4199
submit_branch = stored_submit_branch
4200
remembered_submit_branch = "submit"
4202
if stored_submit_branch is None or remember:
4203
branch.set_submit_branch(submit_branch)
4204
if submit_branch is None:
4205
submit_branch = branch.get_parent()
4206
remembered_submit_branch = "parent"
4207
if submit_branch is None:
4208
raise errors.BzrCommandError('No submit branch known or'
4210
if remembered_submit_branch is not None:
4211
note('Using saved %s location "%s" to determine what '
4212
'changes to submit.', remembered_submit_branch,
4216
submit_config = Branch.open(submit_branch).get_config()
4217
mail_to = submit_config.get_user_option("child_submit_to")
4219
stored_public_branch = branch.get_public_branch()
4220
if public_branch is None:
4221
public_branch = stored_public_branch
4222
elif stored_public_branch is None or remember:
4223
branch.set_public_branch(public_branch)
4224
if no_bundle and public_branch is None:
4225
raise errors.BzrCommandError('No public branch specified or'
4227
base_revision_id = None
4229
if revision is not None:
4230
if len(revision) > 2:
4231
raise errors.BzrCommandError('bzr send takes '
4232
'at most two one revision identifiers')
4233
revision_id = revision[-1].as_revision_id(branch)
4234
if len(revision) == 2:
4235
base_revision_id = revision[0].as_revision_id(branch)
4236
if revision_id is None:
4237
revision_id = branch.last_revision()
4238
if revision_id == NULL_REVISION:
4239
raise errors.BzrCommandError('No revisions to submit.')
4241
directive = merge_directive.MergeDirective2.from_objects(
4242
branch.repository, revision_id, time.time(),
4243
osutils.local_time_offset(), submit_branch,
4244
public_branch=public_branch, include_patch=not no_patch,
4245
include_bundle=not no_bundle, message=message,
4246
base_revision_id=base_revision_id)
4247
elif format == '0.9':
4250
patch_type = 'bundle'
4252
raise errors.BzrCommandError('Format 0.9 does not'
4253
' permit bundle with no patch')
4259
directive = merge_directive.MergeDirective.from_objects(
4260
branch.repository, revision_id, time.time(),
4261
osutils.local_time_offset(), submit_branch,
4262
public_branch=public_branch, patch_type=patch_type,
4265
outfile.writelines(directive.to_lines())
4267
subject = '[MERGE] '
4268
if message is not None:
4271
revision = branch.repository.get_revision(revision_id)
4272
subject += revision.get_summary()
4273
basename = directive.get_disk_name(branch)
4274
mail_client.compose_merge_request(mail_to, subject,
4275
outfile.getvalue(), basename)
5146
4282
class cmd_bundle_revisions(cmd_send):
5147
"""Create a merge-directive for submitting changes.
4284
"""Create a merge-directive for submiting changes.
5149
4286
A merge directive provides many things needed for requesting merges:
5368
4482
_see_also = ['branches', 'checkouts', 'standalone-trees', 'working-trees']
5369
4483
takes_args = ['location?']
5371
RegistryOption.from_kwargs(
5373
title='Target type',
5374
help='The type to reconfigure the directory to.',
5375
value_switches=True, enum_switch=False,
5376
branch='Reconfigure to be an unbound branch with no working tree.',
5377
tree='Reconfigure to be an unbound branch with a working tree.',
5378
checkout='Reconfigure to be a bound branch with a working tree.',
5379
lightweight_checkout='Reconfigure to be a lightweight'
5380
' checkout (with no local history).',
5381
standalone='Reconfigure to be a standalone branch '
5382
'(i.e. stop using shared repository).',
5383
use_shared='Reconfigure to use a shared repository.',
5384
with_trees='Reconfigure repository to create '
5385
'working trees on branches by default.',
5386
with_no_trees='Reconfigure repository to not create '
5387
'working trees on branches by default.'
5389
Option('bind-to', help='Branch to bind checkout to.', type=str),
5391
help='Perform reconfiguration even if local changes'
5393
Option('stacked-on',
5394
help='Reconfigure a branch to be stacked on another branch.',
5398
help='Reconfigure a branch to be unstacked. This '
5399
'may require copying substantial data into it.',
4484
takes_options = [RegistryOption.from_kwargs('target_type',
4485
title='Target type',
4486
help='The type to reconfigure the directory to.',
4487
value_switches=True, enum_switch=False,
4488
branch='Reconfigure to be an unbound branch '
4489
'with no working tree.',
4490
tree='Reconfigure to be an unbound branch '
4491
'with a working tree.',
4492
checkout='Reconfigure to be a bound branch '
4493
'with a working tree.',
4494
lightweight_checkout='Reconfigure to be a lightweight'
4495
' checkout (with no local history).',
4496
standalone='Reconfigure to be a standalone branch '
4497
'(i.e. stop using shared repository).',
4498
use_shared='Reconfigure to use a shared repository.'),
4499
Option('bind-to', help='Branch to bind checkout to.',
4502
help='Perform reconfiguration even if local changes'
5403
def run(self, location=None, target_type=None, bind_to=None, force=False,
4506
def run(self, location=None, target_type=None, bind_to=None, force=False):
5406
4507
directory = bzrdir.BzrDir.open(location)
5407
if stacked_on and unstacked:
5408
raise BzrCommandError("Can't use both --stacked-on and --unstacked")
5409
elif stacked_on is not None:
5410
reconfigure.ReconfigureStackedOn().apply(directory, stacked_on)
5412
reconfigure.ReconfigureUnstacked().apply(directory)
5413
# At the moment you can use --stacked-on and a different
5414
# reconfiguration shape at the same time; there seems no good reason
5416
4508
if target_type is None:
5417
if stacked_on or unstacked:
5420
raise errors.BzrCommandError('No target configuration '
4509
raise errors.BzrCommandError('No target configuration specified')
5422
4510
elif target_type == 'branch':
5423
4511
reconfiguration = reconfigure.Reconfigure.to_branch(directory)
5424
4512
elif target_type == 'tree':
5425
4513
reconfiguration = reconfigure.Reconfigure.to_tree(directory)
5426
4514
elif target_type == 'checkout':
5427
reconfiguration = reconfigure.Reconfigure.to_checkout(
4515
reconfiguration = reconfigure.Reconfigure.to_checkout(directory,
5429
4517
elif target_type == 'lightweight-checkout':
5430
4518
reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
5431
4519
directory, bind_to)
5459
4541
directory of the current branch. For example, if you are currently in a
5460
4542
checkout of /path/to/branch, specifying 'newbranch' will find a branch at
5461
4543
/path/to/newbranch.
5463
Bound branches use the nickname of its master branch unless it is set
5464
locally, in which case switching will update the local nickname to be
5468
takes_args = ['to_location?']
4546
takes_args = ['to_location']
5469
4547
takes_options = [Option('force',
5470
help='Switch even if local commits will be lost.'),
5472
Option('create-branch', short_name='b',
5473
help='Create the target branch from this one before'
5474
' switching to it.'),
4548
help='Switch even if local commits will be lost.')
5477
def run(self, to_location=None, force=False, create_branch=False,
4551
def run(self, to_location, force=False):
5479
4552
from bzrlib import switch
5480
4553
tree_location = '.'
5481
revision = _get_one_revision('switch', revision)
5482
4554
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
5483
if to_location is None:
5484
if revision is None:
5485
raise errors.BzrCommandError('You must supply either a'
5486
' revision or a location')
5489
branch = control_dir.open_branch()
5490
had_explicit_nick = branch.get_config().has_explicit_nickname()
4556
to_branch = Branch.open(to_location)
5491
4557
except errors.NotBranchError:
5493
had_explicit_nick = False
5496
raise errors.BzrCommandError('cannot create branch without'
5498
to_location = directory_service.directories.dereference(
5500
if '/' not in to_location and '\\' not in to_location:
5501
# This path is meant to be relative to the existing branch
5502
this_url = self._get_branch_location(control_dir)
5503
to_location = urlutils.join(this_url, '..', to_location)
5504
to_branch = branch.bzrdir.sprout(to_location,
5505
possible_transports=[branch.bzrdir.root_transport],
5506
source_branch=branch).open_branch()
5509
to_branch = Branch.open(to_location)
5510
except errors.NotBranchError:
5511
this_url = self._get_branch_location(control_dir)
5512
to_branch = Branch.open(
5513
urlutils.join(this_url, '..', to_location))
5514
if revision is not None:
5515
revision = revision.as_revision_id(to_branch)
5516
switch.switch(control_dir, to_branch, force, revision_id=revision)
5517
if had_explicit_nick:
5518
branch = control_dir.open_branch() #get the new branch!
5519
branch.nick = to_branch.nick
4558
to_branch = Branch.open(
4559
control_dir.open_branch().base + '../' + to_location)
4560
switch.switch(control_dir, to_branch, force)
5520
4561
note('Switched to branch: %s',
5521
4562
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
5523
def _get_branch_location(self, control_dir):
5524
"""Return location of branch for this control dir."""
5526
this_branch = control_dir.open_branch()
5527
# This may be a heavy checkout, where we want the master branch
5528
master_location = this_branch.get_bound_location()
5529
if master_location is not None:
5530
return master_location
5531
# If not, use a local sibling
5532
return this_branch.base
5533
except errors.NotBranchError:
5534
format = control_dir.find_branch_format()
5535
if getattr(format, 'get_reference', None) is not None:
5536
return format.get_reference(control_dir)
5538
return control_dir.root_transport.base
5541
class cmd_view(Command):
5542
"""Manage filtered views.
5544
Views provide a mask over the tree so that users can focus on
5545
a subset of a tree when doing their work. After creating a view,
5546
commands that support a list of files - status, diff, commit, etc -
5547
effectively have that list of files implicitly given each time.
5548
An explicit list of files can still be given but those files
5549
must be within the current view.
5551
In most cases, a view has a short life-span: it is created to make
5552
a selected change and is deleted once that change is committed.
5553
At other times, you may wish to create one or more named views
5554
and switch between them.
5556
To disable the current view without deleting it, you can switch to
5557
the pseudo view called ``off``. This can be useful when you need
5558
to see the whole tree for an operation or two (e.g. merge) but
5559
want to switch back to your view after that.
5562
To define the current view::
5564
bzr view file1 dir1 ...
5566
To list the current view::
5570
To delete the current view::
5574
To disable the current view without deleting it::
5576
bzr view --switch off
5578
To define a named view and switch to it::
5580
bzr view --name view-name file1 dir1 ...
5582
To list a named view::
5584
bzr view --name view-name
5586
To delete a named view::
5588
bzr view --name view-name --delete
5590
To switch to a named view::
5592
bzr view --switch view-name
5594
To list all views defined::
5598
To delete all views::
5600
bzr view --delete --all
5604
takes_args = ['file*']
5607
help='Apply list or delete action to all views.',
5610
help='Delete the view.',
5613
help='Name of the view to define, list or delete.',
5617
help='Name of the view to switch to.',
5622
def run(self, file_list,
5628
tree, file_list = tree_files(file_list, apply_view=False)
5629
current_view, view_dict = tree.views.get_view_info()
5634
raise errors.BzrCommandError(
5635
"Both --delete and a file list specified")
5637
raise errors.BzrCommandError(
5638
"Both --delete and --switch specified")
5640
tree.views.set_view_info(None, {})
5641
self.outf.write("Deleted all views.\n")
5643
raise errors.BzrCommandError("No current view to delete")
5645
tree.views.delete_view(name)
5646
self.outf.write("Deleted '%s' view.\n" % name)
5649
raise errors.BzrCommandError(
5650
"Both --switch and a file list specified")
5652
raise errors.BzrCommandError(
5653
"Both --switch and --all specified")
5654
elif switch == 'off':
5655
if current_view is None:
5656
raise errors.BzrCommandError("No current view to disable")
5657
tree.views.set_view_info(None, view_dict)
5658
self.outf.write("Disabled '%s' view.\n" % (current_view))
5660
tree.views.set_view_info(switch, view_dict)
5661
view_str = views.view_display_str(tree.views.lookup_view())
5662
self.outf.write("Using '%s' view: %s\n" % (switch, view_str))
5665
self.outf.write('Views defined:\n')
5666
for view in sorted(view_dict):
5667
if view == current_view:
5671
view_str = views.view_display_str(view_dict[view])
5672
self.outf.write('%s %-20s %s\n' % (active, view, view_str))
5674
self.outf.write('No views defined.\n')
5677
# No name given and no current view set
5680
raise errors.BzrCommandError(
5681
"Cannot change the 'off' pseudo view")
5682
tree.views.set_view(name, sorted(file_list))
5683
view_str = views.view_display_str(tree.views.lookup_view())
5684
self.outf.write("Using '%s' view: %s\n" % (name, view_str))
5688
# No name given and no current view set
5689
self.outf.write('No current view.\n')
5691
view_str = views.view_display_str(tree.views.lookup_view(name))
5692
self.outf.write("'%s' view is: %s\n" % (name, view_str))
5695
4565
class cmd_hooks(Command):
5701
for hook_key in sorted(hooks.known_hooks.keys()):
5702
some_hooks = hooks.known_hooks_key_to_object(hook_key)
5703
self.outf.write("%s:\n" % type(some_hooks).__name__)
5704
for hook_name, hook_point in sorted(some_hooks.items()):
5705
self.outf.write(" %s:\n" % (hook_name,))
5706
found_hooks = list(hook_point)
5708
for hook in found_hooks:
5709
self.outf.write(" %s\n" %
5710
(some_hooks.get_hook_name(hook),))
5712
self.outf.write(" <no hooks installed>\n")
5715
class cmd_shelve(Command):
5716
"""Temporarily set aside some changes from the current tree.
5718
Shelve allows you to temporarily put changes you've made "on the shelf",
5719
ie. out of the way, until a later time when you can bring them back from
5720
the shelf with the 'unshelve' command. The changes are stored alongside
5721
your working tree, and so they aren't propagated along with your branch nor
5722
will they survive its deletion.
5724
If shelve --list is specified, previously-shelved changes are listed.
5726
Shelve is intended to help separate several sets of changes that have
5727
been inappropriately mingled. If you just want to get rid of all changes
5728
and you don't need to restore them later, use revert. If you want to
5729
shelve all text changes at once, use shelve --all.
5731
If filenames are specified, only the changes to those files will be
5732
shelved. Other files will be left untouched.
5734
If a revision is specified, changes since that revision will be shelved.
5736
You can put multiple items on the shelf, and by default, 'unshelve' will
5737
restore the most recently shelved changes.
5740
takes_args = ['file*']
5744
Option('all', help='Shelve all changes.'),
5746
RegistryOption('writer', 'Method to use for writing diffs.',
5747
bzrlib.option.diff_writer_registry,
5748
value_switches=True, enum_switch=False),
5750
Option('list', help='List shelved changes.'),
5752
help='Destroy removed changes instead of shelving them.'),
5754
_see_also = ['unshelve']
5756
def run(self, revision=None, all=False, file_list=None, message=None,
5757
writer=None, list=False, destroy=False):
5759
return self.run_for_list()
5760
from bzrlib.shelf_ui import Shelver
5762
writer = bzrlib.option.diff_writer_registry.get()
5764
shelver = Shelver.from_args(writer(sys.stdout), revision, all,
5765
file_list, message, destroy=destroy)
5770
except errors.UserAbort:
5773
def run_for_list(self):
5774
tree = WorkingTree.open_containing('.')[0]
5776
self.add_cleanup(tree.unlock)
5777
manager = tree.get_shelf_manager()
5778
shelves = manager.active_shelves()
5779
if len(shelves) == 0:
5780
note('No shelved changes.')
5782
for shelf_id in reversed(shelves):
5783
message = manager.get_metadata(shelf_id).get('message')
5785
message = '<no message>'
5786
self.outf.write('%3d: %s\n' % (shelf_id, message))
5790
class cmd_unshelve(Command):
5791
"""Restore shelved changes.
5793
By default, the most recently shelved changes are restored. However if you
5794
specify a shelf by id those changes will be restored instead. This works
5795
best when the changes don't depend on each other.
5798
takes_args = ['shelf_id?']
5800
RegistryOption.from_kwargs(
5801
'action', help="The action to perform.",
5802
enum_switch=False, value_switches=True,
5803
apply="Apply changes and remove from the shelf.",
5804
dry_run="Show changes, but do not apply or remove them.",
5805
preview="Instead of unshelving the changes, show the diff that "
5806
"would result from unshelving.",
5807
delete_only="Delete changes without applying them.",
5808
keep="Apply changes but don't delete them.",
5811
_see_also = ['shelve']
5813
def run(self, shelf_id=None, action='apply'):
5814
from bzrlib.shelf_ui import Unshelver
5815
unshelver = Unshelver.from_args(shelf_id, action)
5819
unshelver.tree.unlock()
5822
class cmd_clean_tree(Command):
5823
"""Remove unwanted files from working tree.
5825
By default, only unknown files, not ignored files, are deleted. Versioned
5826
files are never deleted.
5828
Another class is 'detritus', which includes files emitted by bzr during
5829
normal operations and selftests. (The value of these files decreases with
5832
If no options are specified, unknown files are deleted. Otherwise, option
5833
flags are respected, and may be combined.
5835
To check what clean-tree will do, use --dry-run.
5837
takes_options = [Option('ignored', help='Delete all ignored files.'),
5838
Option('detritus', help='Delete conflict files, merge'
5839
' backups, and failed selftest dirs.'),
5841
help='Delete files unknown to bzr (default).'),
5842
Option('dry-run', help='Show files to delete instead of'
5844
Option('force', help='Do not prompt before deleting.')]
5845
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5847
from bzrlib.clean_tree import clean_tree
5848
if not (unknown or ignored or detritus):
5852
clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
5853
dry_run=dry_run, no_prompt=force)
5856
class cmd_reference(Command):
5857
"""list, view and set branch locations for nested trees.
5859
If no arguments are provided, lists the branch locations for nested trees.
5860
If one argument is provided, display the branch location for that tree.
5861
If two arguments are provided, set the branch location for that tree.
5866
takes_args = ['path?', 'location?']
5868
def run(self, path=None, location=None):
5870
if path is not None:
5872
tree, branch, relpath =(
5873
bzrdir.BzrDir.open_containing_tree_or_branch(branchdir))
5874
if path is not None:
5877
tree = branch.basis_tree()
4566
"""Show a branch's currently registered hooks.
4570
takes_args = ['path?']
4572
def run(self, path=None):
5878
4573
if path is None:
5879
info = branch._get_all_reference_info().iteritems()
5880
self._display_reference_info(tree, branch, info)
4575
branch_hooks = Branch.open(path).hooks
4576
for hook_type in branch_hooks:
4577
hooks = branch_hooks[hook_type]
4578
self.outf.write("%s:\n" % (hook_type,))
4581
self.outf.write(" %s\n" %
4582
(branch_hooks.get_hook_name(hook),))
4584
self.outf.write(" <no hooks installed>\n")
4587
def _create_prefix(cur_transport):
4588
needed = [cur_transport]
4589
# Recurse upwards until we can create a directory successfully
4591
new_transport = cur_transport.clone('..')
4592
if new_transport.base == cur_transport.base:
4593
raise errors.BzrCommandError(
4594
"Failed to create path prefix for %s."
4595
% cur_transport.base)
4597
new_transport.mkdir('.')
4598
except errors.NoSuchFile:
4599
needed.append(new_transport)
4600
cur_transport = new_transport
5882
file_id = tree.path2id(path)
5884
raise errors.NotVersionedError(path)
5885
if location is None:
5886
info = [(file_id, branch.get_reference_info(file_id))]
5887
self._display_reference_info(tree, branch, info)
5889
branch.set_reference_info(file_id, path, location)
5891
def _display_reference_info(self, tree, branch, info):
5893
for file_id, (path, location) in info:
5895
path = tree.id2path(file_id)
5896
except errors.NoSuchId:
5898
ref_list.append((path, location))
5899
for path, location in sorted(ref_list):
5900
self.outf.write('%s %s\n' % (path, location))
4603
# Now we only need to create child directories
4605
cur_transport = needed.pop()
4606
cur_transport.ensure_base()
5903
4609
# these get imported and then picked up by the scan for cmd_*
5904
4610
# TODO: Some more consistent way to split command definitions across files;
5905
# we do need to load at least some information about them to know of
4611
# we do need to load at least some information about them to know of
5906
4612
# aliases. ideally we would avoid loading the implementation until the
5907
4613
# details were needed.
5908
4614
from bzrlib.cmd_version_info import cmd_version_info