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
76
115
def _get_one_revision(command_name, revisions):
77
116
if revisions is None:
108
157
The filenames given are not required to exist.
110
:param file_list: Filenames to convert.
159
:param file_list: Filenames to convert.
112
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
115
167
:return: workingtree, [relative_paths]
117
169
if file_list is None or len(file_list) == 0:
118
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
119
178
tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
120
return tree, safe_relpath_files(tree, file_list, canonicalize)
123
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):
124
184
"""Convert file_list into a list of relpaths in tree.
126
186
:param tree: A tree to operate on.
127
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
128
190
:return: A list of relative paths.
129
191
:raises errors.PathNotChild: When a provided path is in a different tree
132
194
if file_list is None:
196
if tree.supports_views() and apply_view:
197
view_files = tree.views.lookup_view()
135
201
# tree.relpath exists as a "thunk" to osutils, but canonical_relpath
136
202
# doesn't - fix that up here before we enter the loop.
534
Option('tree', help='Show revno of working tree'),
430
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)
433
552
if revision is not None:
434
revs.extend(revision)
553
revision_ids.extend(rev.as_revision_id(b) for rev in revision)
435
554
if revision_info_list is not None:
436
for rev in revision_info_list:
437
revs.append(RevisionSpec.from_string(rev))
439
b = Branch.open_containing(directory)[0]
442
revs.append(RevisionSpec.from_string('-1'))
445
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:
447
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)
448
573
except errors.NoSuchRevision:
449
dotted_map = b.get_revision_id_to_revno_map()
450
revno = '.'.join(str(i) for i in dotted_map[revision_id])
451
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]))
454
583
class cmd_add(Command):
455
584
"""Add specified files or directories.
668
783
takes_args = ['names*']
669
784
takes_options = [Option("after", help="Move only the bzr identifier"
670
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.'),
672
789
aliases = ['move', 'rename']
673
790
encoding_type = 'replace'
675
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.')
676
797
if names_list is None:
679
799
if len(names_list) < 2:
680
800
raise errors.BzrCommandError("missing file argument")
681
801
tree, rel_names = tree_files(names_list, canonicalize=False)
684
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)
688
818
def _run(self, tree, names_list, rel_names, after):
689
819
into_existing = osutils.isdir(names_list[-1])
853
995
if branch_to.get_parent() is None or remember:
854
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)
856
1001
if revision is not None:
857
1002
revision_id = revision.as_revision_id(branch_from)
859
1004
branch_to.lock_write()
861
if tree_to is not None:
862
change_reporter = delta._ChangeReporter(
863
unversioned_filter=tree_to.is_ignored)
864
result = tree_to.pull(branch_from, overwrite, revision_id,
866
possible_transports=possible_transports)
868
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)
870
result.report(self.outf)
871
if verbose and result.old_revid != result.new_revid:
872
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,
878
1025
class cmd_push(Command):
879
1026
"""Update a mirror of this branch.
881
1028
The target branch will not have its working tree populated because this
882
1029
is both expensive, and is not supported on remote file systems.
884
1031
Some smart servers or protocols *may* put the working tree in place in
999
1164
takes_args = ['from_location', 'to_location?']
1000
1165
takes_options = ['revision', Option('hardlink',
1001
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."),
1002
1172
Option('stacked',
1003
1173
help='Create a stacked branch referring to the source branch. '
1004
1174
'The new branch will depend on the availability of the source '
1005
1175
'branch for all operations.'),
1006
1176
Option('standalone',
1007
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.'),
1009
1184
aliases = ['get', 'clone']
1011
1186
def run(self, from_location, to_location=None, revision=None,
1012
hardlink=False, stacked=False, standalone=False):
1187
hardlink=False, stacked=False, standalone=False, no_tree=False,
1188
use_existing_dir=False, switch=False):
1189
from bzrlib import switch as _mod_switch
1013
1190
from bzrlib.tag import _merge_tags_if_possible
1015
1191
accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1017
1193
revision = _get_one_revision('branch', revision)
1018
1194
br_from.lock_read()
1195
self.add_cleanup(br_from.unlock)
1196
if revision is not None:
1197
revision_id = revision.as_revision_id(br_from)
1199
# FIXME - wt.last_revision, fallback to branch, fall back to
1200
# None or perhaps NULL_REVISION to mean copy nothing
1202
revision_id = br_from.last_revision()
1203
if to_location is None:
1204
to_location = urlutils.derive_to_location(from_location)
1205
to_transport = transport.get_transport(to_location)
1020
if revision is not None:
1021
revision_id = revision.as_revision_id(br_from)
1207
to_transport.mkdir('.')
1208
except errors.FileExists:
1209
if not use_existing_dir:
1210
raise errors.BzrCommandError('Target directory "%s" '
1211
'already exists.' % to_location)
1023
# FIXME - wt.last_revision, fallback to branch, fall back to
1024
# None or perhaps NULL_REVISION to mean copy nothing
1026
revision_id = br_from.last_revision()
1027
if to_location is None:
1028
to_location = urlutils.derive_to_location(from_location)
1029
to_transport = transport.get_transport(to_location)
1031
to_transport.mkdir('.')
1032
except errors.FileExists:
1033
raise errors.BzrCommandError('Target directory "%s" already'
1034
' exists.' % to_location)
1035
except errors.NoSuchFile:
1036
raise errors.BzrCommandError('Parent of "%s" does not exist.'
1039
# preserve whatever source format we have.
1040
dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
1041
possible_transports=[to_transport],
1042
accelerator_tree=accelerator_tree,
1043
hardlink=hardlink, stacked=stacked,
1044
force_new_repo=standalone,
1045
source_branch=br_from)
1046
branch = dir.open_branch()
1047
except errors.NoSuchRevision:
1048
to_transport.delete_tree('.')
1049
msg = "The branch %s has no revision %s." % (from_location,
1051
raise errors.BzrCommandError(msg)
1052
_merge_tags_if_possible(br_from, branch)
1053
# If the source branch is stacked, the new branch may
1054
# be stacked whether we asked for that explicitly or not.
1055
# We therefore need a try/except here and not just 'if stacked:'
1057
note('Created new stacked branch referring to %s.' %
1058
branch.get_stacked_on_url())
1059
except (errors.NotStacked, errors.UnstackableBranchFormat,
1060
errors.UnstackableRepositoryFormat), e:
1061
note('Branched %d revision(s).' % branch.revno())
1214
bzrdir.BzrDir.open_from_transport(to_transport)
1215
except errors.NotBranchError:
1218
raise errors.AlreadyBranchError(to_location)
1219
except errors.NoSuchFile:
1220
raise errors.BzrCommandError('Parent of "%s" does not exist.'
1223
# preserve whatever source format we have.
1224
dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
1225
possible_transports=[to_transport],
1226
accelerator_tree=accelerator_tree,
1227
hardlink=hardlink, stacked=stacked,
1228
force_new_repo=standalone,
1229
create_tree_if_local=not no_tree,
1230
source_branch=br_from)
1231
branch = dir.open_branch()
1232
except errors.NoSuchRevision:
1233
to_transport.delete_tree('.')
1234
msg = "The branch %s has no revision %s." % (from_location,
1236
raise errors.BzrCommandError(msg)
1237
_merge_tags_if_possible(br_from, branch)
1238
# If the source branch is stacked, the new branch may
1239
# be stacked whether we asked for that explicitly or not.
1240
# We therefore need a try/except here and not just 'if stacked:'
1242
note('Created new stacked branch referring to %s.' %
1243
branch.get_stacked_on_url())
1244
except (errors.NotStacked, errors.UnstackableBranchFormat,
1245
errors.UnstackableRepositoryFormat), e:
1246
note('Branched %d revision(s).' % branch.revno())
1248
# Switch to the new branch
1249
wt, _ = WorkingTree.open_containing('.')
1250
_mod_switch.switch(wt.bzrdir, branch)
1251
note('Switched to branch: %s',
1252
urlutils.unescape_for_display(branch.base, 'utf-8'))
1066
1255
class cmd_checkout(Command):
1145
1334
def run(self, dir=u'.'):
1146
1335
tree = WorkingTree.open_containing(dir)[0]
1147
1336
tree.lock_read()
1149
new_inv = tree.inventory
1150
old_tree = tree.basis_tree()
1151
old_tree.lock_read()
1153
old_inv = old_tree.inventory
1155
iterator = tree.iter_changes(old_tree, include_unchanged=True)
1156
for f, paths, c, v, p, n, k, e in iterator:
1157
if paths[0] == paths[1]:
1161
renames.append(paths)
1163
for old_name, new_name in renames:
1164
self.outf.write("%s => %s\n" % (old_name, new_name))
1337
self.add_cleanup(tree.unlock)
1338
new_inv = tree.inventory
1339
old_tree = tree.basis_tree()
1340
old_tree.lock_read()
1341
self.add_cleanup(old_tree.unlock)
1342
old_inv = old_tree.inventory
1344
iterator = tree.iter_changes(old_tree, include_unchanged=True)
1345
for f, paths, c, v, p, n, k, e in iterator:
1346
if paths[0] == paths[1]:
1350
renames.append(paths)
1352
for old_name, new_name in renames:
1353
self.outf.write("%s => %s\n" % (old_name, new_name))
1171
1356
class cmd_update(Command):
1172
1357
"""Update a tree to have the latest code committed to its branch.
1174
1359
This will perform a merge into the working tree, and may generate
1175
conflicts. If you have any local changes, you will still
1360
conflicts. If you have any local changes, you will still
1176
1361
need to commit them after the update for the update to be complete.
1178
If you want to discard your local changes, you can just do a
1363
If you want to discard your local changes, you can just do a
1179
1364
'bzr revert' instead of 'bzr commit' after the update.
1366
If the tree's branch is bound to a master branch, it will also update
1367
the branch from the master.
1182
1370
_see_also = ['pull', 'working-trees', 'status-flags']
1183
1371
takes_args = ['dir?']
1372
takes_options = ['revision']
1184
1373
aliases = ['up']
1186
def run(self, dir='.'):
1375
def run(self, dir='.', revision=None):
1376
if revision is not None and len(revision) != 1:
1377
raise errors.BzrCommandError(
1378
"bzr update --revision takes exactly one revision")
1187
1379
tree = WorkingTree.open_containing(dir)[0]
1380
branch = tree.branch
1188
1381
possible_transports = []
1189
master = tree.branch.get_master_branch(
1382
master = branch.get_master_branch(
1190
1383
possible_transports=possible_transports)
1191
1384
if master is not None:
1192
1385
tree.lock_write()
1386
branch_location = master.base
1194
1388
tree.lock_tree_write()
1389
branch_location = tree.branch.base
1390
self.add_cleanup(tree.unlock)
1391
# get rid of the final '/' and be ready for display
1392
branch_location = urlutils.unescape_for_display(branch_location[:-1],
1394
existing_pending_merges = tree.get_parent_ids()[1:]
1398
# may need to fetch data into a heavyweight checkout
1399
# XXX: this may take some time, maybe we should display a
1401
old_tip = branch.update(possible_transports)
1402
if revision is not None:
1403
revision_id = revision[0].as_revision_id(branch)
1405
revision_id = branch.last_revision()
1406
if revision_id == _mod_revision.ensure_null(tree.last_revision()):
1407
revno = branch.revision_id_to_revno(revision_id)
1408
note("Tree is up to date at revision %d of branch %s" %
1409
(revno, branch_location))
1411
view_info = _get_view_info_for_change_reporter(tree)
1412
change_reporter = delta._ChangeReporter(
1413
unversioned_filter=tree.is_ignored,
1414
view_info=view_info)
1196
existing_pending_merges = tree.get_parent_ids()[1:]
1197
last_rev = _mod_revision.ensure_null(tree.last_revision())
1198
if last_rev == _mod_revision.ensure_null(
1199
tree.branch.last_revision()):
1200
# may be up to date, check master too.
1201
if master is None or last_rev == _mod_revision.ensure_null(
1202
master.last_revision()):
1203
revno = tree.branch.revision_id_to_revno(last_rev)
1204
note("Tree is up to date at revision %d." % (revno,))
1206
1416
conflicts = tree.update(
1207
delta._ChangeReporter(unversioned_filter=tree.is_ignored),
1208
possible_transports=possible_transports)
1209
revno = tree.branch.revision_id_to_revno(
1210
_mod_revision.ensure_null(tree.last_revision()))
1211
note('Updated to revision %d.' % (revno,))
1212
if tree.get_parent_ids()[1:] != existing_pending_merges:
1213
note('Your local commits will now show as pending merges with '
1214
"'bzr status', and can be committed with 'bzr commit'.")
1418
possible_transports=possible_transports,
1419
revision=revision_id,
1421
except errors.NoSuchRevision, e:
1422
raise errors.BzrCommandError(
1423
"branch has no revision %s\n"
1424
"bzr update --revision only works"
1425
" for a revision in the branch history"
1427
revno = tree.branch.revision_id_to_revno(
1428
_mod_revision.ensure_null(tree.last_revision()))
1429
note('Updated to revision %d of branch %s' %
1430
(revno, branch_location))
1431
if tree.get_parent_ids()[1:] != existing_pending_merges:
1432
note('Your local commits will now show as pending merges with '
1433
"'bzr status', and can be committed with 'bzr commit'.")
1223
1440
class cmd_info(Command):
1224
1441
"""Show information about a working tree, branch or repository.
1226
1443
This command will show all known locations and formats associated to the
1227
tree, branch or repository. Statistical information is included with
1444
tree, branch or repository.
1446
In verbose mode, statistical information is included with each report.
1447
To see extended statistic information, use a verbosity level of 2 or
1448
higher by specifying the verbose option multiple times, e.g. -vv.
1230
1450
Branches and working trees will also report any missing revisions.
1454
Display information on the format and related locations:
1458
Display the above together with extended format information and
1459
basic statistics (like the number of files in the working tree and
1460
number of revisions in the branch and repository):
1464
Display the above together with number of committers to the branch:
1232
1468
_see_also = ['revno', 'working-trees', 'repositories']
1233
1469
takes_args = ['location?']
1275
1511
file_list = [f for f in file_list]
1277
1513
tree.lock_write()
1279
# Heuristics should probably all move into tree.remove_smart or
1282
added = tree.changes_from(tree.basis_tree(),
1283
specific_files=file_list).added
1284
file_list = sorted([f[0] for f in added], reverse=True)
1285
if len(file_list) == 0:
1286
raise errors.BzrCommandError('No matching files.')
1287
elif file_list is None:
1288
# missing files show up in iter_changes(basis) as
1289
# versioned-with-no-kind.
1291
for change in tree.iter_changes(tree.basis_tree()):
1292
# Find paths in the working tree that have no kind:
1293
if change[1][1] is not None and change[6][1] is None:
1294
missing.append(change[1][1])
1295
file_list = sorted(missing, reverse=True)
1296
file_deletion_strategy = 'keep'
1297
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1298
keep_files=file_deletion_strategy=='keep',
1299
force=file_deletion_strategy=='force')
1514
self.add_cleanup(tree.unlock)
1515
# Heuristics should probably all move into tree.remove_smart or
1518
added = tree.changes_from(tree.basis_tree(),
1519
specific_files=file_list).added
1520
file_list = sorted([f[0] for f in added], reverse=True)
1521
if len(file_list) == 0:
1522
raise errors.BzrCommandError('No matching files.')
1523
elif file_list is None:
1524
# missing files show up in iter_changes(basis) as
1525
# versioned-with-no-kind.
1527
for change in tree.iter_changes(tree.basis_tree()):
1528
# Find paths in the working tree that have no kind:
1529
if change[1][1] is not None and change[6][1] is None:
1530
missing.append(change[1][1])
1531
file_list = sorted(missing, reverse=True)
1532
file_deletion_strategy = 'keep'
1533
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1534
keep_files=file_deletion_strategy=='keep',
1535
force=file_deletion_strategy=='force')
1304
1538
class cmd_file_id(Command):
1821
2069
class cmd_log(Command):
1822
"""Show log of a branch, file, or directory.
1824
By default show the log of the branch containing the working directory.
1826
To request a range of logs, you can use the command -r begin..end
1827
-r revision requests a specific revision, -r ..end or -r begin.. are
1831
Log the current branch::
1839
Log the last 10 revisions of a branch::
1841
bzr log -r -10.. http://server/branch
2070
"""Show historical log for a branch or subset of a branch.
2072
log is bzr's default tool for exploring the history of a branch.
2073
The branch to use is taken from the first parameter. If no parameters
2074
are given, the branch containing the working directory is logged.
2075
Here are some simple examples::
2077
bzr log log the current branch
2078
bzr log foo.py log a file in its branch
2079
bzr log http://server/branch log a branch on a server
2081
The filtering, ordering and information shown for each revision can
2082
be controlled as explained below. By default, all revisions are
2083
shown sorted (topologically) so that newer revisions appear before
2084
older ones and descendants always appear before ancestors. If displayed,
2085
merged revisions are shown indented under the revision in which they
2090
The log format controls how information about each revision is
2091
displayed. The standard log formats are called ``long``, ``short``
2092
and ``line``. The default is long. See ``bzr help log-formats``
2093
for more details on log formats.
2095
The following options can be used to control what information is
2098
-l N display a maximum of N revisions
2099
-n N display N levels of revisions (0 for all, 1 for collapsed)
2100
-v display a status summary (delta) for each revision
2101
-p display a diff (patch) for each revision
2102
--show-ids display revision-ids (and file-ids), not just revnos
2104
Note that the default number of levels to display is a function of the
2105
log format. If the -n option is not used, the standard log formats show
2106
just the top level (mainline).
2108
Status summaries are shown using status flags like A, M, etc. To see
2109
the changes explained using words like ``added`` and ``modified``
2110
instead, use the -vv option.
2114
To display revisions from oldest to newest, use the --forward option.
2115
In most cases, using this option will have little impact on the total
2116
time taken to produce a log, though --forward does not incrementally
2117
display revisions like --reverse does when it can.
2119
:Revision filtering:
2121
The -r option can be used to specify what revision or range of revisions
2122
to filter against. The various forms are shown below::
2124
-rX display revision X
2125
-rX.. display revision X and later
2126
-r..Y display up to and including revision Y
2127
-rX..Y display from X to Y inclusive
2129
See ``bzr help revisionspec`` for details on how to specify X and Y.
2130
Some common examples are given below::
2132
-r-1 show just the tip
2133
-r-10.. show the last 10 mainline revisions
2134
-rsubmit:.. show what's new on this branch
2135
-rancestor:path.. show changes since the common ancestor of this
2136
branch and the one at location path
2137
-rdate:yesterday.. show changes since yesterday
2139
When logging a range of revisions using -rX..Y, log starts at
2140
revision Y and searches back in history through the primary
2141
("left-hand") parents until it finds X. When logging just the
2142
top level (using -n1), an error is reported if X is not found
2143
along the way. If multi-level logging is used (-n0), X may be
2144
a nested merge revision and the log will be truncated accordingly.
2148
If parameters are given and the first one is not a branch, the log
2149
will be filtered to show only those revisions that changed the
2150
nominated files or directories.
2152
Filenames are interpreted within their historical context. To log a
2153
deleted file, specify a revision range so that the file existed at
2154
the end or start of the range.
2156
Historical context is also important when interpreting pathnames of
2157
renamed files/directories. Consider the following example:
2159
* revision 1: add tutorial.txt
2160
* revision 2: modify tutorial.txt
2161
* revision 3: rename tutorial.txt to guide.txt; add tutorial.txt
2165
* ``bzr log guide.txt`` will log the file added in revision 1
2167
* ``bzr log tutorial.txt`` will log the new file added in revision 3
2169
* ``bzr log -r2 -p tutorial.txt`` will show the changes made to
2170
the original file in revision 2.
2172
* ``bzr log -r2 -p guide.txt`` will display an error message as there
2173
was no file called guide.txt in revision 2.
2175
Renames are always followed by log. By design, there is no need to
2176
explicitly ask for this (and no way to stop logging a file back
2177
until it was last renamed).
2181
The --message option can be used for finding revisions that match a
2182
regular expression in a commit message.
2186
GUI tools and IDEs are often better at exploring history than command
2187
line tools. You may prefer qlog or glog from the QBzr and Bzr-Gtk packages
2188
respectively for example. (TortoiseBzr uses qlog for displaying logs.) See
2189
http://bazaar-vcs.org/BzrPlugins and http://bazaar-vcs.org/IDEIntegration.
2191
Web interfaces are often better at exploring history than command line
2192
tools, particularly for branches on servers. You may prefer Loggerhead
2193
or one of its alternatives. See http://bazaar-vcs.org/WebInterface.
2195
You may find it useful to add the aliases below to ``bazaar.conf``::
2199
top = log -l10 --line
2202
``bzr tip`` will then show the latest revision while ``bzr top``
2203
will show the last 10 mainline revisions. To see the details of a
2204
particular revision X, ``bzr show -rX``.
2206
If you are interested in looking deeper into a particular merge X,
2207
use ``bzr log -n0 -rX``.
2209
``bzr log -v`` on a branch with lots of history is currently
2210
very slow. A fix for this issue is currently under development.
2211
With or without that fix, it is recommended that a revision range
2212
be given when using the -v option.
2214
bzr has a generic full-text matching plugin, bzr-search, that can be
2215
used to find revisions matching user names, commit messages, etc.
2216
Among other features, this plugin can find all revisions containing
2217
a list of words but not others.
2219
When exploring non-mainline history on large projects with deep
2220
history, the performance of log can be greatly improved by installing
2221
the historycache plugin. This plugin buffers historical information
2222
trading disk space for faster speed.
1844
# TODO: Make --revision support uuid: and hash: [future tag:] notation.
1846
takes_args = ['location?']
2224
takes_args = ['file*']
2225
_see_also = ['log-formats', 'revisionspec']
1847
2226
takes_options = [
1848
2227
Option('forward',
1849
2228
help='Show from oldest to newest.'),
1927
2326
dir, relpath = bzrdir.BzrDir.open_containing(location)
1928
2327
b = dir.open_branch()
2329
self.add_cleanup(b.unlock)
1932
2330
rev1, rev2 = _get_revision_range(revision, b, self.name())
1933
if log_format is None:
1934
log_format = log.log_formatter_registry.get_default(b)
1936
lf = log_format(show_ids=show_ids, to_file=self.outf,
1937
show_timezone=timezone,
1938
delta_format=get_verbosity_level(),
1945
direction=direction,
1946
start_revision=rev1,
1950
show_diff=show_diff)
2332
# Decide on the type of delta & diff filtering to use
2333
# TODO: add an --all-files option to make this configurable & consistent
2341
diff_type = 'partial'
2345
# Build the log formatter
2346
if log_format is None:
2347
log_format = log.log_formatter_registry.get_default(b)
2348
# Make a non-encoding output to include the diffs - bug 328007
2349
unencoded_output = ui.ui_factory.make_output_stream(encoding_type='exact')
2350
lf = log_format(show_ids=show_ids, to_file=self.outf,
2351
to_exact_file=unencoded_output,
2352
show_timezone=timezone,
2353
delta_format=get_verbosity_level(),
2355
show_advice=levels is None)
2357
# Choose the algorithm for doing the logging. It's annoying
2358
# having multiple code paths like this but necessary until
2359
# the underlying repository format is faster at generating
2360
# deltas or can provide everything we need from the indices.
2361
# The default algorithm - match-using-deltas - works for
2362
# multiple files and directories and is faster for small
2363
# amounts of history (200 revisions say). However, it's too
2364
# slow for logging a single file in a repository with deep
2365
# history, i.e. > 10K revisions. In the spirit of "do no
2366
# evil when adding features", we continue to use the
2367
# original algorithm - per-file-graph - for the "single
2368
# file that isn't a directory without showing a delta" case.
2369
partial_history = revision and b.repository._format.supports_chks
2370
match_using_deltas = (len(file_ids) != 1 or filter_by_dir
2371
or delta_type or partial_history)
2373
# Build the LogRequest and execute it
2374
if len(file_ids) == 0:
2376
rqst = make_log_request_dict(
2377
direction=direction, specific_fileids=file_ids,
2378
start_revision=rev1, end_revision=rev2, limit=limit,
2379
message_search=message, delta_type=delta_type,
2380
diff_type=diff_type, _match_using_deltas=match_using_deltas)
2381
Logger(b, rqst).show(lf)
1955
2384
def _get_revision_range(revisionspec_list, branch, command_name):
1956
2385
"""Take the input of a revision option and turn it into a revision range.
1958
2387
It returns RevisionInfo objects which can be used to obtain the rev_id's
1959
of the desired revisons. It does some user input validations.
2388
of the desired revisions. It does some user input validations.
1961
2390
if revisionspec_list is None:
2069
2500
if path is None:
2074
2504
raise errors.BzrCommandError('cannot specify both --from-root'
2078
2507
tree, branch, relpath = bzrdir.BzrDir.open_containing_tree_or_branch(
2510
# Calculate the prefix to use
2514
prefix = relpath + '/'
2515
elif fs_path != '.' and not fs_path.endswith('/'):
2516
prefix = fs_path + '/'
2084
2518
if revision is not None or tree is None:
2085
2519
tree = _get_one_revision_tree('ls', revision, branch=branch)
2522
if isinstance(tree, WorkingTree) and tree.supports_views():
2523
view_files = tree.views.lookup_view()
2526
view_str = views.view_display_str(view_files)
2527
note("Ignoring files outside view. View is %s" % view_str)
2087
2529
tree.lock_read()
2089
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False):
2090
if fp.startswith(relpath):
2091
fp = osutils.pathjoin(prefix, fp[len(relpath):])
2092
if non_recursive and '/' in fp:
2094
if not all and not selection[fc]:
2096
if kind is not None and fkind != kind:
2098
kindch = entry.kind_character()
2099
outstring = fp + kindch
2101
outstring = '%-8s %s' % (fc, outstring)
2102
if show_ids and fid is not None:
2103
outstring = "%-50s %s" % (outstring, fid)
2104
self.outf.write(outstring + '\n')
2106
self.outf.write(fp + '\0')
2109
self.outf.write(fid)
2110
self.outf.write('\0')
2118
self.outf.write('%-50s %s\n' % (outstring, my_id))
2120
self.outf.write(outstring + '\n')
2530
self.add_cleanup(tree.unlock)
2531
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
2532
from_dir=relpath, recursive=recursive):
2533
# Apply additional masking
2534
if not all and not selection[fc]:
2536
if kind is not None and fkind != kind:
2541
fullpath = osutils.pathjoin(relpath, fp)
2544
views.check_path_in_view(tree, fullpath)
2545
except errors.FileOutsideView:
2550
fp = osutils.pathjoin(prefix, fp)
2551
kindch = entry.kind_character()
2552
outstring = fp + kindch
2553
ui.ui_factory.clear_term()
2555
outstring = '%-8s %s' % (fc, outstring)
2556
if show_ids and fid is not None:
2557
outstring = "%-50s %s" % (outstring, fid)
2558
self.outf.write(outstring + '\n')
2560
self.outf.write(fp + '\0')
2563
self.outf.write(fid)
2564
self.outf.write('\0')
2572
self.outf.write('%-50s %s\n' % (outstring, my_id))
2574
self.outf.write(outstring + '\n')
2125
2577
class cmd_unknowns(Command):
2322
2782
If no revision is nominated, the last revision is used.
2324
2784
Note: Take care to redirect standard output when using this command on a
2328
2788
_see_also = ['ls']
2329
2789
takes_options = [
2330
2790
Option('name-from-revision', help='The path name in the old tree.'),
2791
Option('filters', help='Apply content filters to display the '
2792
'convenience form.'),
2333
2795
takes_args = ['filename']
2334
2796
encoding_type = 'exact'
2336
2798
@display_command
2337
def run(self, filename, revision=None, name_from_revision=False):
2799
def run(self, filename, revision=None, name_from_revision=False,
2338
2801
if revision is not None and len(revision) != 1:
2339
2802
raise errors.BzrCommandError("bzr cat --revision takes exactly"
2340
2803
" one revision specifier")
2341
2804
tree, branch, relpath = \
2342
2805
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
2343
2806
branch.lock_read()
2345
return self._run(tree, branch, relpath, filename, revision,
2807
self.add_cleanup(branch.unlock)
2808
return self._run(tree, branch, relpath, filename, revision,
2809
name_from_revision, filters)
2350
def _run(self, tree, b, relpath, filename, revision, name_from_revision):
2811
def _run(self, tree, b, relpath, filename, revision, name_from_revision,
2351
2813
if tree is None:
2352
2814
tree = b.basis_tree()
2353
2815
rev_tree = _get_one_revision_tree('cat', revision, branch=b)
2355
cur_file_id = tree.path2id(relpath)
2356
2817
old_file_id = rev_tree.path2id(relpath)
2358
2819
if name_from_revision:
2820
# Try in revision if requested
2359
2821
if old_file_id is None:
2360
2822
raise errors.BzrCommandError(
2361
2823
"%r is not present in revision %s" % (
2362
2824
filename, rev_tree.get_revision_id()))
2364
2826
content = rev_tree.get_file_text(old_file_id)
2365
elif cur_file_id is not None:
2366
content = rev_tree.get_file_text(cur_file_id)
2367
elif old_file_id is not None:
2368
content = rev_tree.get_file_text(old_file_id)
2370
raise errors.BzrCommandError(
2371
"%r is not present in revision %s" % (
2372
filename, rev_tree.get_revision_id()))
2373
self.outf.write(content)
2828
cur_file_id = tree.path2id(relpath)
2830
if cur_file_id is not None:
2831
# Then try with the actual file id
2833
content = rev_tree.get_file_text(cur_file_id)
2835
except errors.NoSuchId:
2836
# The actual file id didn't exist at that time
2838
if not found and old_file_id is not None:
2839
# Finally try with the old file id
2840
content = rev_tree.get_file_text(old_file_id)
2843
# Can't be found anywhere
2844
raise errors.BzrCommandError(
2845
"%r is not present in revision %s" % (
2846
filename, rev_tree.get_revision_id()))
2848
from bzrlib.filters import (
2849
ContentFilterContext,
2850
filtered_output_bytes,
2852
filters = rev_tree._content_filter_stack(relpath)
2853
chunks = content.splitlines(True)
2854
content = filtered_output_bytes(chunks, filters,
2855
ContentFilterContext(relpath, rev_tree))
2856
self.outf.writelines(content)
2858
self.outf.write(content)
2376
2861
class cmd_local_time_offset(Command):
2377
2862
"""Show the offset in seconds from GMT to local time."""
2379
2864
@display_command
2381
2866
print osutils.local_time_offset()
2385
2870
class cmd_commit(Command):
2386
2871
"""Commit changes into a new revision.
2388
If no arguments are given, the entire tree is committed.
2390
If selected files are specified, only changes to those files are
2391
committed. If a directory is specified then the directory and everything
2392
within it is committed.
2394
When excludes are given, they take precedence over selected files.
2395
For example, too commit only changes within foo, but not changes within
2398
bzr commit foo -x foo/bar
2400
If author of the change is not the same person as the committer, you can
2401
specify the author's name using the --author option. The name should be
2402
in the same format as a committer-id, e.g. "John Doe <jdoe@example.com>".
2404
A selected-file commit may fail in some cases where the committed
2405
tree would be invalid. Consider::
2410
bzr commit foo -m "committing foo"
2411
bzr mv foo/bar foo/baz
2414
bzr commit foo/bar -m "committing bar but not baz"
2416
In the example above, the last commit will fail by design. This gives
2417
the user the opportunity to decide whether they want to commit the
2418
rename at the same time, separately first, or not at all. (As a general
2419
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2421
Note: A selected-file commit after a merge is not yet supported.
2873
An explanatory message needs to be given for each commit. This is
2874
often done by using the --message option (getting the message from the
2875
command line) or by using the --file option (getting the message from
2876
a file). If neither of these options is given, an editor is opened for
2877
the user to enter the message. To see the changed files in the
2878
boilerplate text loaded into the editor, use the --show-diff option.
2880
By default, the entire tree is committed and the person doing the
2881
commit is assumed to be the author. These defaults can be overridden
2886
If selected files are specified, only changes to those files are
2887
committed. If a directory is specified then the directory and
2888
everything within it is committed.
2890
When excludes are given, they take precedence over selected files.
2891
For example, to commit only changes within foo, but not changes
2894
bzr commit foo -x foo/bar
2896
A selective commit after a merge is not yet supported.
2900
If the author of the change is not the same person as the committer,
2901
you can specify the author's name using the --author option. The
2902
name should be in the same format as a committer-id, e.g.
2903
"John Doe <jdoe@example.com>". If there is more than one author of
2904
the change you can specify the option multiple times, once for each
2909
A common mistake is to forget to add a new file or directory before
2910
running the commit command. The --strict option checks for unknown
2911
files and aborts the commit if any are found. More advanced pre-commit
2912
checks can be implemented by defining hooks. See ``bzr help hooks``
2917
If you accidentially commit the wrong changes or make a spelling
2918
mistake in the commit message say, you can use the uncommit command
2919
to undo it. See ``bzr help uncommit`` for details.
2921
Hooks can also be configured to run after a commit. This allows you
2922
to trigger updates to external systems like bug trackers. The --fixes
2923
option can be used to record the association between a revision and
2924
one or more bugs. See ``bzr help bugs`` for details.
2926
A selective commit may fail in some cases where the committed
2927
tree would be invalid. Consider::
2932
bzr commit foo -m "committing foo"
2933
bzr mv foo/bar foo/baz
2936
bzr commit foo/bar -m "committing bar but not baz"
2938
In the example above, the last commit will fail by design. This gives
2939
the user the opportunity to decide whether they want to commit the
2940
rename at the same time, separately first, or not at all. (As a general
2941
rule, when in doubt, Bazaar has a policy of Doing the Safe Thing.)
2423
2943
# TODO: Run hooks on tree to-be-committed, and after commit.
2458
2982
"the master branch until a normal commit "
2459
2983
"is performed."
2462
help='When no message is supplied, show the diff along'
2463
' with the status summary in the message editor.'),
2986
help='When no message is supplied, show the diff along'
2987
' with the status summary in the message editor.'),
2465
2989
aliases = ['ci', 'checkin']
2467
def _get_bug_fix_properties(self, fixes, branch):
2991
def _iter_bug_fix_urls(self, fixes, branch):
2469
2992
# Configure the properties for bug fixing attributes.
2470
2993
for fixed_bug in fixes:
2471
2994
tokens = fixed_bug.split(':')
2472
2995
if len(tokens) != 2:
2473
2996
raise errors.BzrCommandError(
2474
"Invalid bug %s. Must be in the form of 'tag:id'. "
2475
"Commit refused." % fixed_bug)
2997
"Invalid bug %s. Must be in the form of 'tracker:id'. "
2998
"See \"bzr help bugs\" for more information on this "
2999
"feature.\nCommit refused." % fixed_bug)
2476
3000
tag, bug_id = tokens
2478
bug_url = bugtracker.get_bug_url(tag, branch, bug_id)
3002
yield bugtracker.get_bug_url(tag, branch, bug_id)
2479
3003
except errors.UnknownBugTrackerAbbreviation:
2480
3004
raise errors.BzrCommandError(
2481
3005
'Unrecognized bug %s. Commit refused.' % fixed_bug)
2482
except errors.MalformedBugIdentifier:
3006
except errors.MalformedBugIdentifier, e:
2483
3007
raise errors.BzrCommandError(
2484
"Invalid bug identifier for %s. Commit refused."
2486
properties.append('%s fixed' % bug_url)
2487
return '\n'.join(properties)
3008
"%s\nCommit refused." % (str(e),))
2489
3010
def run(self, message=None, file=None, verbose=False, selected_list=None,
2490
3011
unchanged=False, strict=False, local=False, fixes=None,
2491
author=None, show_diff=False, exclude=None):
3012
author=None, show_diff=False, exclude=None, commit_time=None):
2492
3013
from bzrlib.errors import (
2493
3014
PointlessCommit,
2494
3015
ConflictsInTree,
2925
3502
if cache_dir is not None:
2926
3503
tree_creator.TreeCreator.CACHE_ROOT = osutils.abspath(cache_dir)
2928
print 'testing: %s' % (osutils.realpath(sys.argv[0]),)
2929
print ' %s (%s python%s)' % (
2931
bzrlib.version_string,
2932
bzrlib._format_version_tuple(sys.version_info),
2935
3504
if testspecs_list is not None:
2936
3505
pattern = '|'.join(testspecs_list)
3510
from bzrlib.tests import SubUnitBzrRunner
3512
raise errors.BzrCommandError("subunit not available. subunit "
3513
"needs to be installed to use --subunit.")
3514
self.additional_selftest_args['runner_class'] = SubUnitBzrRunner
3516
self.additional_selftest_args.setdefault(
3517
'suite_decorators', []).append(parallel)
2940
3519
test_suite_factory = benchmarks.test_suite
2941
3520
# Unless user explicitly asks for quiet, be verbose in benchmarks
2942
3521
verbose = not is_quiet()
2943
3522
# TODO: should possibly lock the history file...
2944
3523
benchfile = open(".perf_history", "at", buffering=1)
3524
self.add_cleanup(benchfile.close)
2946
3526
test_suite_factory = None
2947
3527
benchfile = None
2949
result = selftest(verbose=verbose,
2951
stop_on_failure=one,
2952
transport=transport,
2953
test_suite_factory=test_suite_factory,
2954
lsprof_timed=lsprof_timed,
2955
bench_history=benchfile,
2956
matching_tests_first=first,
2957
list_only=list_only,
2958
random_seed=randomize,
2959
exclude_pattern=exclude,
2961
load_list=load_list,
2962
debug_flags=debugflag,
2963
starting_with=starting_with,
2966
if benchfile is not None:
2969
note('tests passed')
2971
note('tests failed')
3528
selftest_kwargs = {"verbose": verbose,
3530
"stop_on_failure": one,
3531
"transport": transport,
3532
"test_suite_factory": test_suite_factory,
3533
"lsprof_timed": lsprof_timed,
3534
"lsprof_tests": lsprof_tests,
3535
"bench_history": benchfile,
3536
"matching_tests_first": first,
3537
"list_only": list_only,
3538
"random_seed": randomize,
3539
"exclude_pattern": exclude,
3541
"load_list": load_list,
3542
"debug_flags": debugflag,
3543
"starting_with": starting_with
3545
selftest_kwargs.update(self.additional_selftest_args)
3546
result = selftest(**selftest_kwargs)
2972
3547
return int(not result)
3128
3706
allow_pending = True
3129
3707
verified = 'inapplicable'
3130
3708
tree = WorkingTree.open_containing(directory)[0]
3711
basis_tree = tree.revision_tree(tree.last_revision())
3712
except errors.NoSuchRevision:
3713
basis_tree = tree.basis_tree()
3715
# die as quickly as possible if there are uncommitted changes
3717
if tree.has_changes():
3718
raise errors.UncommittedChanges(tree)
3720
view_info = _get_view_info_for_change_reporter(tree)
3131
3721
change_reporter = delta._ChangeReporter(
3132
unversioned_filter=tree.is_ignored)
3135
pb = ui.ui_factory.nested_progress_bar()
3136
cleanups.append(pb.finished)
3138
cleanups.append(tree.unlock)
3139
if location is not None:
3141
mergeable = bundle.read_mergeable_from_url(location,
3142
possible_transports=possible_transports)
3143
except errors.NotABundle:
3147
raise errors.BzrCommandError('Cannot use --uncommitted'
3148
' with bundles or merge directives.')
3150
if revision is not None:
3151
raise errors.BzrCommandError(
3152
'Cannot use -r with merge directives or bundles')
3153
merger, verified = _mod_merge.Merger.from_mergeable(tree,
3156
if merger is None and uncommitted:
3157
if revision is not None and len(revision) > 0:
3158
raise errors.BzrCommandError('Cannot use --uncommitted and'
3159
' --revision at the same time.')
3160
location = self._select_branch_location(tree, location)[0]
3161
other_tree, other_path = WorkingTree.open_containing(location)
3162
merger = _mod_merge.Merger.from_uncommitted(tree, other_tree,
3164
allow_pending = False
3165
if other_path != '':
3166
merger.interesting_files = [other_path]
3169
merger, allow_pending = self._get_merger_from_branch(tree,
3170
location, revision, remember, possible_transports, pb)
3172
merger.merge_type = merge_type
3173
merger.reprocess = reprocess
3174
merger.show_base = show_base
3175
self.sanity_check_merger(merger)
3176
if (merger.base_rev_id == merger.other_rev_id and
3177
merger.other_rev_id is not None):
3178
note('Nothing to do.')
3722
unversioned_filter=tree.is_ignored, view_info=view_info)
3723
pb = ui.ui_factory.nested_progress_bar()
3724
self.add_cleanup(pb.finished)
3726
self.add_cleanup(tree.unlock)
3727
if location is not None:
3729
mergeable = bundle.read_mergeable_from_url(location,
3730
possible_transports=possible_transports)
3731
except errors.NotABundle:
3735
raise errors.BzrCommandError('Cannot use --uncommitted'
3736
' with bundles or merge directives.')
3738
if revision is not None:
3739
raise errors.BzrCommandError(
3740
'Cannot use -r with merge directives or bundles')
3741
merger, verified = _mod_merge.Merger.from_mergeable(tree,
3744
if merger is None and uncommitted:
3745
if revision is not None and len(revision) > 0:
3746
raise errors.BzrCommandError('Cannot use --uncommitted and'
3747
' --revision at the same time.')
3748
merger = self.get_merger_from_uncommitted(tree, location, pb)
3749
allow_pending = False
3752
merger, allow_pending = self._get_merger_from_branch(tree,
3753
location, revision, remember, possible_transports, pb)
3755
merger.merge_type = merge_type
3756
merger.reprocess = reprocess
3757
merger.show_base = show_base
3758
self.sanity_check_merger(merger)
3759
if (merger.base_rev_id == merger.other_rev_id and
3760
merger.other_rev_id is not None):
3761
note('Nothing to do.')
3764
if merger.interesting_files is not None:
3765
raise errors.BzrCommandError('Cannot pull individual files')
3766
if (merger.base_rev_id == tree.last_revision()):
3767
result = tree.pull(merger.other_branch, False,
3768
merger.other_rev_id)
3769
result.report(self.outf)
3181
if merger.interesting_files is not None:
3182
raise errors.BzrCommandError('Cannot pull individual files')
3183
if (merger.base_rev_id == tree.last_revision()):
3184
result = tree.pull(merger.other_branch, False,
3185
merger.other_rev_id)
3186
result.report(self.outf)
3188
merger.check_basis(not force)
3190
return self._do_preview(merger)
3192
return self._do_merge(merger, change_reporter, allow_pending,
3195
for cleanup in reversed(cleanups):
3771
if merger.this_basis is None:
3772
raise errors.BzrCommandError(
3773
"This branch has no commits."
3774
" (perhaps you would prefer 'bzr pull')")
3776
return self._do_preview(merger)
3778
return self._do_interactive(merger)
3780
return self._do_merge(merger, change_reporter, allow_pending,
3783
def _get_preview(self, merger):
3784
tree_merger = merger.make_merger()
3785
tt = tree_merger.make_preview_transform()
3786
self.add_cleanup(tt.finalize)
3787
result_tree = tt.get_preview_tree()
3198
3790
def _do_preview(self, merger):
3199
3791
from bzrlib.diff import show_diff_trees
3200
tree_merger = merger.make_merger()
3201
tt = tree_merger.make_preview_transform()
3203
result_tree = tt.get_preview_tree()
3204
show_diff_trees(merger.this_tree, result_tree, self.outf,
3205
old_label='', new_label='')
3792
result_tree = self._get_preview(merger)
3793
show_diff_trees(merger.this_tree, result_tree, self.outf,
3794
old_label='', new_label='')
3209
3796
def _do_merge(self, merger, change_reporter, allow_pending, verified):
3210
3797
merger.change_reporter = change_reporter
3366
3985
merge_type = _mod_merge.Merge3Merger
3367
3986
tree, file_list = tree_files(file_list)
3368
3987
tree.lock_write()
3988
self.add_cleanup(tree.unlock)
3989
parents = tree.get_parent_ids()
3990
if len(parents) != 2:
3991
raise errors.BzrCommandError("Sorry, remerge only works after normal"
3992
" merges. Not cherrypicking or"
3994
repository = tree.branch.repository
3995
interesting_ids = None
3997
conflicts = tree.conflicts()
3998
if file_list is not None:
3999
interesting_ids = set()
4000
for filename in file_list:
4001
file_id = tree.path2id(filename)
4003
raise errors.NotVersionedError(filename)
4004
interesting_ids.add(file_id)
4005
if tree.kind(file_id) != "directory":
4008
for name, ie in tree.inventory.iter_entries(file_id):
4009
interesting_ids.add(ie.file_id)
4010
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
4012
# Remerge only supports resolving contents conflicts
4013
allowed_conflicts = ('text conflict', 'contents conflict')
4014
restore_files = [c.path for c in conflicts
4015
if c.typestring in allowed_conflicts]
4016
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
4017
tree.set_conflicts(ConflictList(new_conflicts))
4018
if file_list is not None:
4019
restore_files = file_list
4020
for filename in restore_files:
4022
restore(tree.abspath(filename))
4023
except errors.NotConflicted:
4025
# Disable pending merges, because the file texts we are remerging
4026
# have not had those merges performed. If we use the wrong parents
4027
# list, we imply that the working tree text has seen and rejected
4028
# all the changes from the other tree, when in fact those changes
4029
# have not yet been seen.
4030
pb = ui.ui_factory.nested_progress_bar()
4031
tree.set_parent_ids(parents[:1])
3370
parents = tree.get_parent_ids()
3371
if len(parents) != 2:
3372
raise errors.BzrCommandError("Sorry, remerge only works after normal"
3373
" merges. Not cherrypicking or"
3375
repository = tree.branch.repository
3376
interesting_ids = None
3378
conflicts = tree.conflicts()
3379
if file_list is not None:
3380
interesting_ids = set()
3381
for filename in file_list:
3382
file_id = tree.path2id(filename)
3384
raise errors.NotVersionedError(filename)
3385
interesting_ids.add(file_id)
3386
if tree.kind(file_id) != "directory":
3389
for name, ie in tree.inventory.iter_entries(file_id):
3390
interesting_ids.add(ie.file_id)
3391
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
3393
# Remerge only supports resolving contents conflicts
3394
allowed_conflicts = ('text conflict', 'contents conflict')
3395
restore_files = [c.path for c in conflicts
3396
if c.typestring in allowed_conflicts]
3397
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
3398
tree.set_conflicts(ConflictList(new_conflicts))
3399
if file_list is not None:
3400
restore_files = file_list
3401
for filename in restore_files:
3403
restore(tree.abspath(filename))
3404
except errors.NotConflicted:
3406
# Disable pending merges, because the file texts we are remerging
3407
# have not had those merges performed. If we use the wrong parents
3408
# list, we imply that the working tree text has seen and rejected
3409
# all the changes from the other tree, when in fact those changes
3410
# have not yet been seen.
3411
pb = ui.ui_factory.nested_progress_bar()
3412
tree.set_parent_ids(parents[:1])
3414
merger = _mod_merge.Merger.from_revision_ids(pb,
3416
merger.interesting_ids = interesting_ids
3417
merger.merge_type = merge_type
3418
merger.show_base = show_base
3419
merger.reprocess = reprocess
3420
conflicts = merger.do_merge()
3422
tree.set_parent_ids(parents)
4033
merger = _mod_merge.Merger.from_revision_ids(pb,
4035
merger.interesting_ids = interesting_ids
4036
merger.merge_type = merge_type
4037
merger.show_base = show_base
4038
merger.reprocess = reprocess
4039
conflicts = merger.do_merge()
4041
tree.set_parent_ids(parents)
3426
4043
if conflicts > 0:
3634
4265
if remote_branch.base == local_branch.base:
3635
4266
remote_branch = local_branch
4268
local_branch.lock_read()
4269
self.add_cleanup(local_branch.unlock)
3637
4270
local_revid_range = _revision_range_to_revid_range(
3638
4271
_get_revision_range(my_revision, local_branch,
4274
remote_branch.lock_read()
4275
self.add_cleanup(remote_branch.unlock)
3641
4276
remote_revid_range = _revision_range_to_revid_range(
3642
4277
_get_revision_range(revision,
3643
4278
remote_branch, self.name()))
3645
local_branch.lock_read()
3647
remote_branch.lock_read()
3649
local_extra, remote_extra = find_unmerged(
3650
local_branch, remote_branch, restrict,
3651
backward=not reverse,
3652
include_merges=include_merges,
3653
local_revid_range=local_revid_range,
3654
remote_revid_range=remote_revid_range)
3656
if log_format is None:
3657
registry = log.log_formatter_registry
3658
log_format = registry.get_default(local_branch)
3659
lf = log_format(to_file=self.outf,
3661
show_timezone='original')
3664
if local_extra and not theirs_only:
3665
message("You have %d extra revision(s):\n" %
3667
for revision in iter_log_revisions(local_extra,
3668
local_branch.repository,
3670
lf.log_revision(revision)
3671
printed_local = True
3674
printed_local = False
3676
if remote_extra and not mine_only:
3677
if printed_local is True:
3679
message("You are missing %d revision(s):\n" %
3681
for revision in iter_log_revisions(remote_extra,
3682
remote_branch.repository,
3684
lf.log_revision(revision)
3687
if mine_only and not local_extra:
3688
# We checked local, and found nothing extra
3689
message('This branch is up to date.\n')
3690
elif theirs_only and not remote_extra:
3691
# We checked remote, and found nothing extra
3692
message('Other branch is up to date.\n')
3693
elif not (mine_only or theirs_only or local_extra or
3695
# We checked both branches, and neither one had extra
3697
message("Branches are up to date.\n")
3699
remote_branch.unlock()
3701
local_branch.unlock()
4280
local_extra, remote_extra = find_unmerged(
4281
local_branch, remote_branch, restrict,
4282
backward=not reverse,
4283
include_merges=include_merges,
4284
local_revid_range=local_revid_range,
4285
remote_revid_range=remote_revid_range)
4287
if log_format is None:
4288
registry = log.log_formatter_registry
4289
log_format = registry.get_default(local_branch)
4290
lf = log_format(to_file=self.outf,
4292
show_timezone='original')
4295
if local_extra and not theirs_only:
4296
message("You have %d extra revision(s):\n" %
4298
for revision in iter_log_revisions(local_extra,
4299
local_branch.repository,
4301
lf.log_revision(revision)
4302
printed_local = True
4305
printed_local = False
4307
if remote_extra and not mine_only:
4308
if printed_local is True:
4310
message("You are missing %d revision(s):\n" %
4312
for revision in iter_log_revisions(remote_extra,
4313
remote_branch.repository,
4315
lf.log_revision(revision)
4318
if mine_only and not local_extra:
4319
# We checked local, and found nothing extra
4320
message('This branch is up to date.\n')
4321
elif theirs_only and not remote_extra:
4322
# We checked remote, and found nothing extra
4323
message('Other branch is up to date.\n')
4324
elif not (mine_only or theirs_only or local_extra or
4326
# We checked both branches, and neither one had extra
4328
message("Branches are up to date.\n")
3702
4330
if not status_code and parent is None and other_branch is not None:
3703
4331
local_branch.lock_write()
3705
# handle race conditions - a parent might be set while we run.
3706
if local_branch.get_parent() is None:
3707
local_branch.set_parent(remote_branch.base)
3709
local_branch.unlock()
4332
self.add_cleanup(local_branch.unlock)
4333
# handle race conditions - a parent might be set while we run.
4334
if local_branch.get_parent() is None:
4335
local_branch.set_parent(remote_branch.base)
3710
4336
return status_code
3834
4458
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
3835
4459
if wt is not None:
4461
self.add_cleanup(wt.unlock)
3838
4463
branch.lock_read()
3840
tree = _get_one_revision_tree('annotate', revision, branch=branch)
3842
file_id = wt.path2id(relpath)
3844
file_id = tree.path2id(relpath)
3846
raise errors.NotVersionedError(filename)
3847
file_version = tree.inventory[file_id].revision
3848
if wt is not None and revision is None:
3849
# If there is a tree and we're not annotating historical
3850
# versions, annotate the working tree's content.
3851
annotate_file_tree(wt, file_id, self.outf, long, all,
3854
annotate_file(branch, file_version, file_id, long, all, self.outf,
4464
self.add_cleanup(branch.unlock)
4465
tree = _get_one_revision_tree('annotate', revision, branch=branch)
4467
self.add_cleanup(tree.unlock)
4469
file_id = wt.path2id(relpath)
4471
file_id = tree.path2id(relpath)
4473
raise errors.NotVersionedError(filename)
4474
file_version = tree.inventory[file_id].revision
4475
if wt is not None and revision is None:
4476
# If there is a tree and we're not annotating historical
4477
# versions, annotate the working tree's content.
4478
annotate_file_tree(wt, file_id, self.outf, long, all,
4481
annotate_file(branch, file_version, file_id, long, all, self.outf,
3863
4485
class cmd_re_sign(Command):
4187
4792
:return: A tuple of (host, port), where 'host' is a host name or IP,
4188
4793
and port is an integer TCP/IP port.
4190
from bzrlib.smart import medium
4191
host = medium.BZR_DEFAULT_INTERFACE
4193
port = medium.BZR_DEFAULT_PORT
4796
if port is not None:
4195
4797
if ':' in port:
4196
4798
host, port = port.split(':')
4197
4799
port = int(port)
4198
4800
return host, port
4200
def get_smart_server(self, transport, inet, port):
4201
"""Construct a smart server.
4203
:param transport: The base transport from which branches will be
4205
:param inet: If True, serve over stdin and stdout. Used for running
4207
:param port: The port to listen on. By default, it's `
4208
medium.BZR_DEFAULT_PORT`. See `get_host_and_port` for more
4210
:return: A smart server.
4212
from bzrlib.smart import medium, server
4214
smart_server = medium.SmartServerPipeStreamMedium(
4215
sys.stdin, sys.stdout, transport)
4217
host, port = self.get_host_and_port(port)
4218
smart_server = server.SmartTCPServer(
4219
transport, host=host, port=port)
4220
note('listening on port: %s' % smart_server.port)
4223
def run(self, port=None, inet=False, directory=None, allow_writes=False):
4224
from bzrlib.transport import get_transport
4225
from bzrlib.transport.chroot import ChrootServer
4802
def run(self, port=None, inet=False, directory=None, allow_writes=False,
4804
from bzrlib.transport import get_transport, transport_server_registry
4226
4805
if directory is None:
4227
4806
directory = os.getcwd()
4807
if protocol is None:
4808
protocol = transport_server_registry.get()
4809
host, port = self.get_host_and_port(port)
4228
4810
url = urlutils.local_path_to_url(directory)
4229
4811
if not allow_writes:
4230
4812
url = 'readonly+' + url
4231
chroot_server = ChrootServer(get_transport(url))
4232
chroot_server.setUp()
4233
t = get_transport(chroot_server.get_url())
4234
smart_server = self.get_smart_server(t, inet, port)
4235
self.run_smart_server(smart_server)
4813
transport = get_transport(url)
4814
protocol(transport, host, port, inet)
4238
4817
class cmd_join(Command):
4239
"""Combine a subtree into its containing tree.
4241
This command is for experimental use only. It requires the target tree
4242
to be in dirstate-with-subtree format, which cannot be converted into
4818
"""Combine a tree into its containing tree.
4820
This command requires the target tree to be in a rich-root format.
4245
4822
The TREE argument should be an independent tree, inside another tree, but
4246
4823
not part of it. (Such trees can be produced by "bzr split", but also by
4487
5059
help='Write merge directive to this file; '
4488
5060
'use - for stdout.',
5063
help='Refuse to send if there are uncommitted changes in'
5064
' the working tree, --no-strict disables the check.'),
4490
5065
Option('mail-to', help='Mail the request to this address.',
4494
RegistryOption.from_kwargs('format',
4495
'Use the specified output format.',
4496
**{'4': 'Bundle format 4, Merge Directive 2 (default)',
4497
'0.9': 'Bundle format 0.9, Merge Directive 1',})
5069
Option('body', help='Body for the email.', type=unicode),
5070
RegistryOption('format',
5071
help='Use the specified output format.',
5072
lazy_registry=('bzrlib.send', 'format_registry')),
4500
5075
def run(self, submit_branch=None, public_branch=None, no_bundle=False,
4501
5076
no_patch=False, revision=None, remember=False, output=None,
4502
format='4', mail_to=None, message=None, **kwargs):
4503
return self._run(submit_branch, revision, public_branch, remember,
4504
format, no_bundle, no_patch, output,
4505
kwargs.get('from', '.'), mail_to, message)
4507
def _run(self, submit_branch, revision, public_branch, remember, format,
4508
no_bundle, no_patch, output, from_, mail_to, message):
4509
from bzrlib.revision import NULL_REVISION
4510
branch = Branch.open_containing(from_)[0]
4512
outfile = cStringIO.StringIO()
4516
outfile = open(output, 'wb')
4517
# we may need to write data into branch's repository to calculate
4522
config = branch.get_config()
4524
mail_to = config.get_user_option('submit_to')
4525
mail_client = config.get_mail_client()
4526
if remember and submit_branch is None:
4527
raise errors.BzrCommandError(
4528
'--remember requires a branch to be specified.')
4529
stored_submit_branch = branch.get_submit_branch()
4530
remembered_submit_branch = None
4531
if submit_branch is None:
4532
submit_branch = stored_submit_branch
4533
remembered_submit_branch = "submit"
4535
if stored_submit_branch is None or remember:
4536
branch.set_submit_branch(submit_branch)
4537
if submit_branch is None:
4538
submit_branch = branch.get_parent()
4539
remembered_submit_branch = "parent"
4540
if submit_branch is None:
4541
raise errors.BzrCommandError('No submit branch known or'
4543
if remembered_submit_branch is not None:
4544
note('Using saved %s location "%s" to determine what '
4545
'changes to submit.', remembered_submit_branch,
4549
submit_config = Branch.open(submit_branch).get_config()
4550
mail_to = submit_config.get_user_option("child_submit_to")
4552
stored_public_branch = branch.get_public_branch()
4553
if public_branch is None:
4554
public_branch = stored_public_branch
4555
elif stored_public_branch is None or remember:
4556
branch.set_public_branch(public_branch)
4557
if no_bundle and public_branch is None:
4558
raise errors.BzrCommandError('No public branch specified or'
4560
base_revision_id = None
4562
if revision is not None:
4563
if len(revision) > 2:
4564
raise errors.BzrCommandError('bzr send takes '
4565
'at most two one revision identifiers')
4566
revision_id = revision[-1].as_revision_id(branch)
4567
if len(revision) == 2:
4568
base_revision_id = revision[0].as_revision_id(branch)
4569
if revision_id is None:
4570
revision_id = branch.last_revision()
4571
if revision_id == NULL_REVISION:
4572
raise errors.BzrCommandError('No revisions to submit.')
4574
directive = merge_directive.MergeDirective2.from_objects(
4575
branch.repository, revision_id, time.time(),
4576
osutils.local_time_offset(), submit_branch,
4577
public_branch=public_branch, include_patch=not no_patch,
4578
include_bundle=not no_bundle, message=message,
4579
base_revision_id=base_revision_id)
4580
elif format == '0.9':
4583
patch_type = 'bundle'
4585
raise errors.BzrCommandError('Format 0.9 does not'
4586
' permit bundle with no patch')
4592
directive = merge_directive.MergeDirective.from_objects(
4593
branch.repository, revision_id, time.time(),
4594
osutils.local_time_offset(), submit_branch,
4595
public_branch=public_branch, patch_type=patch_type,
4598
outfile.writelines(directive.to_lines())
4600
subject = '[MERGE] '
4601
if message is not None:
4604
revision = branch.repository.get_revision(revision_id)
4605
subject += revision.get_summary()
4606
basename = directive.get_disk_name(branch)
4607
mail_client.compose_merge_request(mail_to, subject,
4608
outfile.getvalue(), basename)
5077
format=None, mail_to=None, message=None, body=None,
5078
strict=None, **kwargs):
5079
from bzrlib.send import send
5080
return send(submit_branch, revision, public_branch, remember,
5081
format, no_bundle, no_patch, output,
5082
kwargs.get('from', '.'), mail_to, message, body,
4615
5087
class cmd_bundle_revisions(cmd_send):
4617
5088
"""Create a merge-directive for submitting changes.
4619
5090
A merge directive provides many things needed for requesting merges:
4830
5309
_see_also = ['branches', 'checkouts', 'standalone-trees', 'working-trees']
4831
5310
takes_args = ['location?']
4832
takes_options = [RegistryOption.from_kwargs('target_type',
4833
title='Target type',
4834
help='The type to reconfigure the directory to.',
4835
value_switches=True, enum_switch=False,
4836
branch='Reconfigure to be an unbound branch '
4837
'with no working tree.',
4838
tree='Reconfigure to be an unbound branch '
4839
'with a working tree.',
4840
checkout='Reconfigure to be a bound branch '
4841
'with a working tree.',
4842
lightweight_checkout='Reconfigure to be a lightweight'
4843
' checkout (with no local history).',
4844
standalone='Reconfigure to be a standalone branch '
4845
'(i.e. stop using shared repository).',
4846
use_shared='Reconfigure to use a shared repository.'),
4847
Option('bind-to', help='Branch to bind checkout to.',
4850
help='Perform reconfiguration even if local changes'
5312
RegistryOption.from_kwargs(
5314
title='Target type',
5315
help='The type to reconfigure the directory to.',
5316
value_switches=True, enum_switch=False,
5317
branch='Reconfigure to be an unbound branch with no working tree.',
5318
tree='Reconfigure to be an unbound branch with a working tree.',
5319
checkout='Reconfigure to be a bound branch with a working tree.',
5320
lightweight_checkout='Reconfigure to be a lightweight'
5321
' checkout (with no local history).',
5322
standalone='Reconfigure to be a standalone branch '
5323
'(i.e. stop using shared repository).',
5324
use_shared='Reconfigure to use a shared repository.',
5325
with_trees='Reconfigure repository to create '
5326
'working trees on branches by default.',
5327
with_no_trees='Reconfigure repository to not create '
5328
'working trees on branches by default.'
5330
Option('bind-to', help='Branch to bind checkout to.', type=str),
5332
help='Perform reconfiguration even if local changes'
5334
Option('stacked-on',
5335
help='Reconfigure a branch to be stacked on another branch.',
5339
help='Reconfigure a branch to be unstacked. This '
5340
'may require copying substantial data into it.',
4854
def run(self, location=None, target_type=None, bind_to=None, force=False):
5344
def run(self, location=None, target_type=None, bind_to=None, force=False,
4855
5347
directory = bzrdir.BzrDir.open(location)
5348
if stacked_on and unstacked:
5349
raise BzrCommandError("Can't use both --stacked-on and --unstacked")
5350
elif stacked_on is not None:
5351
reconfigure.ReconfigureStackedOn().apply(directory, stacked_on)
5353
reconfigure.ReconfigureUnstacked().apply(directory)
5354
# At the moment you can use --stacked-on and a different
5355
# reconfiguration shape at the same time; there seems no good reason
4856
5357
if target_type is None:
4857
raise errors.BzrCommandError('No target configuration specified')
5358
if stacked_on or unstacked:
5361
raise errors.BzrCommandError('No target configuration '
4858
5363
elif target_type == 'branch':
4859
5364
reconfiguration = reconfigure.Reconfigure.to_branch(directory)
4860
5365
elif target_type == 'tree':
4861
5366
reconfiguration = reconfigure.Reconfigure.to_tree(directory)
4862
5367
elif target_type == 'checkout':
4863
reconfiguration = reconfigure.Reconfigure.to_checkout(directory,
5368
reconfiguration = reconfigure.Reconfigure.to_checkout(
4865
5370
elif target_type == 'lightweight-checkout':
4866
5371
reconfiguration = reconfigure.Reconfigure.to_lightweight_checkout(
4867
5372
directory, bind_to)
4891
5402
/path/to/newbranch.
4893
5404
Bound branches use the nickname of its master branch unless it is set
4894
locally, in which case switching will update the the local nickname to be
5405
locally, in which case switching will update the local nickname to be
4895
5406
that of the master.
4898
5409
takes_args = ['to_location?']
4899
5410
takes_options = [Option('force',
4900
5411
help='Switch even if local commits will be lost.'),
5413
Option('create-branch', short_name='b',
5414
help='Create the target branch from this one before'
5415
' switching to it.'),
4904
def run(self, to_location=None, force=False, revision=None):
5418
def run(self, to_location=None, force=False, create_branch=False,
4905
5420
from bzrlib import switch
4906
5421
tree_location = '.'
4907
5422
revision = _get_one_revision('switch', revision)
4908
5423
control_dir = bzrdir.BzrDir.open_containing(tree_location)[0]
4909
branch = control_dir.open_branch()
4910
5424
if to_location is None:
4911
5425
if revision is None:
4912
5426
raise errors.BzrCommandError('You must supply either a'
4913
5427
' revision or a location')
4914
5428
to_location = '.'
4916
to_branch = Branch.open(to_location)
5430
branch = control_dir.open_branch()
5431
had_explicit_nick = branch.get_config().has_explicit_nickname()
4917
5432
except errors.NotBranchError:
4918
this_branch = control_dir.open_branch()
4919
# This may be a heavy checkout, where we want the master branch
4920
this_url = this_branch.get_bound_location()
4921
# If not, use a local sibling
4922
if this_url is None:
4923
this_url = this_branch.base
4924
to_branch = Branch.open(
4925
urlutils.join(this_url, '..', to_location))
5434
had_explicit_nick = False
5437
raise errors.BzrCommandError('cannot create branch without'
5439
to_location = directory_service.directories.dereference(
5441
if '/' not in to_location and '\\' not in to_location:
5442
# This path is meant to be relative to the existing branch
5443
this_url = self._get_branch_location(control_dir)
5444
to_location = urlutils.join(this_url, '..', to_location)
5445
to_branch = branch.bzrdir.sprout(to_location,
5446
possible_transports=[branch.bzrdir.root_transport],
5447
source_branch=branch).open_branch()
5449
# from_branch = control_dir.open_branch()
5450
# except errors.NotBranchError:
5451
# raise BzrCommandError('Cannot create a branch from this'
5452
# ' location when we cannot open this branch')
5453
# from_branch.bzrdir.sprout(
5457
to_branch = Branch.open(to_location)
5458
except errors.NotBranchError:
5459
this_url = self._get_branch_location(control_dir)
5460
to_branch = Branch.open(
5461
urlutils.join(this_url, '..', to_location))
4926
5462
if revision is not None:
4927
5463
revision = revision.as_revision_id(to_branch)
4928
switch.switch(control_dir, to_branch, force, revision)
4929
if branch.get_config().has_explicit_nickname():
5464
switch.switch(control_dir, to_branch, force, revision_id=revision)
5465
if had_explicit_nick:
4930
5466
branch = control_dir.open_branch() #get the new branch!
4931
5467
branch.nick = to_branch.nick
4932
5468
note('Switched to branch: %s',
4933
5469
urlutils.unescape_for_display(to_branch.base, 'utf-8'))
5471
def _get_branch_location(self, control_dir):
5472
"""Return location of branch for this control dir."""
5474
this_branch = control_dir.open_branch()
5475
# This may be a heavy checkout, where we want the master branch
5476
master_location = this_branch.get_bound_location()
5477
if master_location is not None:
5478
return master_location
5479
# If not, use a local sibling
5480
return this_branch.base
5481
except errors.NotBranchError:
5482
format = control_dir.find_branch_format()
5483
if getattr(format, 'get_reference', None) is not None:
5484
return format.get_reference(control_dir)
5486
return control_dir.root_transport.base
5489
class cmd_view(Command):
5490
"""Manage filtered views.
5492
Views provide a mask over the tree so that users can focus on
5493
a subset of a tree when doing their work. After creating a view,
5494
commands that support a list of files - status, diff, commit, etc -
5495
effectively have that list of files implicitly given each time.
5496
An explicit list of files can still be given but those files
5497
must be within the current view.
5499
In most cases, a view has a short life-span: it is created to make
5500
a selected change and is deleted once that change is committed.
5501
At other times, you may wish to create one or more named views
5502
and switch between them.
5504
To disable the current view without deleting it, you can switch to
5505
the pseudo view called ``off``. This can be useful when you need
5506
to see the whole tree for an operation or two (e.g. merge) but
5507
want to switch back to your view after that.
5510
To define the current view::
5512
bzr view file1 dir1 ...
5514
To list the current view::
5518
To delete the current view::
5522
To disable the current view without deleting it::
5524
bzr view --switch off
5526
To define a named view and switch to it::
5528
bzr view --name view-name file1 dir1 ...
5530
To list a named view::
5532
bzr view --name view-name
5534
To delete a named view::
5536
bzr view --name view-name --delete
5538
To switch to a named view::
5540
bzr view --switch view-name
5542
To list all views defined::
5546
To delete all views::
5548
bzr view --delete --all
5552
takes_args = ['file*']
5555
help='Apply list or delete action to all views.',
5558
help='Delete the view.',
5561
help='Name of the view to define, list or delete.',
5565
help='Name of the view to switch to.',
5570
def run(self, file_list,
5576
tree, file_list = tree_files(file_list, apply_view=False)
5577
current_view, view_dict = tree.views.get_view_info()
5582
raise errors.BzrCommandError(
5583
"Both --delete and a file list specified")
5585
raise errors.BzrCommandError(
5586
"Both --delete and --switch specified")
5588
tree.views.set_view_info(None, {})
5589
self.outf.write("Deleted all views.\n")
5591
raise errors.BzrCommandError("No current view to delete")
5593
tree.views.delete_view(name)
5594
self.outf.write("Deleted '%s' view.\n" % name)
5597
raise errors.BzrCommandError(
5598
"Both --switch and a file list specified")
5600
raise errors.BzrCommandError(
5601
"Both --switch and --all specified")
5602
elif switch == 'off':
5603
if current_view is None:
5604
raise errors.BzrCommandError("No current view to disable")
5605
tree.views.set_view_info(None, view_dict)
5606
self.outf.write("Disabled '%s' view.\n" % (current_view))
5608
tree.views.set_view_info(switch, view_dict)
5609
view_str = views.view_display_str(tree.views.lookup_view())
5610
self.outf.write("Using '%s' view: %s\n" % (switch, view_str))
5613
self.outf.write('Views defined:\n')
5614
for view in sorted(view_dict):
5615
if view == current_view:
5619
view_str = views.view_display_str(view_dict[view])
5620
self.outf.write('%s %-20s %s\n' % (active, view, view_str))
5622
self.outf.write('No views defined.\n')
5625
# No name given and no current view set
5628
raise errors.BzrCommandError(
5629
"Cannot change the 'off' pseudo view")
5630
tree.views.set_view(name, sorted(file_list))
5631
view_str = views.view_display_str(tree.views.lookup_view())
5632
self.outf.write("Using '%s' view: %s\n" % (name, view_str))
5636
# No name given and no current view set
5637
self.outf.write('No current view.\n')
5639
view_str = views.view_display_str(tree.views.lookup_view(name))
5640
self.outf.write("'%s' view is: %s\n" % (name, view_str))
4936
5643
class cmd_hooks(Command):
4937
"""Show a branch's currently registered hooks.
4941
takes_args = ['path?']
4943
def run(self, path=None):
4946
branch_hooks = Branch.open(path).hooks
4947
for hook_type in branch_hooks:
4948
hooks = branch_hooks[hook_type]
4949
self.outf.write("%s:\n" % (hook_type,))
4952
self.outf.write(" %s\n" %
4953
(branch_hooks.get_hook_name(hook),))
4955
self.outf.write(" <no hooks installed>\n")
5649
for hook_key in sorted(hooks.known_hooks.keys()):
5650
some_hooks = hooks.known_hooks_key_to_object(hook_key)
5651
self.outf.write("%s:\n" % type(some_hooks).__name__)
5652
for hook_name, hook_point in sorted(some_hooks.items()):
5653
self.outf.write(" %s:\n" % (hook_name,))
5654
found_hooks = list(hook_point)
5656
for hook in found_hooks:
5657
self.outf.write(" %s\n" %
5658
(some_hooks.get_hook_name(hook),))
5660
self.outf.write(" <no hooks installed>\n")
4958
5663
class cmd_shelve(Command):
4989
5696
value_switches=True, enum_switch=False),
4991
5698
Option('list', help='List shelved changes.'),
5700
help='Destroy removed changes instead of shelving them.'),
4993
5702
_see_also = ['unshelve']
4995
5704
def run(self, revision=None, all=False, file_list=None, message=None,
4996
writer=None, list=False):
5705
writer=None, list=False, destroy=False):
4998
5707
return self.run_for_list()
4999
5708
from bzrlib.shelf_ui import Shelver
5000
5709
if writer is None:
5001
5710
writer = bzrlib.option.diff_writer_registry.get()
5003
Shelver.from_args(writer(sys.stdout), revision, all, file_list,
5712
shelver = Shelver.from_args(writer(sys.stdout), revision, all,
5713
file_list, message, destroy=destroy)
5005
5718
except errors.UserAbort:
5008
5721
def run_for_list(self):
5009
5722
tree = WorkingTree.open_containing('.')[0]
5010
5723
tree.lock_read()
5012
manager = tree.get_shelf_manager()
5013
shelves = manager.active_shelves()
5014
if len(shelves) == 0:
5015
note('No shelved changes.')
5017
for shelf_id in reversed(shelves):
5018
message = manager.get_metadata(shelf_id).get('message')
5020
message = '<no message>'
5021
self.outf.write('%3d: %s\n' % (shelf_id, message))
5724
self.add_cleanup(tree.unlock)
5725
manager = tree.get_shelf_manager()
5726
shelves = manager.active_shelves()
5727
if len(shelves) == 0:
5728
note('No shelved changes.')
5730
for shelf_id in reversed(shelves):
5731
message = manager.get_metadata(shelf_id).get('message')
5733
message = '<no message>'
5734
self.outf.write('%3d: %s\n' % (shelf_id, message))
5027
5738
class cmd_unshelve(Command):
5028
5739
"""Restore shelved changes.
5030
5741
By default, the most recently shelved changes are restored. However if you
5031
specify a patch by name those changes will be restored instead. This
5032
works best when the changes don't depend on each other.
5742
specify a shelf by id those changes will be restored instead. This works
5743
best when the changes don't depend on each other.
5035
5746
takes_args = ['shelf_id?']
5039
5750
enum_switch=False, value_switches=True,
5040
5751
apply="Apply changes and remove from the shelf.",
5041
5752
dry_run="Show changes, but do not apply or remove them.",
5042
delete_only="Delete changes without applying them."
5753
delete_only="Delete changes without applying them.",
5754
keep="Apply changes but don't delete them.",
5045
5757
_see_also = ['shelve']
5047
5759
def run(self, shelf_id=None, action='apply'):
5048
5760
from bzrlib.shelf_ui import Unshelver
5049
Unshelver.from_args(shelf_id, action).run()
5052
def _create_prefix(cur_transport):
5053
needed = [cur_transport]
5054
# Recurse upwards until we can create a directory successfully
5056
new_transport = cur_transport.clone('..')
5057
if new_transport.base == cur_transport.base:
5058
raise errors.BzrCommandError(
5059
"Failed to create path prefix for %s."
5060
% cur_transport.base)
5761
unshelver = Unshelver.from_args(shelf_id, action)
5062
new_transport.mkdir('.')
5063
except errors.NoSuchFile:
5064
needed.append(new_transport)
5065
cur_transport = new_transport
5765
unshelver.tree.unlock()
5768
class cmd_clean_tree(Command):
5769
"""Remove unwanted files from working tree.
5771
By default, only unknown files, not ignored files, are deleted. Versioned
5772
files are never deleted.
5774
Another class is 'detritus', which includes files emitted by bzr during
5775
normal operations and selftests. (The value of these files decreases with
5778
If no options are specified, unknown files are deleted. Otherwise, option
5779
flags are respected, and may be combined.
5781
To check what clean-tree will do, use --dry-run.
5783
takes_options = [Option('ignored', help='Delete all ignored files.'),
5784
Option('detritus', help='Delete conflict files, merge'
5785
' backups, and failed selftest dirs.'),
5787
help='Delete files unknown to bzr (default).'),
5788
Option('dry-run', help='Show files to delete instead of'
5790
Option('force', help='Do not prompt before deleting.')]
5791
def run(self, unknown=False, ignored=False, detritus=False, dry_run=False,
5793
from bzrlib.clean_tree import clean_tree
5794
if not (unknown or ignored or detritus):
5798
clean_tree('.', unknown=unknown, ignored=ignored, detritus=detritus,
5799
dry_run=dry_run, no_prompt=force)
5802
class cmd_reference(Command):
5803
"""list, view and set branch locations for nested trees.
5805
If no arguments are provided, lists the branch locations for nested trees.
5806
If one argument is provided, display the branch location for that tree.
5807
If two arguments are provided, set the branch location for that tree.
5812
takes_args = ['path?', 'location?']
5814
def run(self, path=None, location=None):
5816
if path is not None:
5818
tree, branch, relpath =(
5819
bzrdir.BzrDir.open_containing_tree_or_branch(branchdir))
5820
if path is not None:
5823
tree = branch.basis_tree()
5825
info = branch._get_all_reference_info().iteritems()
5826
self._display_reference_info(tree, branch, info)
5068
# Now we only need to create child directories
5070
cur_transport = needed.pop()
5071
cur_transport.ensure_base()
5828
file_id = tree.path2id(path)
5830
raise errors.NotVersionedError(path)
5831
if location is None:
5832
info = [(file_id, branch.get_reference_info(file_id))]
5833
self._display_reference_info(tree, branch, info)
5835
branch.set_reference_info(file_id, path, location)
5837
def _display_reference_info(self, tree, branch, info):
5839
for file_id, (path, location) in info:
5841
path = tree.id2path(file_id)
5842
except errors.NoSuchId:
5844
ref_list.append((path, location))
5845
for path, location in sorted(ref_list):
5846
self.outf.write('%s %s\n' % (path, location))
5074
5849
# these get imported and then picked up by the scan for cmd_*
5075
5850
# TODO: Some more consistent way to split command definitions across files;
5076
# we do need to load at least some information about them to know of
5851
# we do need to load at least some information about them to know of
5077
5852
# aliases. ideally we would avoid loading the implementation until the
5078
5853
# details were needed.
5079
5854
from bzrlib.cmd_version_info import cmd_version_info