65
70
from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
68
def tree_files(file_list, default_branch=u'.', canonicalize=True):
73
def tree_files(file_list, default_branch=u'.', canonicalize=True,
70
return internal_tree_files(file_list, default_branch, canonicalize)
76
return internal_tree_files(file_list, default_branch, canonicalize,
71
78
except errors.FileInWrongBranch, e:
72
79
raise errors.BzrCommandError("%s is not in the same branch as %s" %
73
80
(e.path, file_list[0]))
83
def tree_files_for_add(file_list):
85
Return a tree and list of absolute paths from a file list.
87
Similar to tree_files, but add handles files a bit differently, so it a
88
custom implementation. In particular, MutableTreeTree.smart_add expects
89
absolute paths, which it immediately converts to relative paths.
91
# FIXME Would be nice to just return the relative paths like
92
# internal_tree_files does, but there are a large number of unit tests
93
# that assume the current interface to mutabletree.smart_add
95
tree, relpath = WorkingTree.open_containing(file_list[0])
96
if tree.supports_views():
97
view_files = tree.views.lookup_view()
99
for filename in file_list:
100
if not osutils.is_inside_any(view_files, filename):
101
raise errors.FileOutsideView(filename, view_files)
102
file_list = file_list[:]
103
file_list[0] = tree.abspath(relpath)
105
tree = WorkingTree.open_containing(u'.')[0]
106
if tree.supports_views():
107
view_files = tree.views.lookup_view()
109
file_list = view_files
110
view_str = views.view_display_str(view_files)
111
note("Ignoring files outside view. View is %s" % view_str)
112
return tree, file_list
115
def _get_one_revision(command_name, revisions):
116
if revisions is None:
118
if len(revisions) != 1:
119
raise errors.BzrCommandError(
120
'bzr %s --revision takes exactly one revision identifier' % (
76
125
def _get_one_revision_tree(command_name, revisions, branch=None, tree=None):
126
"""Get a revision tree. Not suitable for commands that change the tree.
128
Specifically, the basis tree in dirstate trees is coupled to the dirstate
129
and doing a commit/uncommit/pull will at best fail due to changing the
132
If tree is passed in, it should be already locked, for lifetime management
133
of the trees internal cached state.
77
135
if branch is None:
78
136
branch = tree.branch
79
137
if revisions is None:
101
157
The filenames given are not required to exist.
103
:param file_list: Filenames to convert.
159
:param file_list: Filenames to convert.
105
161
:param default_branch: Fallback tree path to use if file_list is empty or
164
:param apply_view: if True and a view is set, apply it or check that
165
specified files are within it
108
167
:return: workingtree, [relative_paths]
110
169
if file_list is None or len(file_list) == 0:
111
return WorkingTree.open_containing(default_branch)[0], file_list
170
tree = WorkingTree.open_containing(default_branch)[0]
171
if tree.supports_views() and apply_view:
172
view_files = tree.views.lookup_view()
174
file_list = view_files
175
view_str = views.view_display_str(view_files)
176
note("Ignoring files outside view. View is %s" % view_str)
177
return tree, file_list
112
178
tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
113
return tree, safe_relpath_files(tree, file_list, canonicalize)
116
def safe_relpath_files(tree, file_list, canonicalize=True):
179
return tree, safe_relpath_files(tree, file_list, canonicalize,
180
apply_view=apply_view)
183
def safe_relpath_files(tree, file_list, canonicalize=True, apply_view=True):
117
184
"""Convert file_list into a list of relpaths in tree.
119
186
:param tree: A tree to operate on.
120
187
:param file_list: A list of user provided paths or None.
188
:param apply_view: if True and a view is set, apply it or check that
189
specified files are within it
121
190
:return: A list of relative paths.
122
191
:raises errors.PathNotChild: When a provided path is in a different tree
125
194
if file_list is None:
196
if tree.supports_views() and apply_view:
197
view_files = tree.views.lookup_view()
128
201
# tree.relpath exists as a "thunk" to osutils, but canonical_relpath
129
202
# doesn't - fix that up here before we enter the loop.
534
Option('tree', help='Show revno of working tree'),
423
def run(self, revision=None, directory=u'.', revision_info_list=[]):
538
def run(self, revision=None, directory=u'.', tree=False,
539
revision_info_list=[]):
542
wt = WorkingTree.open_containing(directory)[0]
545
self.add_cleanup(wt.unlock)
546
except (errors.NoWorkingTree, errors.NotLocalUrl):
548
b = Branch.open_containing(directory)[0]
550
self.add_cleanup(b.unlock)
426
552
if revision is not None:
427
revs.extend(revision)
553
revision_ids.extend(rev.as_revision_id(b) for rev in revision)
428
554
if revision_info_list is not None:
429
for rev in revision_info_list:
430
revs.append(RevisionSpec.from_string(rev))
432
b = Branch.open_containing(directory)[0]
435
revs.append(RevisionSpec.from_string('-1'))
438
revision_id = rev.as_revision_id(b)
555
for rev_str in revision_info_list:
556
rev_spec = RevisionSpec.from_string(rev_str)
557
revision_ids.append(rev_spec.as_revision_id(b))
558
# No arguments supplied, default to the last revision
559
if len(revision_ids) == 0:
562
raise errors.NoWorkingTree(directory)
563
revision_ids.append(wt.last_revision())
565
revision_ids.append(b.last_revision())
569
for revision_id in revision_ids:
440
revno = '%4d' % (b.revision_id_to_revno(revision_id))
571
dotted_revno = b.revision_id_to_dotted_revno(revision_id)
572
revno = '.'.join(str(i) for i in dotted_revno)
441
573
except errors.NoSuchRevision:
442
dotted_map = b.get_revision_id_to_revno_map()
443
revno = '.'.join(str(i) for i in dotted_map[revision_id])
444
print '%s %s' % (revno, revision_id)
575
maxlen = max(maxlen, len(revno))
576
revinfos.append([revno, revision_id])
580
self.outf.write('%*s %s\n' % (maxlen, ri[0], ri[1]))
447
583
class cmd_add(Command):
448
584
"""Add specified files or directories.
600
724
if kind and kind not in ['file', 'directory', 'symlink']:
601
725
raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
727
revision = _get_one_revision('inventory', revision)
603
728
work_tree, file_list = tree_files(file_list)
604
729
work_tree.lock_read()
606
if revision is not None:
607
if len(revision) > 1:
608
raise errors.BzrCommandError(
609
'bzr inventory --revision takes exactly one revision'
611
tree = revision[0].as_tree(work_tree.branch)
613
extra_trees = [work_tree]
619
if file_list is not None:
620
file_ids = tree.paths2ids(file_list, trees=extra_trees,
621
require_versioned=True)
622
# find_ids_across_trees may include some paths that don't
624
entries = sorted((tree.id2path(file_id), tree.inventory[file_id])
625
for file_id in file_ids if file_id in tree)
627
entries = tree.inventory.entries()
630
if tree is not work_tree:
730
self.add_cleanup(work_tree.unlock)
731
if revision is not None:
732
tree = revision.as_tree(work_tree.branch)
734
extra_trees = [work_tree]
736
self.add_cleanup(tree.unlock)
741
if file_list is not None:
742
file_ids = tree.paths2ids(file_list, trees=extra_trees,
743
require_versioned=True)
744
# find_ids_across_trees may include some paths that don't
746
entries = sorted((tree.id2path(file_id), tree.inventory[file_id])
747
for file_id in file_ids if file_id in tree)
749
entries = tree.inventory.entries()
633
752
for path, entry in entries:
634
753
if kind and kind != entry.kind:
664
783
takes_args = ['names*']
665
784
takes_options = [Option("after", help="Move only the bzr identifier"
666
785
" of the file, because the file has already been moved."),
786
Option('auto', help='Automatically guess renames.'),
787
Option('dry-run', help='Avoid making changes when guessing renames.'),
668
789
aliases = ['move', 'rename']
669
790
encoding_type = 'replace'
671
def run(self, names_list, after=False):
792
def run(self, names_list, after=False, auto=False, dry_run=False):
794
return self.run_auto(names_list, after, dry_run)
796
raise errors.BzrCommandError('--dry-run requires --auto.')
672
797
if names_list is None:
675
799
if len(names_list) < 2:
676
800
raise errors.BzrCommandError("missing file argument")
677
801
tree, rel_names = tree_files(names_list, canonicalize=False)
680
self._run(tree, names_list, rel_names, after)
802
tree.lock_tree_write()
803
self.add_cleanup(tree.unlock)
804
self._run(tree, names_list, rel_names, after)
806
def run_auto(self, names_list, after, dry_run):
807
if names_list is not None and len(names_list) > 1:
808
raise errors.BzrCommandError('Only one path may be specified to'
811
raise errors.BzrCommandError('--after cannot be specified with'
813
work_tree, file_list = tree_files(names_list, default_branch='.')
814
work_tree.lock_tree_write()
815
self.add_cleanup(work_tree.unlock)
816
rename_map.RenameMap.guess_renames(work_tree, dry_run)
684
818
def _run(self, tree, names_list, rel_names, after):
685
819
into_existing = osutils.isdir(names_list[-1])
848
995
if branch_to.get_parent() is None or remember:
849
996
branch_to.set_parent(branch_from.base)
998
if branch_from is not branch_to:
999
branch_from.lock_read()
1000
self.add_cleanup(branch_from.unlock)
851
1001
if revision is not None:
852
if len(revision) == 1:
853
revision_id = revision[0].as_revision_id(branch_from)
855
raise errors.BzrCommandError(
856
'bzr pull --revision takes one value.')
1002
revision_id = revision.as_revision_id(branch_from)
858
1004
branch_to.lock_write()
860
if tree_to is not None:
861
change_reporter = delta._ChangeReporter(
862
unversioned_filter=tree_to.is_ignored)
863
result = tree_to.pull(branch_from, overwrite, revision_id,
865
possible_transports=possible_transports)
867
result = branch_to.pull(branch_from, overwrite, revision_id)
1005
self.add_cleanup(branch_to.unlock)
1006
if tree_to is not None:
1007
view_info = _get_view_info_for_change_reporter(tree_to)
1008
change_reporter = delta._ChangeReporter(
1009
unversioned_filter=tree_to.is_ignored,
1010
view_info=view_info)
1011
result = tree_to.pull(
1012
branch_from, overwrite, revision_id, change_reporter,
1013
possible_transports=possible_transports, local=local)
1015
result = branch_to.pull(
1016
branch_from, overwrite, revision_id, local=local)
869
result.report(self.outf)
870
if verbose and result.old_revid != result.new_revid:
871
log.show_branch_change(branch_to, self.outf, result.old_revno,
1018
result.report(self.outf)
1019
if verbose and result.old_revid != result.new_revid:
1020
log.show_branch_change(
1021
branch_to, self.outf, result.old_revno,
877
1025
class cmd_push(Command):
878
1026
"""Update a mirror of this branch.
880
1028
The target branch will not have its working tree populated because this
881
1029
is both expensive, and is not supported on remote file systems.
883
1031
Some smart servers or protocols *may* put the working tree in place in
931
1082
def run(self, location=None, remember=False, overwrite=False,
932
1083
create_prefix=False, verbose=False, revision=None,
933
1084
use_existing_dir=False, directory=None, stacked_on=None,
1085
stacked=False, strict=None):
935
1086
from bzrlib.push import _show_push_branch
937
# Get the source branch and revision_id
938
1088
if directory is None:
940
br_from = Branch.open_containing(directory)[0]
1090
# Get the source branch
1092
_unused) = bzrdir.BzrDir.open_containing_tree_or_branch(directory)
1094
strict = br_from.get_config().get_user_option_as_bool('push_strict')
1095
if strict is None: strict = True # default value
1096
# Get the tip's revision_id
1097
revision = _get_one_revision('push', revision)
941
1098
if revision is not None:
942
if len(revision) == 1:
943
revision_id = revision[0].in_history(br_from).rev_id
945
raise errors.BzrCommandError(
946
'bzr push --revision takes one value.')
1099
revision_id = revision.in_history(br_from).rev_id
948
revision_id = br_from.last_revision()
1102
if strict and tree is not None and revision_id is None:
1103
if (tree.has_changes()):
1104
raise errors.UncommittedChanges(
1105
tree, more='Use --no-strict to force the push.')
1106
if tree.last_revision() != tree.branch.last_revision():
1107
# The tree has lost sync with its branch, there is little
1108
# chance that the user is aware of it but he can still force
1109
# the push with --no-strict
1110
raise errors.OutOfDateTree(
1111
tree, more='Use --no-strict to force the push.')
950
1113
# Get the stacked_on branch, if any
951
1114
if stacked_on is not None:
1001
1164
takes_args = ['from_location', 'to_location?']
1002
1165
takes_options = ['revision', Option('hardlink',
1003
1166
help='Hard-link working tree files where possible.'),
1168
help="Create a branch without a working-tree."),
1170
help="Switch the checkout in the current directory "
1171
"to the new branch."),
1004
1172
Option('stacked',
1005
1173
help='Create a stacked branch referring to the source branch. '
1006
1174
'The new branch will depend on the availability of the source '
1007
1175
'branch for all operations.'),
1008
1176
Option('standalone',
1009
1177
help='Do not use a shared repository, even if available.'),
1178
Option('use-existing-dir',
1179
help='By default branch will fail if the target'
1180
' directory exists, but does not already'
1181
' have a control directory. This flag will'
1182
' allow branch to proceed.'),
1184
help="Bind new branch to from location."),
1011
1186
aliases = ['get', 'clone']
1013
1188
def run(self, from_location, to_location=None, revision=None,
1014
hardlink=False, stacked=False, standalone=False):
1189
hardlink=False, stacked=False, standalone=False, no_tree=False,
1190
use_existing_dir=False, switch=False, bind=False):
1191
from bzrlib import switch as _mod_switch
1015
1192
from bzrlib.tag import _merge_tags_if_possible
1016
if revision is None:
1018
elif len(revision) > 1:
1019
raise errors.BzrCommandError(
1020
'bzr branch --revision takes exactly 1 revision value')
1022
1193
accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1195
revision = _get_one_revision('branch', revision)
1024
1196
br_from.lock_read()
1197
self.add_cleanup(br_from.unlock)
1198
if revision is not None:
1199
revision_id = revision.as_revision_id(br_from)
1201
# FIXME - wt.last_revision, fallback to branch, fall back to
1202
# None or perhaps NULL_REVISION to mean copy nothing
1204
revision_id = br_from.last_revision()
1205
if to_location is None:
1206
to_location = urlutils.derive_to_location(from_location)
1207
to_transport = transport.get_transport(to_location)
1026
if len(revision) == 1 and revision[0] is not None:
1027
revision_id = revision[0].as_revision_id(br_from)
1209
to_transport.mkdir('.')
1210
except errors.FileExists:
1211
if not use_existing_dir:
1212
raise errors.BzrCommandError('Target directory "%s" '
1213
'already exists.' % to_location)
1029
# FIXME - wt.last_revision, fallback to branch, fall back to
1030
# None or perhaps NULL_REVISION to mean copy nothing
1032
revision_id = br_from.last_revision()
1033
if to_location is None:
1034
to_location = urlutils.derive_to_location(from_location)
1035
to_transport = transport.get_transport(to_location)
1037
to_transport.mkdir('.')
1038
except errors.FileExists:
1039
raise errors.BzrCommandError('Target directory "%s" already'
1040
' exists.' % to_location)
1041
except errors.NoSuchFile:
1042
raise errors.BzrCommandError('Parent of "%s" does not exist.'
1045
# preserve whatever source format we have.
1046
dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
1047
possible_transports=[to_transport],
1048
accelerator_tree=accelerator_tree,
1049
hardlink=hardlink, stacked=stacked,
1050
force_new_repo=standalone,
1051
source_branch=br_from)
1052
branch = dir.open_branch()
1053
except errors.NoSuchRevision:
1054
to_transport.delete_tree('.')
1055
msg = "The branch %s has no revision %s." % (from_location,
1057
raise errors.BzrCommandError(msg)
1058
_merge_tags_if_possible(br_from, branch)
1059
# If the source branch is stacked, the new branch may
1060
# be stacked whether we asked for that explicitly or not.
1061
# We therefore need a try/except here and not just 'if stacked:'
1063
note('Created new stacked branch referring to %s.' %
1064
branch.get_stacked_on_url())
1065
except (errors.NotStacked, errors.UnstackableBranchFormat,
1066
errors.UnstackableRepositoryFormat), e:
1067
note('Branched %d revision(s).' % branch.revno())
1216
bzrdir.BzrDir.open_from_transport(to_transport)
1217
except errors.NotBranchError:
1220
raise errors.AlreadyBranchError(to_location)
1221
except errors.NoSuchFile:
1222
raise errors.BzrCommandError('Parent of "%s" does not exist.'
1225
# preserve whatever source format we have.
1226
dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
1227
possible_transports=[to_transport],
1228
accelerator_tree=accelerator_tree,
1229
hardlink=hardlink, stacked=stacked,
1230
force_new_repo=standalone,
1231
create_tree_if_local=not no_tree,
1232
source_branch=br_from)
1233
branch = dir.open_branch()
1234
except errors.NoSuchRevision:
1235
to_transport.delete_tree('.')
1236
msg = "The branch %s has no revision %s." % (from_location,
1238
raise errors.BzrCommandError(msg)
1239
_merge_tags_if_possible(br_from, branch)
1240
# If the source branch is stacked, the new branch may
1241
# be stacked whether we asked for that explicitly or not.
1242
# We therefore need a try/except here and not just 'if stacked:'
1244
note('Created new stacked branch referring to %s.' %
1245
branch.get_stacked_on_url())
1246
except (errors.NotStacked, errors.UnstackableBranchFormat,
1247
errors.UnstackableRepositoryFormat), e:
1248
note('Branched %d revision(s).' % branch.revno())
1250
# Bind to the parent
1251
parent_branch = Branch.open(from_location)
1252
branch.bind(parent_branch)
1253
note('New branch bound to %s' % from_location)
1255
# Switch to the new branch
1256
wt, _ = WorkingTree.open_containing('.')
1257
_mod_switch.switch(wt.bzrdir, branch)
1258
note('Switched to branch: %s',
1259
urlutils.unescape_for_display(branch.base, 'utf-8'))
1072
1262
class cmd_checkout(Command):
1155
1341
def run(self, dir=u'.'):
1156
1342
tree = WorkingTree.open_containing(dir)[0]
1157
1343
tree.lock_read()
1159
new_inv = tree.inventory
1160
old_tree = tree.basis_tree()
1161
old_tree.lock_read()
1163
old_inv = old_tree.inventory
1165
iterator = tree.iter_changes(old_tree, include_unchanged=True)
1166
for f, paths, c, v, p, n, k, e in iterator:
1167
if paths[0] == paths[1]:
1171
renames.append(paths)
1173
for old_name, new_name in renames:
1174
self.outf.write("%s => %s\n" % (old_name, new_name))
1344
self.add_cleanup(tree.unlock)
1345
new_inv = tree.inventory
1346
old_tree = tree.basis_tree()
1347
old_tree.lock_read()
1348
self.add_cleanup(old_tree.unlock)
1349
old_inv = old_tree.inventory
1351
iterator = tree.iter_changes(old_tree, include_unchanged=True)
1352
for f, paths, c, v, p, n, k, e in iterator:
1353
if paths[0] == paths[1]:
1357
renames.append(paths)
1359
for old_name, new_name in renames:
1360
self.outf.write("%s => %s\n" % (old_name, new_name))
1181
1363
class cmd_update(Command):
1182
1364
"""Update a tree to have the latest code committed to its branch.
1184
1366
This will perform a merge into the working tree, and may generate
1185
conflicts. If you have any local changes, you will still
1367
conflicts. If you have any local changes, you will still
1186
1368
need to commit them after the update for the update to be complete.
1188
If you want to discard your local changes, you can just do a
1370
If you want to discard your local changes, you can just do a
1189
1371
'bzr revert' instead of 'bzr commit' after the update.
1373
If the tree's branch is bound to a master branch, it will also update
1374
the branch from the master.
1192
1377
_see_also = ['pull', 'working-trees', 'status-flags']
1193
1378
takes_args = ['dir?']
1379
takes_options = ['revision']
1194
1380
aliases = ['up']
1196
def run(self, dir='.'):
1382
def run(self, dir='.', revision=None):
1383
if revision is not None and len(revision) != 1:
1384
raise errors.BzrCommandError(
1385
"bzr update --revision takes exactly one revision")
1197
1386
tree = WorkingTree.open_containing(dir)[0]
1387
branch = tree.branch
1198
1388
possible_transports = []
1199
master = tree.branch.get_master_branch(
1389
master = branch.get_master_branch(
1200
1390
possible_transports=possible_transports)
1201
1391
if master is not None:
1202
1392
tree.lock_write()
1393
branch_location = master.base
1204
1395
tree.lock_tree_write()
1396
branch_location = tree.branch.base
1397
self.add_cleanup(tree.unlock)
1398
# get rid of the final '/' and be ready for display
1399
branch_location = urlutils.unescape_for_display(branch_location[:-1],
1401
existing_pending_merges = tree.get_parent_ids()[1:]
1405
# may need to fetch data into a heavyweight checkout
1406
# XXX: this may take some time, maybe we should display a
1408
old_tip = branch.update(possible_transports)
1409
if revision is not None:
1410
revision_id = revision[0].as_revision_id(branch)
1412
revision_id = branch.last_revision()
1413
if revision_id == _mod_revision.ensure_null(tree.last_revision()):
1414
revno = branch.revision_id_to_revno(revision_id)
1415
note("Tree is up to date at revision %d of branch %s" %
1416
(revno, branch_location))
1418
view_info = _get_view_info_for_change_reporter(tree)
1419
change_reporter = delta._ChangeReporter(
1420
unversioned_filter=tree.is_ignored,
1421
view_info=view_info)
1206
existing_pending_merges = tree.get_parent_ids()[1:]
1207
last_rev = _mod_revision.ensure_null(tree.last_revision())
1208
if last_rev == _mod_revision.ensure_null(
1209
tree.branch.last_revision()):
1210
# may be up to date, check master too.
1211
if master is None or last_rev == _mod_revision.ensure_null(
1212
master.last_revision()):
1213
revno = tree.branch.revision_id_to_revno(last_rev)
1214
note("Tree is up to date at revision %d." % (revno,))
1216
1423
conflicts = tree.update(
1217
delta._ChangeReporter(unversioned_filter=tree.is_ignored),
1218
possible_transports=possible_transports)
1219
revno = tree.branch.revision_id_to_revno(
1220
_mod_revision.ensure_null(tree.last_revision()))
1221
note('Updated to revision %d.' % (revno,))
1222
if tree.get_parent_ids()[1:] != existing_pending_merges:
1223
note('Your local commits will now show as pending merges with '
1224
"'bzr status', and can be committed with 'bzr commit'.")
1425
possible_transports=possible_transports,
1426
revision=revision_id,
1428
except errors.NoSuchRevision, e:
1429
raise errors.BzrCommandError(
1430
"branch has no revision %s\n"
1431
"bzr update --revision only works"
1432
" for a revision in the branch history"
1434
revno = tree.branch.revision_id_to_revno(
1435
_mod_revision.ensure_null(tree.last_revision()))
1436
note('Updated to revision %d of branch %s' %
1437
(revno, branch_location))
1438
if tree.get_parent_ids()[1:] != existing_pending_merges:
1439
note('Your local commits will now show as pending merges with '
1440
"'bzr status', and can be committed with 'bzr commit'.")
1233
1447
class cmd_info(Command):
1234
1448
"""Show information about a working tree, branch or repository.
1236
1450
This command will show all known locations and formats associated to the
1237
tree, branch or repository. Statistical information is included with
1451
tree, branch or repository.
1453
In verbose mode, statistical information is included with each report.
1454
To see extended statistic information, use a verbosity level of 2 or
1455
higher by specifying the verbose option multiple times, e.g. -vv.
1240
1457
Branches and working trees will also report any missing revisions.
1461
Display information on the format and related locations:
1465
Display the above together with extended format information and
1466
basic statistics (like the number of files in the working tree and
1467
number of revisions in the branch and repository):
1471
Display the above together with number of committers to the branch:
1242
1475
_see_also = ['revno', 'working-trees', 'repositories']
1243
1476
takes_args = ['location?']
1285
1518
file_list = [f for f in file_list]
1287
1520
tree.lock_write()
1289
# Heuristics should probably all move into tree.remove_smart or
1292
added = tree.changes_from(tree.basis_tree(),
1293
specific_files=file_list).added
1294
file_list = sorted([f[0] for f in added], reverse=True)
1295
if len(file_list) == 0:
1296
raise errors.BzrCommandError('No matching files.')
1297
elif file_list is None:
1298
# missing files show up in iter_changes(basis) as
1299
# versioned-with-no-kind.
1301
for change in tree.iter_changes(tree.basis_tree()):
1302
# Find paths in the working tree that have no kind:
1303
if change[1][1] is not None and change[6][1] is None:
1304
missing.append(change[1][1])
1305
file_list = sorted(missing, reverse=True)
1306
file_deletion_strategy = 'keep'
1307
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1308
keep_files=file_deletion_strategy=='keep',
1309
force=file_deletion_strategy=='force')
1521
self.add_cleanup(tree.unlock)
1522
# Heuristics should probably all move into tree.remove_smart or
1525
added = tree.changes_from(tree.basis_tree(),
1526
specific_files=file_list).added
1527
file_list = sorted([f[0] for f in added], reverse=True)
1528
if len(file_list) == 0:
1529
raise errors.BzrCommandError('No matching files.')
1530
elif file_list is None:
1531
# missing files show up in iter_changes(basis) as
1532
# versioned-with-no-kind.
1534
for change in tree.iter_changes(tree.basis_tree()):
1535
# Find paths in the working tree that have no kind:
1536
if change[1][1] is not None and change[6][1] is None:
1537
missing.append(change[1][1])
1538
file_list = sorted(missing, reverse=True)
1539
file_deletion_strategy = 'keep'
1540
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1541
keep_files=file_deletion_strategy=='keep',
1542
force=file_deletion_strategy=='force')
1314
1545
class cmd_file_id(Command):
1831
2076
class cmd_log(Command):
1832
"""Show log of a branch, file, or directory.
1834
By default show the log of the branch containing the working directory.
1836
To request a range of logs, you can use the command -r begin..end
1837
-r revision requests a specific revision, -r ..end or -r begin.. are
1841
Log the current branch::
1849
Log the last 10 revisions of a branch::
1851
bzr log -r -10.. http://server/branch
2077
"""Show historical log for a branch or subset of a branch.
2079
log is bzr's default tool for exploring the history of a branch.
2080
The branch to use is taken from the first parameter. If no parameters
2081
are given, the branch containing the working directory is logged.
2082
Here are some simple examples::
2084
bzr log log the current branch
2085
bzr log foo.py log a file in its branch
2086
bzr log http://server/branch log a branch on a server
2088
The filtering, ordering and information shown for each revision can
2089
be controlled as explained below. By default, all revisions are
2090
shown sorted (topologically) so that newer revisions appear before
2091
older ones and descendants always appear before ancestors. If displayed,
2092
merged revisions are shown indented under the revision in which they
2097
The log format controls how information about each revision is
2098
displayed. The standard log formats are called ``long``, ``short``
2099
and ``line``. The default is long. See ``bzr help log-formats``
2100
for more details on log formats.
2102
The following options can be used to control what information is
2105
-l N display a maximum of N revisions
2106
-n N display N levels of revisions (0 for all, 1 for collapsed)
2107
-v display a status summary (delta) for each revision
2108
-p display a diff (patch) for each revision
2109
--show-ids display revision-ids (and file-ids), not just revnos
2111
Note that the default number of levels to display is a function of the
2112
log format. If the -n option is not used, the standard log formats show
2113
just the top level (mainline).
2115
Status summaries are shown using status flags like A, M, etc. To see
2116
the changes explained using words like ``added`` and ``modified``
2117
instead, use the -vv option.
2121
To display revisions from oldest to newest, use the --forward option.
2122
In most cases, using this option will have little impact on the total
2123
time taken to produce a log, though --forward does not incrementally
2124
display revisions like --reverse does when it can.
2126
:Revision filtering:
2128
The -r option can be used to specify what revision or range of revisions
2129
to filter against. The various forms are shown below::
2131
-rX display revision X
2132
-rX.. display revision X and later
2133
-r..Y display up to and including revision Y
2134
-rX..Y display from X to Y inclusive
2136
See ``bzr help revisionspec`` for details on how to specify X and Y.
2137
Some common examples are given below::
2139
-r-1 show just the tip
2140
-r-10.. show the last 10 mainline revisions
2141
-rsubmit:.. show what's new on this branch
2142
-rancestor:path.. show changes since the common ancestor of this
2143
branch and the one at location path
2144
-rdate:yesterday.. show changes since yesterday
2146
When logging a range of revisions using -rX..Y, log starts at
2147
revision Y and searches back in history through the primary
2148
("left-hand") parents until it finds X. When logging just the
2149
top level (using -n1), an error is reported if X is not found
2150
along the way. If multi-level logging is used (-n0), X may be
2151
a nested merge revision and the log will be truncated accordingly.
2155
If parameters are given and the first one is not a branch, the log
2156
will be filtered to show only those revisions that changed the
2157
nominated files or directories.
2159
Filenames are interpreted within their historical context. To log a
2160
deleted file, specify a revision range so that the file existed at
2161
the end or start of the range.
2163
Historical context is also important when interpreting pathnames of
2164
renamed files/directories. Consider the following example:
2166
* revision 1: add tutorial.txt
2167
* revision 2: modify tutorial.txt
2168
* revision 3: rename tutorial.txt to guide.txt; add tutorial.txt
2172
* ``bzr log guide.txt`` will log the file added in revision 1
2174
* ``bzr log tutorial.txt`` will log the new file added in revision 3
2176
* ``bzr log -r2 -p tutorial.txt`` will show the changes made to
2177
the original file in revision 2.
2179
* ``bzr log -r2 -p guide.txt`` will display an error message as there
2180
was no file called guide.txt in revision 2.
2182
Renames are always followed by log. By design, there is no need to
2183
explicitly ask for this (and no way to stop logging a file back
2184
until it was last renamed).
2188
The --message option can be used for finding revisions that match a
2189
regular expression in a commit message.
2193
GUI tools and IDEs are often better at exploring history than command
2194
line tools: you may prefer qlog or viz from qbzr or bzr-gtk, the
2195
bzr-explorer shell, or the Loggerhead web interface. See the Plugin
2196
Guide <http://doc.bazaar.canonical.com/plugins/en/> and
2197
<http://wiki.bazaar.canonical.com/IDEIntegration>.
2199
You may find it useful to add the aliases below to ``bazaar.conf``::
2203
top = log -l10 --line
2206
``bzr tip`` will then show the latest revision while ``bzr top``
2207
will show the last 10 mainline revisions. To see the details of a
2208
particular revision X, ``bzr show -rX``.
2210
If you are interested in looking deeper into a particular merge X,
2211
use ``bzr log -n0 -rX``.
2213
``bzr log -v`` on a branch with lots of history is currently
2214
very slow. A fix for this issue is currently under development.
2215
With or without that fix, it is recommended that a revision range
2216
be given when using the -v option.
2218
bzr has a generic full-text matching plugin, bzr-search, that can be
2219
used to find revisions matching user names, commit messages, etc.
2220
Among other features, this plugin can find all revisions containing
2221
a list of words but not others.
2223
When exploring non-mainline history on large projects with deep
2224
history, the performance of log can be greatly improved by installing
2225
the historycache plugin. This plugin buffers historical information
2226
trading disk space for faster speed.
1854
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
1856
takes_args = ['location?']
2228
takes_args = ['file*']
2229
_see_also = ['log-formats', 'revisionspec']
1857
2230
takes_options = [
1858
2231
Option('forward',
1859
2232
help='Show from oldest to newest.'),
1937
2330
dir, relpath = bzrdir.BzrDir.open_containing(location)
1938
2331
b = dir.open_branch()
2333
self.add_cleanup(b.unlock)
1942
2334
rev1, rev2 = _get_revision_range(revision, b, self.name())
1943
if log_format is None:
1944
log_format = log.log_formatter_registry.get_default(b)
1946
lf = log_format(show_ids=show_ids, to_file=self.outf,
1947
show_timezone=timezone,
1948
delta_format=get_verbosity_level(),
1955
direction=direction,
1956
start_revision=rev1,
1960
show_diff=show_diff)
2336
# Decide on the type of delta & diff filtering to use
2337
# TODO: add an --all-files option to make this configurable & consistent
2345
diff_type = 'partial'
2349
# Build the log formatter
2350
if log_format is None:
2351
log_format = log.log_formatter_registry.get_default(b)
2352
# Make a non-encoding output to include the diffs - bug 328007
2353
unencoded_output = ui.ui_factory.make_output_stream(encoding_type='exact')
2354
lf = log_format(show_ids=show_ids, to_file=self.outf,
2355
to_exact_file=unencoded_output,
2356
show_timezone=timezone,
2357
delta_format=get_verbosity_level(),
2359
show_advice=levels is None)
2361
# Choose the algorithm for doing the logging. It's annoying
2362
# having multiple code paths like this but necessary until
2363
# the underlying repository format is faster at generating
2364
# deltas or can provide everything we need from the indices.
2365
# The default algorithm - match-using-deltas - works for
2366
# multiple files and directories and is faster for small
2367
# amounts of history (200 revisions say). However, it's too
2368
# slow for logging a single file in a repository with deep
2369
# history, i.e. > 10K revisions. In the spirit of "do no
2370
# evil when adding features", we continue to use the
2371
# original algorithm - per-file-graph - for the "single
2372
# file that isn't a directory without showing a delta" case.
2373
partial_history = revision and b.repository._format.supports_chks
2374
match_using_deltas = (len(file_ids) != 1 or filter_by_dir
2375
or delta_type or partial_history)
2377
# Build the LogRequest and execute it
2378
if len(file_ids) == 0:
2380
rqst = make_log_request_dict(
2381
direction=direction, specific_fileids=file_ids,
2382
start_revision=rev1, end_revision=rev2, limit=limit,
2383
message_search=message, delta_type=delta_type,
2384
diff_type=diff_type, _match_using_deltas=match_using_deltas)
2385
Logger(b, rqst).show(lf)
1965
2388
def _get_revision_range(revisionspec_list, branch, command_name):
1966
2389
"""Take the input of a revision option and turn it into a revision range.
1968
2391
It returns RevisionInfo objects which can be used to obtain the rev_id's
1969
of the desired revisons. It does some user input validations.
2392
of the desired revisions. It does some user input validations.
1971
2394
if revisionspec_list is None:
2079
2504
if path is None:
2084
2508
raise errors.BzrCommandError('cannot specify both --from-root'
2088
2511
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
2514
# Calculate the prefix to use
2518
prefix = relpath + '/'
2519
elif fs_path != '.' and not fs_path.endswith('/'):
2520
prefix = fs_path + '/'
2094
2522
if revision is not None or tree is None:
2095
2523
tree = _get_one_revision_tree('ls', revision, branch=branch)
2526
if isinstance(tree, WorkingTree) and tree.supports_views():
2527
view_files = tree.views.lookup_view()
2530
view_str = views.view_display_str(view_files)
2531
note("Ignoring files outside view. View is %s" % view_str)
2097
2533
tree.lock_read()
2099
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
2100
if fp.startswith(relpath):
2101
fp = osutils.pathjoin(prefix, fp[len(relpath):])
2102
if non_recursive and '/' in fp:
2104
if not all and not selection[fc]:
2106
if kind is not None and fkind != kind:
2108
kindch = entry.kind_character()
2109
outstring = fp + kindch
2111
outstring = '%-8s %s' % (fc, outstring)
2112
if show_ids and fid is not None:
2113
outstring = "%-50s %s" % (outstring, fid)
2114
self.outf.write(outstring + '\n')
2116
self.outf.write(fp + '\0')
2119
self.outf.write(fid)
2120
self.outf.write('\0')
2128
self.outf.write('%-50s %s\n' % (outstring, my_id))
2130
self.outf.write(outstring + '\n')
2534
self.add_cleanup(tree.unlock)
2535
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
2536
from_dir=relpath, recursive=recursive):
2537
# Apply additional masking
2538
if not all and not selection[fc]:
2540
if kind is not None and fkind != kind:
2545
fullpath = osutils.pathjoin(relpath, fp)
2548
views.check_path_in_view(tree, fullpath)
2549
except errors.FileOutsideView:
2554
fp = osutils.pathjoin(prefix, fp)
2555
kindch = entry.kind_character()
2556
outstring = fp + kindch
2557
ui.ui_factory.clear_term()
2559
outstring = '%-8s %s' % (fc, outstring)
2560
if show_ids and fid is not None:
2561
outstring = "%-50s %s" % (outstring, fid)
2562
self.outf.write(outstring + '\n')
2564
self.outf.write(fp + '\0')
2567
self.outf.write(fid)
2568
self.outf.write('\0')
2576
self.outf.write('%-50s %s\n' % (outstring, my_id))
2578
self.outf.write(outstring + '\n')
2135
2581
class cmd_unknowns(Command):
2332
2804
If no revision is nominated, the last revision is used.
2334
2806
Note: Take care to redirect standard output when using this command on a
2338
2810
_see_also = ['ls']
2339
2811
takes_options = [
2340
2812
Option('name-from-revision', help='The path name in the old tree.'),
2813
Option('filters', help='Apply content filters to display the '
2814
'convenience form.'),
2343
2817
takes_args = ['filename']
2344
2818
encoding_type = 'exact'
2346
2820
@display_command
2347
def run(self, filename, revision=None, name_from_revision=False):
2821
def run(self, filename, revision=None, name_from_revision=False,
2348
2823
if revision is not None and len(revision) != 1:
2349
2824
raise errors.BzrCommandError("bzr cat --revision takes exactly"
2350
2825
" one revision specifier")
2351
2826
tree, branch, relpath = \
2352
2827
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2353
2828
branch.lock_read()
2355
return self._run(tree, branch, relpath, filename, revision,
2829
self.add_cleanup(branch.unlock)
2830
return self._run(tree, branch, relpath, filename, revision,
2831
name_from_revision, filters)
2360
def _run(self, tree, b, relpath, filename, revision, name_from_revision):
2833
def _run(self, tree, b, relpath, filename, revision, name_from_revision,
2361
2835
if tree is None:
2362
2836
tree = b.basis_tree()
2363
2837
rev_tree = _get_one_revision_tree('cat', revision, branch=b)
2838
rev_tree.lock_read()
2839
self.add_cleanup(rev_tree.unlock)
2365
cur_file_id = tree.path2id(relpath)
2366
2841
old_file_id = rev_tree.path2id(relpath)
2368
2843
if name_from_revision:
2844
# Try in revision if requested
2369
2845
if old_file_id is None:
2370
2846
raise errors.BzrCommandError(
2371
2847
"%r is not present in revision %s" % (
2372
2848
filename, rev_tree.get_revision_id()))
2374
2850
content = rev_tree.get_file_text(old_file_id)
2375
elif cur_file_id is not None:
2376
content = rev_tree.get_file_text(cur_file_id)
2377
elif old_file_id is not None:
2378
content = rev_tree.get_file_text(old_file_id)
2380
raise errors.BzrCommandError(
2381
"%r is not present in revision %s" % (
2382
filename, rev_tree.get_revision_id()))
2383
self.outf.write(content)
2852
cur_file_id = tree.path2id(relpath)
2854
if cur_file_id is not None:
2855
# Then try with the actual file id
2857
content = rev_tree.get_file_text(cur_file_id)
2859
except errors.NoSuchId:
2860
# The actual file id didn't exist at that time
2862
if not found and old_file_id is not None:
2863
# Finally try with the old file id
2864
content = rev_tree.get_file_text(old_file_id)
2867
# Can't be found anywhere
2868
raise errors.BzrCommandError(
2869
"%r is not present in revision %s" % (
2870
filename, rev_tree.get_revision_id()))
2872
from bzrlib.filters import (
2873
ContentFilterContext,
2874
filtered_output_bytes,
2876
filters = rev_tree._content_filter_stack(relpath)
2877
chunks = content.splitlines(True)
2878
content = filtered_output_bytes(chunks, filters,
2879
ContentFilterContext(relpath, rev_tree))
2881
self.outf.writelines(content)
2884
self.outf.write(content)
2386
2887
class cmd_local_time_offset(Command):
2387
2888
"""Show the offset in seconds from GMT to local time."""
2389
2890
@display_command
2391
2892
print osutils.local_time_offset()
2395
2896
class cmd_commit(Command):
2396
2897
"""Commit changes into a new revision.
2398
If no arguments are given, the entire tree is committed.
2400
If selected files are specified, only changes to those files are
2401
committed. If a directory is specified then the directory and everything
2402
within it is committed.
2404
When excludes are given, they take precedence over selected files.
2405
For example, too commit only changes within foo, but not changes within
2408
bzr commit foo -x foo/bar
2410
If author of the change is not the same person as the committer, you can
2411
specify the author's name using the --author option. The name should be
2412
in the same format as a committer-id, e.g. "John Doe <jdoe@example.com>".
2414
A selected-file commit may fail in some cases where the committed
2415
tree would be invalid. Consider::
2420
bzr commit foo -m "committing foo"
2421
bzr mv foo/bar foo/baz
2424
bzr commit foo/bar -m "committing bar but not baz"
2426
In the example above, the last commit will fail by design. This gives
2427
the user the opportunity to decide whether they want to commit the
2428
rename at the same time, separately first, or not at all. (As a general
2429
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2431
Note: A selected-file commit after a merge is not yet supported.
2899
An explanatory message needs to be given for each commit. This is
2900
often done by using the --message option (getting the message from the
2901
command line) or by using the --file option (getting the message from
2902
a file). If neither of these options is given, an editor is opened for
2903
the user to enter the message. To see the changed files in the
2904
boilerplate text loaded into the editor, use the --show-diff option.
2906
By default, the entire tree is committed and the person doing the
2907
commit is assumed to be the author. These defaults can be overridden
2912
If selected files are specified, only changes to those files are
2913
committed. If a directory is specified then the directory and
2914
everything within it is committed.
2916
When excludes are given, they take precedence over selected files.
2917
For example, to commit only changes within foo, but not changes
2920
bzr commit foo -x foo/bar
2922
A selective commit after a merge is not yet supported.
2926
If the author of the change is not the same person as the committer,
2927
you can specify the author's name using the --author option. The
2928
name should be in the same format as a committer-id, e.g.
2929
"John Doe <jdoe@example.com>". If there is more than one author of
2930
the change you can specify the option multiple times, once for each
2935
A common mistake is to forget to add a new file or directory before
2936
running the commit command. The --strict option checks for unknown
2937
files and aborts the commit if any are found. More advanced pre-commit
2938
checks can be implemented by defining hooks. See ``bzr help hooks``
2943
If you accidentially commit the wrong changes or make a spelling
2944
mistake in the commit message say, you can use the uncommit command
2945
to undo it. See ``bzr help uncommit`` for details.
2947
Hooks can also be configured to run after a commit. This allows you
2948
to trigger updates to external systems like bug trackers. The --fixes
2949
option can be used to record the association between a revision and
2950
one or more bugs. See ``bzr help bugs`` for details.
2952
A selective commit may fail in some cases where the committed
2953
tree would be invalid. Consider::
2958
bzr commit foo -m "committing foo"
2959
bzr mv foo/bar foo/baz
2962
bzr commit foo/bar -m "committing bar but not baz"
2964
In the example above, the last commit will fail by design. This gives
2965
the user the opportunity to decide whether they want to commit the
2966
rename at the same time, separately first, or not at all. (As a general
2967
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2433
2969
# TODO: Run hooks on tree to-be-committed, and after commit.
2468
3008
"the master branch until a normal commit "
2469
3009
"is performed."
2472
help='When no message is supplied, show the diff along'
2473
' with the status summary in the message editor.'),
3012
help='When no message is supplied, show the diff along'
3013
' with the status summary in the message editor.'),
2475
3015
aliases = ['ci', 'checkin']
2477
def _get_bug_fix_properties(self, fixes, branch):
3017
def _iter_bug_fix_urls(self, fixes, branch):
2479
3018
# Configure the properties for bug fixing attributes.
2480
3019
for fixed_bug in fixes:
2481
3020
tokens = fixed_bug.split(':')
2482
3021
if len(tokens) != 2:
2483
3022
raise errors.BzrCommandError(
2484
"Invalid bug %s. Must be in the form of 'tag:id'. "
2485
"Commit refused." % fixed_bug)
3023
"Invalid bug %s. Must be in the form of 'tracker:id'. "
3024
"See \"bzr help bugs\" for more information on this "
3025
"feature.\nCommit refused." % fixed_bug)
2486
3026
tag, bug_id = tokens
2488
bug_url = bugtracker.get_bug_url(tag, branch, bug_id)
3028
yield bugtracker.get_bug_url(tag, branch, bug_id)
2489
3029
except errors.UnknownBugTrackerAbbreviation:
2490
3030
raise errors.BzrCommandError(
2491
3031
'Unrecognized bug %s. Commit refused.' % fixed_bug)
2492
except errors.MalformedBugIdentifier:
3032
except errors.MalformedBugIdentifier, e:
2493
3033
raise errors.BzrCommandError(
2494
"Invalid bug identifier for %s. Commit refused."
2496
properties.append('%s fixed' % bug_url)
2497
return '\n'.join(properties)
3034
"%s\nCommit refused." % (str(e),))
2499
3036
def run(self, message=None, file=None, verbose=False, selected_list=None,
2500
3037
unchanged=False, strict=False, local=False, fixes=None,
2501
author=None, show_diff=False, exclude=None):
3038
author=None, show_diff=False, exclude=None, commit_time=None):
2502
3039
from bzrlib.errors import (
2503
3040
PointlessCommit,
2504
3041
ConflictsInTree,
2935
3528
if cache_dir is not None:
2936
3529
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
2938
print 'testing: %s' % (osutils.realpath(sys.argv[0]),)
2939
print ' %s (%s python%s)' % (
2941
bzrlib.version_string,
2942
bzrlib._format_version_tuple(sys.version_info),
2945
3530
if testspecs_list is not None:
2946
3531
pattern = '|'.join(testspecs_list)
3536
from bzrlib.tests import SubUnitBzrRunner
3538
raise errors.BzrCommandError("subunit not available. subunit "
3539
"needs to be installed to use --subunit.")
3540
self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3542
self.additional_selftest_args.setdefault(
3543
'suite_decorators', []).append(parallel)
2950
3545
test_suite_factory = benchmarks.test_suite
2951
3546
# Unless user explicitly asks for quiet, be verbose in benchmarks
2952
3547
verbose = not is_quiet()
2953
3548
# TODO: should possibly lock the history file...
2954
3549
benchfile = open(".perf_history", "at", buffering=1)
3550
self.add_cleanup(benchfile.close)
2956
3552
test_suite_factory = None
2957
3553
benchfile = None
2959
result = selftest(verbose=verbose,
2961
stop_on_failure=one,
2962
transport=transport,
2963
test_suite_factory=test_suite_factory,
2964
lsprof_timed=lsprof_timed,
2965
bench_history=benchfile,
2966
matching_tests_first=first,
2967
list_only=list_only,
2968
random_seed=randomize,
2969
exclude_pattern=exclude,
2971
load_list=load_list,
2972
debug_flags=debugflag,
2973
starting_with=starting_with,
2976
if benchfile is not None:
2979
note('tests passed')
2981
note('tests failed')
3554
selftest_kwargs = {"verbose": verbose,
3556
"stop_on_failure": one,
3557
"transport": transport,
3558
"test_suite_factory": test_suite_factory,
3559
"lsprof_timed": lsprof_timed,
3560
"lsprof_tests": lsprof_tests,
3561
"bench_history": benchfile,
3562
"matching_tests_first": first,
3563
"list_only": list_only,
3564
"random_seed": randomize,
3565
"exclude_pattern": exclude,
3567
"load_list": load_list,
3568
"debug_flags": debugflag,
3569
"starting_with": starting_with
3571
selftest_kwargs.update(self.additional_selftest_args)
3572
result = selftest(**selftest_kwargs)
2982
3573
return int(not result)
3138
3744
allow_pending = True
3139
3745
verified = 'inapplicable'
3140
3746
tree = WorkingTree.open_containing(directory)[0]
3749
basis_tree = tree.revision_tree(tree.last_revision())
3750
except errors.NoSuchRevision:
3751
basis_tree = tree.basis_tree()
3753
# die as quickly as possible if there are uncommitted changes
3755
if tree.has_changes():
3756
raise errors.UncommittedChanges(tree)
3758
view_info = _get_view_info_for_change_reporter(tree)
3141
3759
change_reporter = delta._ChangeReporter(
3142
unversioned_filter=tree.is_ignored)
3145
pb = ui.ui_factory.nested_progress_bar()
3146
cleanups.append(pb.finished)
3148
cleanups.append(tree.unlock)
3149
if location is not None:
3151
mergeable = bundle.read_mergeable_from_url(location,
3152
possible_transports=possible_transports)
3153
except errors.NotABundle:
3157
raise errors.BzrCommandError('Cannot use --uncommitted'
3158
' with bundles or merge directives.')
3160
if revision is not None:
3161
raise errors.BzrCommandError(
3162
'Cannot use -r with merge directives or bundles')
3163
merger, verified = _mod_merge.Merger.from_mergeable(tree,
3166
if merger is None and uncommitted:
3167
if revision is not None and len(revision) > 0:
3168
raise errors.BzrCommandError('Cannot use --uncommitted and'
3169
' --revision at the same time.')
3170
location = self._select_branch_location(tree, location)[0]
3171
other_tree, other_path = WorkingTree.open_containing(location)
3172
merger = _mod_merge.Merger.from_uncommitted(tree, other_tree,
3174
allow_pending = False
3175
if other_path != '':
3176
merger.interesting_files = [other_path]
3179
merger, allow_pending = self._get_merger_from_branch(tree,
3180
location, revision, remember, possible_transports, pb)
3182
merger.merge_type = merge_type
3183
merger.reprocess = reprocess
3184
merger.show_base = show_base
3185
self.sanity_check_merger(merger)
3186
if (merger.base_rev_id == merger.other_rev_id and
3187
merger.other_rev_id is not None):
3188
note('Nothing to do.')
3760
unversioned_filter=tree.is_ignored, view_info=view_info)
3761
pb = ui.ui_factory.nested_progress_bar()
3762
self.add_cleanup(pb.finished)
3764
self.add_cleanup(tree.unlock)
3765
if location is not None:
3767
mergeable = bundle.read_mergeable_from_url(location,
3768
possible_transports=possible_transports)
3769
except errors.NotABundle:
3773
raise errors.BzrCommandError('Cannot use --uncommitted'
3774
' with bundles or merge directives.')
3776
if revision is not None:
3777
raise errors.BzrCommandError(
3778
'Cannot use -r with merge directives or bundles')
3779
merger, verified = _mod_merge.Merger.from_mergeable(tree,
3782
if merger is None and uncommitted:
3783
if revision is not None and len(revision) > 0:
3784
raise errors.BzrCommandError('Cannot use --uncommitted and'
3785
' --revision at the same time.')
3786
merger = self.get_merger_from_uncommitted(tree, location, None)
3787
allow_pending = False
3790
merger, allow_pending = self._get_merger_from_branch(tree,
3791
location, revision, remember, possible_transports, None)
3793
merger.merge_type = merge_type
3794
merger.reprocess = reprocess
3795
merger.show_base = show_base
3796
self.sanity_check_merger(merger)
3797
if (merger.base_rev_id == merger.other_rev_id and
3798
merger.other_rev_id is not None):
3799
note('Nothing to do.')
3802
if merger.interesting_files is not None:
3803
raise errors.BzrCommandError('Cannot pull individual files')
3804
if (merger.base_rev_id == tree.last_revision()):
3805
result = tree.pull(merger.other_branch, False,
3806
merger.other_rev_id)
3807
result.report(self.outf)
3191
if merger.interesting_files is not None:
3192
raise errors.BzrCommandError('Cannot pull individual files')
3193
if (merger.base_rev_id == tree.last_revision()):
3194
result = tree.pull(merger.other_branch, False,
3195
merger.other_rev_id)
3196
result.report(self.outf)
3198
merger.check_basis(not force)
3200
return self._do_preview(merger)
3202
return self._do_merge(merger, change_reporter, allow_pending,
3205
for cleanup in reversed(cleanups):
3809
if merger.this_basis is None:
3810
raise errors.BzrCommandError(
3811
"This branch has no commits."
3812
" (perhaps you would prefer 'bzr pull')")
3814
return self._do_preview(merger)
3816
return self._do_interactive(merger)
3818
return self._do_merge(merger, change_reporter, allow_pending,
3821
def _get_preview(self, merger):
3822
tree_merger = merger.make_merger()
3823
tt = tree_merger.make_preview_transform()
3824
self.add_cleanup(tt.finalize)
3825
result_tree = tt.get_preview_tree()
3208
3828
def _do_preview(self, merger):
3209
3829
from bzrlib.diff import show_diff_trees
3210
tree_merger = merger.make_merger()
3211
tt = tree_merger.make_preview_transform()
3213
result_tree = tt.get_preview_tree()
3214
show_diff_trees(merger.this_tree, result_tree, self.outf,
3215
old_label='', new_label='')
3830
result_tree = self._get_preview(merger)
3831
show_diff_trees(merger.this_tree, result_tree, self.outf,
3832
old_label='', new_label='')
3219
3834
def _do_merge(self, merger, change_reporter, allow_pending, verified):
3220
3835
merger.change_reporter = change_reporter
3376
4023
merge_type = _mod_merge.Merge3Merger
3377
4024
tree, file_list = tree_files(file_list)
3378
4025
tree.lock_write()
4026
self.add_cleanup(tree.unlock)
4027
parents = tree.get_parent_ids()
4028
if len(parents) != 2:
4029
raise errors.BzrCommandError("Sorry, remerge only works after normal"
4030
" merges. Not cherrypicking or"
4032
repository = tree.branch.repository
4033
interesting_ids = None
4035
conflicts = tree.conflicts()
4036
if file_list is not None:
4037
interesting_ids = set()
4038
for filename in file_list:
4039
file_id = tree.path2id(filename)
4041
raise errors.NotVersionedError(filename)
4042
interesting_ids.add(file_id)
4043
if tree.kind(file_id) != "directory":
4046
for name, ie in tree.inventory.iter_entries(file_id):
4047
interesting_ids.add(ie.file_id)
4048
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
4050
# Remerge only supports resolving contents conflicts
4051
allowed_conflicts = ('text conflict', 'contents conflict')
4052
restore_files = [c.path for c in conflicts
4053
if c.typestring in allowed_conflicts]
4054
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
4055
tree.set_conflicts(ConflictList(new_conflicts))
4056
if file_list is not None:
4057
restore_files = file_list
4058
for filename in restore_files:
4060
restore(tree.abspath(filename))
4061
except errors.NotConflicted:
4063
# Disable pending merges, because the file texts we are remerging
4064
# have not had those merges performed. If we use the wrong parents
4065
# list, we imply that the working tree text has seen and rejected
4066
# all the changes from the other tree, when in fact those changes
4067
# have not yet been seen.
4068
tree.set_parent_ids(parents[:1])
3380
parents = tree.get_parent_ids()
3381
if len(parents) != 2:
3382
raise errors.BzrCommandError("Sorry, remerge only works after normal"
3383
" merges. Not cherrypicking or"
3385
repository = tree.branch.repository
3386
interesting_ids = None
3388
conflicts = tree.conflicts()
3389
if file_list is not None:
3390
interesting_ids = set()
3391
for filename in file_list:
3392
file_id = tree.path2id(filename)
3394
raise errors.NotVersionedError(filename)
3395
interesting_ids.add(file_id)
3396
if tree.kind(file_id) != "directory":
3399
for name, ie in tree.inventory.iter_entries(file_id):
3400
interesting_ids.add(ie.file_id)
3401
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
3403
# Remerge only supports resolving contents conflicts
3404
allowed_conflicts = ('text conflict', 'contents conflict')
3405
restore_files = [c.path for c in conflicts
3406
if c.typestring in allowed_conflicts]
3407
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
3408
tree.set_conflicts(ConflictList(new_conflicts))
3409
if file_list is not None:
3410
restore_files = file_list
3411
for filename in restore_files:
3413
restore(tree.abspath(filename))
3414
except errors.NotConflicted:
3416
# Disable pending merges, because the file texts we are remerging
3417
# have not had those merges performed. If we use the wrong parents
3418
# list, we imply that the working tree text has seen and rejected
3419
# all the changes from the other tree, when in fact those changes
3420
# have not yet been seen.
3421
pb = ui.ui_factory.nested_progress_bar()
3422
tree.set_parent_ids(parents[:1])
3424
merger = _mod_merge.Merger.from_revision_ids(pb,
3426
merger.interesting_ids = interesting_ids
3427
merger.merge_type = merge_type
3428
merger.show_base = show_base
3429
merger.reprocess = reprocess
3430
conflicts = merger.do_merge()
3432
tree.set_parent_ids(parents)
4070
merger = _mod_merge.Merger.from_revision_ids(None, tree, parents[1])
4071
merger.interesting_ids = interesting_ids
4072
merger.merge_type = merge_type
4073
merger.show_base = show_base
4074
merger.reprocess = reprocess
4075
conflicts = merger.do_merge()
4077
tree.set_parent_ids(parents)
3436
4078
if conflicts > 0:
3460
4102
name. If you name a directory, all the contents of that directory will be
3463
Any files that have been newly added since that revision will be deleted,
3464
with a backup kept if appropriate. Directories containing unknown files
3465
will not be deleted.
4105
If you have newly added files since the target revision, they will be
4106
removed. If the files to be removed have been changed, backups will be
4107
created as above. Directories containing unknown files will not be
3467
The working tree contains a list of pending merged revisions, which will
3468
be included as parents in the next commit. Normally, revert clears that
3469
list as well as reverting the files. If any files are specified, revert
3470
leaves the pending merge list alone and reverts only the files. Use "bzr
3471
revert ." in the tree root to revert all files but keep the merge record,
3472
and "bzr revert --forget-merges" to clear the pending merge list without
4110
The working tree contains a list of revisions that have been merged but
4111
not yet committed. These revisions will be included as additional parents
4112
of the next commit. Normally, using revert clears that list as well as
4113
reverting the files. If any files are specified, revert leaves the list
4114
of uncommitted merges alone and reverts only the files. Use ``bzr revert
4115
.`` in the tree root to revert all files but keep the recorded merges,
4116
and ``bzr revert --forget-merges`` to clear the pending merge list without
3473
4117
reverting any files.
4119
Using "bzr revert --forget-merges", it is possible to apply all of the
4120
changes from a branch in a single revision. To do this, perform the merge
4121
as desired. Then doing revert with the "--forget-merges" option will keep
4122
the content of the tree as it was, but it will clear the list of pending
4123
merges. The next commit will then contain all of the changes that are
4124
present in the other branch, but without any other parent revisions.
4125
Because this technique forgets where these changes originated, it may
4126
cause additional conflicts on later merges involving the same source and
3476
4130
_see_also = ['cat', 'export']
3644
4297
if remote_branch.base == local_branch.base:
3645
4298
remote_branch = local_branch
4300
local_branch.lock_read()
4301
self.add_cleanup(local_branch.unlock)
3647
4302
local_revid_range = _revision_range_to_revid_range(
3648
4303
_get_revision_range(my_revision, local_branch,
4306
remote_branch.lock_read()
4307
self.add_cleanup(remote_branch.unlock)
3651
4308
remote_revid_range = _revision_range_to_revid_range(
3652
4309
_get_revision_range(revision,
3653
4310
remote_branch, self.name()))
3655
local_branch.lock_read()
3657
remote_branch.lock_read()
3659
local_extra, remote_extra = find_unmerged(
3660
local_branch, remote_branch, restrict,
3661
backward=not reverse,
3662
include_merges=include_merges,
3663
local_revid_range=local_revid_range,
3664
remote_revid_range=remote_revid_range)
3666
if log_format is None:
3667
registry = log.log_formatter_registry
3668
log_format = registry.get_default(local_branch)
3669
lf = log_format(to_file=self.outf,
3671
show_timezone='original')
3674
if local_extra and not theirs_only:
3675
message("You have %d extra revision(s):\n" %
3677
for revision in iter_log_revisions(local_extra,
3678
local_branch.repository,
3680
lf.log_revision(revision)
3681
printed_local = True
3684
printed_local = False
3686
if remote_extra and not mine_only:
3687
if printed_local is True:
3689
message("You are missing %d revision(s):\n" %
3691
for revision in iter_log_revisions(remote_extra,
3692
remote_branch.repository,
3694
lf.log_revision(revision)
3697
if mine_only and not local_extra:
3698
# We checked local, and found nothing extra
3699
message('This branch is up to date.\n')
3700
elif theirs_only and not remote_extra:
3701
# We checked remote, and found nothing extra
3702
message('Other branch is up to date.\n')
3703
elif not (mine_only or theirs_only or local_extra or
3705
# We checked both branches, and neither one had extra
3707
message("Branches are up to date.\n")
3709
remote_branch.unlock()
3711
local_branch.unlock()
4312
local_extra, remote_extra = find_unmerged(
4313
local_branch, remote_branch, restrict,
4314
backward=not reverse,
4315
include_merges=include_merges,
4316
local_revid_range=local_revid_range,
4317
remote_revid_range=remote_revid_range)
4319
if log_format is None:
4320
registry = log.log_formatter_registry
4321
log_format = registry.get_default(local_branch)
4322
lf = log_format(to_file=self.outf,
4324
show_timezone='original')
4327
if local_extra and not theirs_only:
4328
message("You have %d extra revision(s):\n" %
4330
for revision in iter_log_revisions(local_extra,
4331
local_branch.repository,
4333
lf.log_revision(revision)
4334
printed_local = True
4337
printed_local = False
4339
if remote_extra and not mine_only:
4340
if printed_local is True:
4342
message("You are missing %d revision(s):\n" %
4344
for revision in iter_log_revisions(remote_extra,
4345
remote_branch.repository,
4347
lf.log_revision(revision)
4350
if mine_only and not local_extra:
4351
# We checked local, and found nothing extra
4352
message('This branch is up to date.\n')
4353
elif theirs_only and not remote_extra:
4354
# We checked remote, and found nothing extra
4355
message('Other branch is up to date.\n')
4356
elif not (mine_only or theirs_only or local_extra or
4358
# We checked both branches, and neither one had extra
4360
message("Branches are up to date.\n")
3712
4362
if not status_code and parent is None and other_branch is not None:
3713
4363
local_branch.lock_write()
3715
# handle race conditions - a parent might be set while we run.
3716
if local_branch.get_parent() is None:
3717
local_branch.set_parent(remote_branch.base)
3719
local_branch.unlock()
4364
self.add_cleanup(local_branch.unlock)
4365
# handle race conditions - a parent might be set while we run.
4366
if local_branch.get_parent() is None:
4367
local_branch.set_parent(remote_branch.base)
3720
4368
return status_code
3844
4490
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
3845
4491
if wt is not None:
4493
self.add_cleanup(wt.unlock)
3848
4495
branch.lock_read()
3850
tree = _get_one_revision_tree('annotate', revision, branch=branch)
3852
file_id = wt.path2id(relpath)
3854
file_id = tree.path2id(relpath)
3856
raise errors.NotVersionedError(filename)
3857
file_version = tree.inventory[file_id].revision
3858
if wt is not None and revision is None:
3859
# If there is a tree and we're not annotating historical
3860
# versions, annotate the working tree's content.
3861
annotate_file_tree(wt, file_id, self.outf, long, all,
3864
annotate_file(branch, file_version, file_id, long, all, self.outf,
4496
self.add_cleanup(branch.unlock)
4497
tree = _get_one_revision_tree('annotate', revision, branch=branch)
4499
self.add_cleanup(tree.unlock)
4501
file_id = wt.path2id(relpath)
4503
file_id = tree.path2id(relpath)
4505
raise errors.NotVersionedError(filename)
4506
file_version = tree.inventory[file_id].revision
4507
if wt is not None and revision is None:
4508
# If there is a tree and we're not annotating historical
4509
# versions, annotate the working tree's content.
4510
annotate_file_tree(wt, file_id, self.outf, long, all,
4513
annotate_file(branch, file_version, file_id, long, all, self.outf,
3873
4517
class cmd_re_sign(Command):
4197
4828
:return: A tuple of (host, port), where 'host' is a host name or IP,
4198
4829
and port is an integer TCP/IP port.
4200
from bzrlib.smart import medium
4201
host = medium.BZR_DEFAULT_INTERFACE
4203
port = medium.BZR_DEFAULT_PORT
4832
if port is not None:
4205
4833
if ':' in port:
4206
4834
host, port = port.split(':')
4207
4835
port = int(port)
4208
4836
return host, port
4210
def get_smart_server(self, transport, inet, port):
4211
"""Construct a smart server.
4213
:param transport: The base transport from which branches will be
4215
:param inet: If True, serve over stdin and stdout. Used for running
4217
:param port: The port to listen on. By default, it's `
4218
medium.BZR_DEFAULT_PORT`. See `get_host_and_port` for more
4220
:return: A smart server.
4222
from bzrlib.smart import medium, server
4224
smart_server = medium.SmartServerPipeStreamMedium(
4225
sys.stdin, sys.stdout, transport)
4227
host, port = self.get_host_and_port(port)
4228
smart_server = server.SmartTCPServer(
4229
transport, host=host, port=port)
4230
note('listening on port: %s' % smart_server.port)
4233
def run(self, port=None, inet=False, directory=None, allow_writes=False):
4234
from bzrlib.transport import get_transport
4235
from bzrlib.transport.chroot import ChrootServer
4838
def run(self, port=None, inet=False, directory=None, allow_writes=False,
4840
from bzrlib.transport import get_transport, transport_server_registry
4236
4841
if directory is None:
4237
4842
directory = os.getcwd()
4843
if protocol is None:
4844
protocol = transport_server_registry.get()
4845
host, port = self.get_host_and_port(port)
4238
4846
url = urlutils.local_path_to_url(directory)
4239
4847
if not allow_writes:
4240
4848
url = 'readonly+' + url
4241
chroot_server = ChrootServer(get_transport(url))
4242
chroot_server.setUp()
4243
t = get_transport(chroot_server.get_url())
4244
smart_server = self.get_smart_server(t, inet, port)
4245
self.run_smart_server(smart_server)
4849
transport = get_transport(url)
4850
protocol(transport, host, port, inet)
4248
4853
class cmd_join(Command):
4249
"""Combine a subtree into its containing tree.
4251
This command is for experimental use only. It requires the target tree
4252
to be in dirstate-with-subtree format, which cannot be converted into
4854
"""Combine a tree into its containing tree.
4856
This command requires the target tree to be in a rich-root format.
4255
4858
The TREE argument should be an independent tree, inside another tree, but
4256
4859
not part of it. (Such trees can be produced by "bzr split", but also by
4438
5034
directly from the merge directive, without retrieving data from a
4441
If --no-bundle is specified, then public_branch is needed (and must be
4442
up-to-date), so that the receiver can perform the merge using the
4443
public_branch. The public_branch is always included if known, so that
4444
people can check it later.
4446
The submit branch defaults to the parent, but can be overridden. Both
4447
submit branch and public branch will be remembered if supplied.
4449
If a public_branch is known for the submit_branch, that public submit
4450
branch is used in the merge instructions. This means that a local mirror
4451
can be used as your actual submit branch, once you have set public_branch
5037
`bzr send` creates a compact data set that, when applied using bzr
5038
merge, has the same effect as merging from the source branch.
5040
By default the merge directive is self-contained and can be applied to any
5041
branch containing submit_branch in its ancestory without needing access to
5044
If --no-bundle is specified, then Bazaar doesn't send the contents of the
5045
revisions, but only a structured request to merge from the
5046
public_location. In that case the public_branch is needed and it must be
5047
up-to-date and accessible to the recipient. The public_branch is always
5048
included if known, so that people can check it later.
5050
The submit branch defaults to the parent of the source branch, but can be
5051
overridden. Both submit branch and public branch will be remembered in
5052
branch.conf the first time they are used for a particular branch. The
5053
source branch defaults to that containing the working directory, but can
5054
be changed using --from.
5056
In order to calculate those changes, bzr must analyse the submit branch.
5057
Therefore it is most efficient for the submit branch to be a local mirror.
5058
If a public location is known for the submit_branch, that location is used
5059
in the merge directive.
5061
The default behaviour is to send the merge directive by mail, unless -o is
5062
given, in which case it is sent to a file.
4454
5064
Mail is sent using your preferred mail program. This should be transparent
4455
5065
on Windows (it uses MAPI). On Linux, it requires the xdg-email utility.
4456
5066
If the preferred client can't be found (or used), your editor will be used.
4458
5068
To use a specific mail program, set the mail_client configuration option.
4459
5069
(For Thunderbird 1.5, this works around some bugs.) Supported values for
4460
specific clients are "claws", "evolution", "kmail", "mutt", and
4461
"thunderbird"; generic options are "default", "editor", "emacsclient",
4462
"mapi", and "xdg-email". Plugins may also add supported clients.
5070
specific clients are "claws", "evolution", "kmail", "mail.app" (MacOS X's
5071
Mail.app), "mutt", and "thunderbird"; generic options are "default",
5072
"editor", "emacsclient", "mapi", and "xdg-email". Plugins may also add
4464
5075
If mail is being sent, a to address is required. This can be supplied
4465
5076
either on the commandline, by setting the submit_to configuration
4466
option in the branch itself or the child_submit_to configuration option
5077
option in the branch itself or the child_submit_to configuration option
4467
5078
in the submit branch.
4469
5080
Two formats are currently supported: "4" uses revision bundle format 4 and
4497
5113
help='Write merge directive to this file; '
4498
5114
'use - for stdout.',
5117
help='Refuse to send if there are uncommitted changes in'
5118
' the working tree, --no-strict disables the check.'),
4500
5119
Option('mail-to', help='Mail the request to this address.',
4504
RegistryOption.from_kwargs('format',
4505
'Use the specified output format.',
4506
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4507
'0.9': 'Bundle format 0.9, Merge Directive 1',})
5123
Option('body', help='Body for the email.', type=unicode),
5124
RegistryOption('format',
5125
help='Use the specified output format.',
5126
lazy_registry=('bzrlib.send', 'format_registry')),
4510
5129
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4511
5130
no_patch=False, revision=None, remember=False, output=None,
4512
format='4', mail_to=None, message=None, **kwargs):
4513
return self._run(submit_branch, revision, public_branch, remember,
4514
format, no_bundle, no_patch, output,
4515
kwargs.get('from', '.'), mail_to, message)
4517
def _run(self, submit_branch, revision, public_branch, remember, format,
4518
no_bundle, no_patch, output, from_, mail_to, message):
4519
from bzrlib.revision import NULL_REVISION
4520
branch = Branch.open_containing(from_)[0]
4522
outfile = cStringIO.StringIO()
4526
outfile = open(output, 'wb')
4527
# we may need to write data into branch's repository to calculate
4532
config = branch.get_config()
4534
mail_to = config.get_user_option('submit_to')
4535
mail_client = config.get_mail_client()
4536
if remember and submit_branch is None:
4537
raise errors.BzrCommandError(
4538
'--remember requires a branch to be specified.')
4539
stored_submit_branch = branch.get_submit_branch()
4540
remembered_submit_branch = None
4541
if submit_branch is None:
4542
submit_branch = stored_submit_branch
4543
remembered_submit_branch = "submit"
4545
if stored_submit_branch is None or remember:
4546
branch.set_submit_branch(submit_branch)
4547
if submit_branch is None:
4548
submit_branch = branch.get_parent()
4549
remembered_submit_branch = "parent"
4550
if submit_branch is None:
4551
raise errors.BzrCommandError('No submit branch known or'
4553
if remembered_submit_branch is not None:
4554
note('Using saved %s location "%s" to determine what '
4555
'changes to submit.', remembered_submit_branch,
4559
submit_config = Branch.open(submit_branch).get_config()
4560
mail_to = submit_config.get_user_option("child_submit_to")
4562
stored_public_branch = branch.get_public_branch()
4563
if public_branch is None:
4564
public_branch = stored_public_branch
4565
elif stored_public_branch is None or remember:
4566
branch.set_public_branch(public_branch)
4567
if no_bundle and public_branch is None:
4568
raise errors.BzrCommandError('No public branch specified or'
4570
base_revision_id = None
4572
if revision is not None:
4573
if len(revision) > 2:
4574
raise errors.BzrCommandError('bzr send takes '
4575
'at most two one revision identifiers')
4576
revision_id = revision[-1].as_revision_id(branch)
4577
if len(revision) == 2:
4578
base_revision_id = revision[0].as_revision_id(branch)
4579
if revision_id is None:
4580
revision_id = branch.last_revision()
4581
if revision_id == NULL_REVISION:
4582
raise errors.BzrCommandError('No revisions to submit.')
4584
directive = merge_directive.MergeDirective2.from_objects(
4585
branch.repository, revision_id, time.time(),
4586
osutils.local_time_offset(), submit_branch,
4587
public_branch=public_branch, include_patch=not no_patch,
4588
include_bundle=not no_bundle, message=message,
4589
base_revision_id=base_revision_id)
4590
elif format == '0.9':
4593
patch_type = 'bundle'
4595
raise errors.BzrCommandError('Format 0.9 does not'
4596
' permit bundle with no patch')
4602
directive = merge_directive.MergeDirective.from_objects(
4603
branch.repository, revision_id, time.time(),
4604
osutils.local_time_offset(), submit_branch,
4605
public_branch=public_branch, patch_type=patch_type,
4608
outfile.writelines(directive.to_lines())
4610
subject = '[MERGE] '
4611
if message is not None:
4614
revision = branch.repository.get_revision(revision_id)
4615
subject += revision.get_summary()
4616
basename = directive.get_disk_name(branch)
4617
mail_client.compose_merge_request(mail_to, subject,
4618
outfile.getvalue(), basename)
5131
format=None, mail_to=None, message=None, body=None,
5132
strict=None, **kwargs):
5133
from bzrlib.send import send
5134
return send(submit_branch, revision, public_branch, remember,
5135
format, no_bundle, no_patch, output,
5136
kwargs.get('from', '.'), mail_to, message, body,
4625
5141
class cmd_bundle_revisions(cmd_send):
4627
5142
"""Create a merge-directive for submitting changes.
4629
5144
A merge directive provides many things needed for requesting merges:
4840
5363
_see_also = ['branches', 'checkouts', 'standalone-trees', 'working-trees']
4841
5364
takes_args = ['location?']
4842
takes_options = [RegistryOption.from_kwargs('target_type',
4843
title='Target type',
4844
help='The type to reconfigure the directory to.',
4845
value_switches=True, enum_switch=False,
4846
branch='Reconfigure to be an unbound branch '
4847
'with no working tree.',
4848
tree='Reconfigure to be an unbound branch '
4849
'with a working tree.',
4850
checkout='Reconfigure to be a bound branch '
4851
'with a working tree.',
4852
lightweight_checkout='Reconfigure to be a lightweight'
4853
' checkout (with no local history).',
4854
standalone='Reconfigure to be a standalone branch '
4855
'(i.e. stop using shared repository).',
4856
use_shared='Reconfigure to use a shared repository.'),
4857
Option('bind-to', help='Branch to bind checkout to.',
4860
help='Perform reconfiguration even if local changes'
5366
RegistryOption.from_kwargs(
5368
title='Target type',
5369
help='The type to reconfigure the directory to.',
5370
value_switches=True, enum_switch=False,
5371
branch='Reconfigure to be an unbound branch with no working tree.',
5372
tree='Reconfigure to be an unbound branch with a working tree.',
5373
checkout='Reconfigure to be a bound branch with a working tree.',
5374
lightweight_checkout='Reconfigure to be a lightweight'
5375
' checkout (with no local history).',
5376
standalone='Reconfigure to be a standalone branch '
5377
'(i.e. stop using shared repository).',
5378
use_shared='Reconfigure to use a shared repository.',
5379
with_trees='Reconfigure repository to create '
5380
'working trees on branches by default.',
5381
with_no_trees='Reconfigure repository to not create '
5382
'working trees on branches by default.'
5384
Option('bind-to', help='Branch to bind checkout to.', type=str),
5386
help='Perform reconfiguration even if local changes'
5388
Option('stacked-on',
5389
help='Reconfigure a branch to be stacked on another branch.',
5393
help='Reconfigure a branch to be unstacked. This '
5394
'may require copying substantial data into it.',
4864
def run(self, location=None, target_type=None, bind_to=None, force=False):
5398
def run(self, location=None, target_type=None, bind_to=None, force=False,
4865
5401
directory = bzrdir.BzrDir.open(location)
5402
if stacked_on and unstacked:
5403
raise BzrCommandError("Can't use both --stacked-on and --unstacked")
5404
elif stacked_on is not None:
5405
reconfigure.ReconfigureStackedOn().apply(directory, stacked_on)
5407
reconfigure.ReconfigureUnstacked().apply(directory)
5408
# At the moment you can use --stacked-on and a different
5409
# reconfiguration shape at the same time; there seems no good reason
4866
5411
if target_type is None:
4867
raise errors.BzrCommandError('No target configuration specified')
5412
if stacked_on or unstacked:
5415
raise errors.BzrCommandError('No target configuration '
4868
5417
elif target_type == 'branch':
4869
5418
reconfiguration = reconfigure.Reconfigure.to_branch(directory)
4870
5419
elif target_type == 'tree':
4871
5420
reconfiguration = reconfigure.Reconfigure.to_tree(directory)
4872
5421
elif target_type == 'checkout':
4873
reconfiguration = reconfigure.Reconfigure.to_checkout(directory,
5422
reconfiguration = reconfigure.Reconfigure.to_checkout(
4875
5424
elif target_type == 'lightweight-checkout':
4876
5425
reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
4877
5426
directory, bind_to)
4901
5456
/path/to/newbranch.
4903
5458
Bound branches use the nickname of its master branch unless it is set
4904
locally, in which case switching will update the the local nickname to be
5459
locally, in which case switching will update the local nickname to be
4905
5460
that of the master.
4908
takes_args = ['to_location']
5463
takes_args = ['to_location?']
4909
5464
takes_options = [Option('force',
4910
help='Switch even if local commits will be lost.')
5465
help='Switch even if local commits will be lost.'),
5467
Option('create-branch', short_name='b',
5468
help='Create the target branch from this one before'
5469
' switching to it.'),
4913
def run(self, to_location, force=False):
5472
def run(self, to_location=None, force=False, create_branch=False,
4914
5474
from bzrlib import switch
4915
5475
tree_location = '.'
5476
revision = _get_one_revision('switch', revision)
4916
5477
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
4917
branch = control_dir.open_branch()
5478
if to_location is None:
5479
if revision is None:
5480
raise errors.BzrCommandError('You must supply either a'
5481
' revision or a location')
4919
to_branch = Branch.open(to_location)
5484
branch = control_dir.open_branch()
5485
had_explicit_nick = branch.get_config().has_explicit_nickname()
4920
5486
except errors.NotBranchError:
4921
this_branch = control_dir.open_branch()
4922
# This may be a heavy checkout, where we want the master branch
4923
this_url = this_branch.get_bound_location()
4924
# If not, use a local sibling
4925
if this_url is None:
4926
this_url = this_branch.base
4927
to_branch = Branch.open(
4928
urlutils.join(this_url, '..', to_location))
4929
switch.switch(control_dir, to_branch, force)
4930
if branch.get_config().has_explicit_nickname():
5488
had_explicit_nick = False
5491
raise errors.BzrCommandError('cannot create branch without'
5493
to_location = directory_service.directories.dereference(
5495
if '/' not in to_location and '\\' not in to_location:
5496
# This path is meant to be relative to the existing branch
5497
this_url = self._get_branch_location(control_dir)
5498
to_location = urlutils.join(this_url, '..', to_location)
5499
to_branch = branch.bzrdir.sprout(to_location,
5500
possible_transports=[branch.bzrdir.root_transport],
5501
source_branch=branch).open_branch()
5504
to_branch = Branch.open(to_location)
5505
except errors.NotBranchError:
5506
this_url = self._get_branch_location(control_dir)
5507
to_branch = Branch.open(
5508
urlutils.join(this_url, '..', to_location))
5509
if revision is not None:
5510
revision = revision.as_revision_id(to_branch)
5511
switch.switch(control_dir, to_branch, force, revision_id=revision)
5512
if had_explicit_nick:
4931
5513
branch = control_dir.open_branch() #get the new branch!
4932
5514
branch.nick = to_branch.nick
4933
5515
note('Switched to branch: %s',
4934
5516
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
5518
def _get_branch_location(self, control_dir):
5519
"""Return location of branch for this control dir."""
5521
this_branch = control_dir.open_branch()
5522
# This may be a heavy checkout, where we want the master branch
5523
master_location = this_branch.get_bound_location()
5524
if master_location is not None:
5525
return master_location
5526
# If not, use a local sibling
5527
return this_branch.base
5528
except errors.NotBranchError:
5529
format = control_dir.find_branch_format()
5530
if getattr(format, 'get_reference', None) is not None:
5531
return format.get_reference(control_dir)
5533
return control_dir.root_transport.base
5536
class cmd_view(Command):
5537
"""Manage filtered views.
5539
Views provide a mask over the tree so that users can focus on
5540
a subset of a tree when doing their work. After creating a view,
5541
commands that support a list of files - status, diff, commit, etc -
5542
effectively have that list of files implicitly given each time.
5543
An explicit list of files can still be given but those files
5544
must be within the current view.
5546
In most cases, a view has a short life-span: it is created to make
5547
a selected change and is deleted once that change is committed.
5548
At other times, you may wish to create one or more named views
5549
and switch between them.
5551
To disable the current view without deleting it, you can switch to
5552
the pseudo view called ``off``. This can be useful when you need
5553
to see the whole tree for an operation or two (e.g. merge) but
5554
want to switch back to your view after that.
5557
To define the current view::
5559
bzr view file1 dir1 ...
5561
To list the current view::
5565
To delete the current view::
5569
To disable the current view without deleting it::
5571
bzr view --switch off
5573
To define a named view and switch to it::
5575
bzr view --name view-name file1 dir1 ...
5577
To list a named view::
5579
bzr view --name view-name
5581
To delete a named view::
5583
bzr view --name view-name --delete
5585
To switch to a named view::
5587
bzr view --switch view-name
5589
To list all views defined::
5593
To delete all views::
5595
bzr view --delete --all
5599
takes_args = ['file*']
5602
help='Apply list or delete action to all views.',
5605
help='Delete the view.',
5608
help='Name of the view to define, list or delete.',
5612
help='Name of the view to switch to.',
5617
def run(self, file_list,
5623
tree, file_list = tree_files(file_list, apply_view=False)
5624
current_view, view_dict = tree.views.get_view_info()
5629
raise errors.BzrCommandError(
5630
"Both --delete and a file list specified")
5632
raise errors.BzrCommandError(
5633
"Both --delete and --switch specified")
5635
tree.views.set_view_info(None, {})
5636
self.outf.write("Deleted all views.\n")
5638
raise errors.BzrCommandError("No current view to delete")
5640
tree.views.delete_view(name)
5641
self.outf.write("Deleted '%s' view.\n" % name)
5644
raise errors.BzrCommandError(
5645
"Both --switch and a file list specified")
5647
raise errors.BzrCommandError(
5648
"Both --switch and --all specified")
5649
elif switch == 'off':
5650
if current_view is None:
5651
raise errors.BzrCommandError("No current view to disable")
5652
tree.views.set_view_info(None, view_dict)
5653
self.outf.write("Disabled '%s' view.\n" % (current_view))
5655
tree.views.set_view_info(switch, view_dict)
5656
view_str = views.view_display_str(tree.views.lookup_view())
5657
self.outf.write("Using '%s' view: %s\n" % (switch, view_str))
5660
self.outf.write('Views defined:\n')
5661
for view in sorted(view_dict):
5662
if view == current_view:
5666
view_str = views.view_display_str(view_dict[view])
5667
self.outf.write('%s %-20s %s\n' % (active, view, view_str))
5669
self.outf.write('No views defined.\n')
5672
# No name given and no current view set
5675
raise errors.BzrCommandError(
5676
"Cannot change the 'off' pseudo view")
5677
tree.views.set_view(name, sorted(file_list))
5678
view_str = views.view_display_str(tree.views.lookup_view())
5679
self.outf.write("Using '%s' view: %s\n" % (name, view_str))
5683
# No name given and no current view set
5684
self.outf.write('No current view.\n')
5686
view_str = views.view_display_str(tree.views.lookup_view(name))
5687
self.outf.write("'%s' view is: %s\n" % (name, view_str))
4937
5690
class cmd_hooks(Command):
4938
"""Show a branch's currently registered hooks.
4942
takes_args = ['path?']
4944
def run(self, path=None):
4947
branch_hooks = Branch.open(path).hooks
4948
for hook_type in branch_hooks:
4949
hooks = branch_hooks[hook_type]
4950
self.outf.write("%s:\n" % (hook_type,))
4953
self.outf.write(" %s\n" %
4954
(branch_hooks.get_hook_name(hook),))
4956
self.outf.write(" <no hooks installed>\n")
5696
for hook_key in sorted(hooks.known_hooks.keys()):
5697
some_hooks = hooks.known_hooks_key_to_object(hook_key)
5698
self.outf.write("%s:\n" % type(some_hooks).__name__)
5699
for hook_name, hook_point in sorted(some_hooks.items()):
5700
self.outf.write(" %s:\n" % (hook_name,))
5701
found_hooks = list(hook_point)
5703
for hook in found_hooks:
5704
self.outf.write(" %s\n" %
5705
(some_hooks.get_hook_name(hook),))
5707
self.outf.write(" <no hooks installed>\n")
4959
5710
class cmd_shelve(Command):
4990
5743
value_switches=True, enum_switch=False),
4992
5745
Option('list', help='List shelved changes.'),
5747
help='Destroy removed changes instead of shelving them.'),
4994
5749
_see_also = ['unshelve']
4996
5751
def run(self, revision=None, all=False, file_list=None, message=None,
4997
writer=None, list=False):
5752
writer=None, list=False, destroy=False):
4999
5754
return self.run_for_list()
5000
5755
from bzrlib.shelf_ui import Shelver
5001
5756
if writer is None:
5002
5757
writer = bzrlib.option.diff_writer_registry.get()
5004
Shelver.from_args(writer(sys.stdout), revision, all, file_list,
5759
shelver = Shelver.from_args(writer(sys.stdout), revision, all,
5760
file_list, message, destroy=destroy)
5006
5765
except errors.UserAbort:
5009
5768
def run_for_list(self):
5010
5769
tree = WorkingTree.open_containing('.')[0]
5011
5770
tree.lock_read()
5013
manager = tree.get_shelf_manager()
5014
shelves = manager.active_shelves()
5015
if len(shelves) == 0:
5016
note('No shelved changes.')
5018
for shelf_id in reversed(shelves):
5019
message = manager.get_metadata(shelf_id).get('message')
5021
message = '<no message>'
5022
self.outf.write('%3d: %s\n' % (shelf_id, message))
5771
self.add_cleanup(tree.unlock)
5772
manager = tree.get_shelf_manager()
5773
shelves = manager.active_shelves()
5774
if len(shelves) == 0:
5775
note('No shelved changes.')
5777
for shelf_id in reversed(shelves):
5778
message = manager.get_metadata(shelf_id).get('message')
5780
message = '<no message>'
5781
self.outf.write('%3d: %s\n' % (shelf_id, message))
5028
5785
class cmd_unshelve(Command):
5029
5786
"""Restore shelved changes.
5031
5788
By default, the most recently shelved changes are restored. However if you
5032
specify a patch by name those changes will be restored instead. This
5033
works best when the changes don't depend on each other.
5789
specify a shelf by id those changes will be restored instead. This works
5790
best when the changes don't depend on each other.
5036
5793
takes_args = ['shelf_id?']
5040
5797
enum_switch=False, value_switches=True,
5041
5798
apply="Apply changes and remove from the shelf.",
5042
5799
dry_run="Show changes, but do not apply or remove them.",
5043
delete_only="Delete changes without applying them."
5800
preview="Instead of unshelving the changes, show the diff that "
5801
"would result from unshelving.",
5802
delete_only="Delete changes without applying them.",
5803
keep="Apply changes but don't delete them.",
5046
5806
_see_also = ['shelve']
5048
5808
def run(self, shelf_id=None, action='apply'):
5049
5809
from bzrlib.shelf_ui import Unshelver
5050
Unshelver.from_args(shelf_id, action).run()
5053
def _create_prefix(cur_transport):
5054
needed = [cur_transport]
5055
# Recurse upwards until we can create a directory successfully
5057
new_transport = cur_transport.clone('..')
5058
if new_transport.base == cur_transport.base:
5059
raise errors.BzrCommandError(
5060
"Failed to create path prefix for %s."
5061
% cur_transport.base)
5810
unshelver = Unshelver.from_args(shelf_id, action)
5063
new_transport.mkdir('.')
5064
except errors.NoSuchFile:
5065
needed.append(new_transport)
5066
cur_transport = new_transport
5814
unshelver.tree.unlock()
5817
class cmd_clean_tree(Command):
5818
"""Remove unwanted files from working tree.
5820
By default, only unknown files, not ignored files, are deleted. Versioned
5821
files are never deleted.
5823
Another class is 'detritus', which includes files emitted by bzr during
5824
normal operations and selftests. (The value of these files decreases with
5827
If no options are specified, unknown files are deleted. Otherwise, option
5828
flags are respected, and may be combined.
5830
To check what clean-tree will do, use --dry-run.
5832
takes_options = [Option('ignored', help='Delete all ignored files.'),
5833
Option('detritus', help='Delete conflict files, merge'
5834
' backups, and failed selftest dirs.'),
5836
help='Delete files unknown to bzr (default).'),
5837
Option('dry-run', help='Show files to delete instead of'
5839
Option('force', help='Do not prompt before deleting.')]
5840
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5842
from bzrlib.clean_tree import clean_tree
5843
if not (unknown or ignored or detritus):
5847
clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
5848
dry_run=dry_run, no_prompt=force)
5851
class cmd_reference(Command):
5852
"""list, view and set branch locations for nested trees.
5854
If no arguments are provided, lists the branch locations for nested trees.
5855
If one argument is provided, display the branch location for that tree.
5856
If two arguments are provided, set the branch location for that tree.
5861
takes_args = ['path?', 'location?']
5863
def run(self, path=None, location=None):
5865
if path is not None:
5867
tree, branch, relpath =(
5868
bzrdir.BzrDir.open_containing_tree_or_branch(branchdir))
5869
if path is not None:
5872
tree = branch.basis_tree()
5874
info = branch._get_all_reference_info().iteritems()
5875
self._display_reference_info(tree, branch, info)
5069
# Now we only need to create child directories
5071
cur_transport = needed.pop()
5072
cur_transport.ensure_base()
5877
file_id = tree.path2id(path)
5879
raise errors.NotVersionedError(path)
5880
if location is None:
5881
info = [(file_id, branch.get_reference_info(file_id))]
5882
self._display_reference_info(tree, branch, info)
5884
branch.set_reference_info(file_id, path, location)
5886
def _display_reference_info(self, tree, branch, info):
5888
for file_id, (path, location) in info:
5890
path = tree.id2path(file_id)
5891
except errors.NoSuchId:
5893
ref_list.append((path, location))
5894
for path, location in sorted(ref_list):
5895
self.outf.write('%s %s\n' % (path, location))
5075
5898
# these get imported and then picked up by the scan for cmd_*
5076
5899
# TODO: Some more consistent way to split command definitions across files;
5077
# we do need to load at least some information about them to know of
5900
# we do need to load at least some information about them to know of
5078
5901
# aliases. ideally we would avoid loading the implementation until the
5079
5902
# details were needed.
5080
5903
from bzrlib.cmd_version_info import cmd_version_info