542
540
wt = WorkingTree.open_containing(directory)[0]
545
self.add_cleanup(wt.unlock)
546
543
except (errors.NoWorkingTree, errors.NotLocalUrl):
548
545
b = Branch.open_containing(directory)[0]
550
self.add_cleanup(b.unlock)
552
if revision is not None:
553
revision_ids.extend(rev.as_revision_id(b) for rev in revision)
554
if revision_info_list is not None:
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())
549
if revision is not None:
550
revision_ids.extend(rev.as_revision_id(b) for rev in revision)
551
if revision_info_list is not None:
552
for rev_str in revision_info_list:
553
rev_spec = RevisionSpec.from_string(rev_str)
554
revision_ids.append(rev_spec.as_revision_id(b))
555
# No arguments supplied, default to the last revision
556
if len(revision_ids) == 0:
559
raise errors.NoWorkingTree(directory)
560
revision_ids.append(wt.last_revision())
562
revision_ids.append(b.last_revision())
566
for revision_id in revision_ids:
568
dotted_revno = b.revision_id_to_dotted_revno(revision_id)
569
revno = '.'.join(str(i) for i in dotted_revno)
570
except errors.NoSuchRevision:
572
maxlen = max(maxlen, len(revno))
573
revinfos.append([revno, revision_id])
565
revision_ids.append(b.last_revision())
569
for revision_id in revision_ids:
571
dotted_revno = b.revision_id_to_dotted_revno(revision_id)
572
revno = '.'.join(str(i) for i in dotted_revno)
573
except errors.NoSuchRevision:
575
maxlen = max(maxlen, len(revno))
576
revinfos.append([revno, revision_id])
579
580
for ri in revinfos:
580
581
self.outf.write('%*s %s\n' % (maxlen, ri[0], ri[1]))
727
730
revision = _get_one_revision('inventory', revision)
728
731
work_tree, file_list = tree_files(file_list)
729
732
work_tree.lock_read()
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()
734
if revision is not None:
735
tree = revision.as_tree(work_tree.branch)
737
extra_trees = [work_tree]
743
if file_list is not None:
744
file_ids = tree.paths2ids(file_list, trees=extra_trees,
745
require_versioned=True)
746
# find_ids_across_trees may include some paths that don't
748
entries = sorted((tree.id2path(file_id), tree.inventory[file_id])
749
for file_id in file_ids if file_id in tree)
751
entries = tree.inventory.entries()
754
if tree is not work_tree:
752
757
for path, entry in entries:
753
758
if kind and kind != entry.kind:
892
900
dest = osutils.pathjoin(dest_parent, dest_tail)
893
901
mutter("attempting to move %s => %s", src, dest)
894
902
tree.rename_one(src, dest, after=after)
896
self.outf.write("%s => %s\n" % (src, dest))
903
self.outf.write("%s => %s\n" % (src, dest))
899
906
class cmd_pull(Command):
900
907
"""Turn this branch into a mirror of another branch.
902
By default, this command only works on branches that have not diverged.
903
Branches are considered diverged if the destination branch's most recent
904
commit is one that has not been merged (directly or indirectly) into the
909
This command only works on branches that have not diverged. Branches are
910
considered diverged if the destination branch's most recent commit is one
911
that has not been merged (directly or indirectly) into the parent.
907
913
If branches have diverged, you can use 'bzr merge' to integrate the changes
908
914
from one into the other. Once one branch has merged, the other should
909
915
be able to pull it again.
911
If you want to replace your local changes and just want your branch to
912
match the remote one, use pull --overwrite. This will work even if the two
913
branches have diverged.
917
If you want to forget your local changes and just update your branch to
918
match the remote one, use pull --overwrite.
915
920
If there is no default location set, the first pull will set it. After
916
921
that, you can omit the location to use the default. To change the
998
1003
if branch_from is not branch_to:
999
1004
branch_from.lock_read()
1000
self.add_cleanup(branch_from.unlock)
1001
if revision is not None:
1002
revision_id = revision.as_revision_id(branch_from)
1004
branch_to.lock_write()
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)
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,
1006
if revision is not None:
1007
revision_id = revision.as_revision_id(branch_from)
1009
branch_to.lock_write()
1011
if tree_to is not None:
1012
view_info = _get_view_info_for_change_reporter(tree_to)
1013
change_reporter = delta._ChangeReporter(
1014
unversioned_filter=tree_to.is_ignored,
1015
view_info=view_info)
1016
result = tree_to.pull(
1017
branch_from, overwrite, revision_id, change_reporter,
1018
possible_transports=possible_transports, local=local)
1020
result = branch_to.pull(
1021
branch_from, overwrite, revision_id, local=local)
1023
result.report(self.outf)
1024
if verbose and result.old_revid != result.new_revid:
1025
log.show_branch_change(
1026
branch_to, self.outf, result.old_revno,
1031
if branch_from is not branch_to:
1032
branch_from.unlock()
1025
1035
class cmd_push(Command):
1180
1190
' directory exists, but does not already'
1181
1191
' have a control directory. This flag will'
1182
1192
' allow branch to proceed.'),
1184
help="Bind new branch to from location."),
1186
1194
aliases = ['get', 'clone']
1188
1196
def run(self, from_location, to_location=None, revision=None,
1189
1197
hardlink=False, stacked=False, standalone=False, no_tree=False,
1190
use_existing_dir=False, switch=False, bind=False):
1198
use_existing_dir=False, switch=False):
1191
1199
from bzrlib import switch as _mod_switch
1192
1200
from bzrlib.tag import _merge_tags_if_possible
1193
1201
accelerator_tree, br_from = bzrdir.BzrDir.open_tree_or_branch(
1203
if (accelerator_tree is not None and
1204
accelerator_tree.supports_content_filtering()):
1205
accelerator_tree = None
1195
1206
revision = _get_one_revision('branch', revision)
1196
1207
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)
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)
1209
if revision is not None:
1210
revision_id = revision.as_revision_id(br_from)
1216
bzrdir.BzrDir.open_from_transport(to_transport)
1217
except errors.NotBranchError:
1212
# FIXME - wt.last_revision, fallback to branch, fall back to
1213
# None or perhaps NULL_REVISION to mean copy nothing
1215
revision_id = br_from.last_revision()
1216
if to_location is None:
1217
to_location = urlutils.derive_to_location(from_location)
1218
to_transport = transport.get_transport(to_location)
1220
to_transport.mkdir('.')
1221
except errors.FileExists:
1222
if not use_existing_dir:
1223
raise errors.BzrCommandError('Target directory "%s" '
1224
'already exists.' % to_location)
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'))
1227
bzrdir.BzrDir.open_from_transport(to_transport)
1228
except errors.NotBranchError:
1231
raise errors.AlreadyBranchError(to_location)
1232
except errors.NoSuchFile:
1233
raise errors.BzrCommandError('Parent of "%s" does not exist.'
1236
# preserve whatever source format we have.
1237
dir = br_from.bzrdir.sprout(to_transport.base, revision_id,
1238
possible_transports=[to_transport],
1239
accelerator_tree=accelerator_tree,
1240
hardlink=hardlink, stacked=stacked,
1241
force_new_repo=standalone,
1242
create_tree_if_local=not no_tree,
1243
source_branch=br_from)
1244
branch = dir.open_branch()
1245
except errors.NoSuchRevision:
1246
to_transport.delete_tree('.')
1247
msg = "The branch %s has no revision %s." % (from_location,
1249
raise errors.BzrCommandError(msg)
1250
_merge_tags_if_possible(br_from, branch)
1251
# If the source branch is stacked, the new branch may
1252
# be stacked whether we asked for that explicitly or not.
1253
# We therefore need a try/except here and not just 'if stacked:'
1255
note('Created new stacked branch referring to %s.' %
1256
branch.get_stacked_on_url())
1257
except (errors.NotStacked, errors.UnstackableBranchFormat,
1258
errors.UnstackableRepositoryFormat), e:
1259
note('Branched %d revision(s).' % branch.revno())
1261
# Switch to the new branch
1262
wt, _ = WorkingTree.open_containing('.')
1263
_mod_switch.switch(wt.bzrdir, branch)
1264
note('Switched to branch: %s',
1265
urlutils.unescape_for_display(branch.base, 'utf-8'))
1262
1270
class cmd_checkout(Command):
1341
1349
def run(self, dir=u'.'):
1342
1350
tree = WorkingTree.open_containing(dir)[0]
1343
1351
tree.lock_read()
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))
1353
new_inv = tree.inventory
1354
old_tree = tree.basis_tree()
1355
old_tree.lock_read()
1357
old_inv = old_tree.inventory
1359
iterator = tree.iter_changes(old_tree, include_unchanged=True)
1360
for f, paths, c, v, p, n, k, e in iterator:
1361
if paths[0] == paths[1]:
1365
renames.append(paths)
1367
for old_name, new_name in renames:
1368
self.outf.write("%s => %s\n" % (old_name, new_name))
1363
1375
class cmd_update(Command):
1370
1382
If you want to discard your local changes, you can just do a
1371
1383
'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.
1377
1386
_see_also = ['pull', 'working-trees', 'status-flags']
1378
1387
takes_args = ['dir?']
1379
takes_options = ['revision']
1380
1388
aliases = ['up']
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")
1390
def run(self, dir='.'):
1386
1391
tree = WorkingTree.open_containing(dir)[0]
1387
branch = tree.branch
1388
1392
possible_transports = []
1389
master = branch.get_master_branch(
1393
master = tree.branch.get_master_branch(
1390
1394
possible_transports=possible_transports)
1391
1395
if master is not None:
1392
1396
tree.lock_write()
1393
branch_location = master.base
1395
1398
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)
1400
existing_pending_merges = tree.get_parent_ids()[1:]
1401
last_rev = _mod_revision.ensure_null(tree.last_revision())
1402
if last_rev == _mod_revision.ensure_null(
1403
tree.branch.last_revision()):
1404
# may be up to date, check master too.
1405
if master is None or last_rev == _mod_revision.ensure_null(
1406
master.last_revision()):
1407
revno = tree.branch.revision_id_to_revno(last_rev)
1408
note("Tree is up to date at revision %d." % (revno,))
1410
view_info = _get_view_info_for_change_reporter(tree)
1423
1411
conflicts = tree.update(
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'.")
1412
delta._ChangeReporter(unversioned_filter=tree.is_ignored,
1413
view_info=view_info), possible_transports=possible_transports)
1414
revno = tree.branch.revision_id_to_revno(
1415
_mod_revision.ensure_null(tree.last_revision()))
1416
note('Updated to revision %d.' % (revno,))
1417
if tree.get_parent_ids()[1:] != existing_pending_merges:
1418
note('Your local commits will now show as pending merges with '
1419
"'bzr status', and can be committed with 'bzr commit'.")
1447
1428
class cmd_info(Command):
1518
1499
file_list = [f for f in file_list]
1520
1501
tree.lock_write()
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')
1503
# Heuristics should probably all move into tree.remove_smart or
1506
added = tree.changes_from(tree.basis_tree(),
1507
specific_files=file_list).added
1508
file_list = sorted([f[0] for f in added], reverse=True)
1509
if len(file_list) == 0:
1510
raise errors.BzrCommandError('No matching files.')
1511
elif file_list is None:
1512
# missing files show up in iter_changes(basis) as
1513
# versioned-with-no-kind.
1515
for change in tree.iter_changes(tree.basis_tree()):
1516
# Find paths in the working tree that have no kind:
1517
if change[1][1] is not None and change[6][1] is None:
1518
missing.append(change[1][1])
1519
file_list = sorted(missing, reverse=True)
1520
file_deletion_strategy = 'keep'
1521
tree.remove(file_list, verbose=verbose, to_file=self.outf,
1522
keep_files=file_deletion_strategy=='keep',
1523
force=file_deletion_strategy=='force')
1545
1528
class cmd_file_id(Command):
1767
1750
class cmd_init_repository(Command):
1768
"""Create a shared repository for branches to share storage space.
1751
"""Create a shared repository to hold branches.
1770
1753
New branches created under the repository directory will store their
1771
revisions in the repository, not in the branch directory. For branches
1772
with shared history, this reduces the amount of storage needed and
1773
speeds up the creation of new branches.
1754
revisions in the repository, not in the branch directory.
1775
If the --no-trees option is given then the branches in the repository
1776
will not have working trees by default. They will still exist as
1777
directories on disk, but they will not have separate copies of the
1778
files at a certain revision. This can be useful for repositories that
1779
store branches which are interacted with through checkouts or remote
1780
branches, such as on a server.
1756
If the --no-trees option is used then the branches in the repository
1757
will not have working trees by default.
1783
Create a shared repository holding just branches::
1760
Create a shared repositories holding just branches::
1785
1762
bzr init-repo --no-trees repo
1786
1763
bzr init repo/trunk
2303
2277
filter_by_dir = False
2305
# find the file ids to log and check for directory filtering
2306
b, file_info_list, rev1, rev2 = _get_info_for_log_files(
2307
revision, file_list)
2308
self.add_cleanup(b.unlock)
2309
for relpath, file_id, kind in file_info_list:
2311
raise errors.BzrCommandError(
2312
"Path unknown at end or start of revision range: %s" %
2314
# If the relpath is the top of the tree, we log everything
2281
# find the file ids to log and check for directory filtering
2282
b, file_info_list, rev1, rev2 = _get_info_for_log_files(
2283
revision, file_list)
2284
for relpath, file_id, kind in file_info_list:
2286
raise errors.BzrCommandError(
2287
"Path unknown at end or start of revision range: %s" %
2289
# If the relpath is the top of the tree, we log everything
2294
file_ids.append(file_id)
2295
filter_by_dir = filter_by_dir or (
2296
kind in ['directory', 'tree-reference'])
2299
# FIXME ? log the current subdir only RBC 20060203
2300
if revision is not None \
2301
and len(revision) > 0 and revision[0].get_branch():
2302
location = revision[0].get_branch()
2319
file_ids.append(file_id)
2320
filter_by_dir = filter_by_dir or (
2321
kind in ['directory', 'tree-reference'])
2324
# FIXME ? log the current subdir only RBC 20060203
2325
if revision is not None \
2326
and len(revision) > 0 and revision[0].get_branch():
2327
location = revision[0].get_branch()
2330
dir, relpath = bzrdir.BzrDir.open_containing(location)
2331
b = dir.open_branch()
2333
self.add_cleanup(b.unlock)
2334
rev1, rev2 = _get_revision_range(revision, b, self.name())
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)
2305
dir, relpath = bzrdir.BzrDir.open_containing(location)
2306
b = dir.open_branch()
2308
rev1, rev2 = _get_revision_range(revision, b, self.name())
2310
# Decide on the type of delta & diff filtering to use
2311
# TODO: add an --all-files option to make this configurable & consistent
2319
diff_type = 'partial'
2323
# Build the log formatter
2324
if log_format is None:
2325
log_format = log.log_formatter_registry.get_default(b)
2326
lf = log_format(show_ids=show_ids, to_file=self.outf,
2327
show_timezone=timezone,
2328
delta_format=get_verbosity_level(),
2330
show_advice=levels is None)
2332
# Choose the algorithm for doing the logging. It's annoying
2333
# having multiple code paths like this but necessary until
2334
# the underlying repository format is faster at generating
2335
# deltas or can provide everything we need from the indices.
2336
# The default algorithm - match-using-deltas - works for
2337
# multiple files and directories and is faster for small
2338
# amounts of history (200 revisions say). However, it's too
2339
# slow for logging a single file in a repository with deep
2340
# history, i.e. > 10K revisions. In the spirit of "do no
2341
# evil when adding features", we continue to use the
2342
# original algorithm - per-file-graph - for the "single
2343
# file that isn't a directory without showing a delta" case.
2344
partial_history = revision and b.repository._format.supports_chks
2345
match_using_deltas = (len(file_ids) != 1 or filter_by_dir
2346
or delta_type or partial_history)
2348
# Build the LogRequest and execute it
2349
if len(file_ids) == 0:
2351
rqst = make_log_request_dict(
2352
direction=direction, specific_fileids=file_ids,
2353
start_revision=rev1, end_revision=rev2, limit=limit,
2354
message_search=message, delta_type=delta_type,
2355
diff_type=diff_type, _match_using_deltas=match_using_deltas)
2356
Logger(b, rqst).show(lf)
2388
2362
def _get_revision_range(revisionspec_list, branch, command_name):
2531
2507
note("Ignoring files outside view. View is %s" % view_str)
2533
2509
tree.lock_read()
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:
2511
for fp, fc, fkind, fid, entry in tree.list_files(include_root=False,
2512
from_dir=relpath, recursive=recursive):
2513
# Apply additional masking
2514
if not all and not selection[fc]:
2516
if kind is not None and fkind != kind:
2521
fullpath = osutils.pathjoin(relpath, fp)
2524
views.check_path_in_view(tree, fullpath)
2525
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))
2530
fp = osutils.pathjoin(prefix, fp)
2531
kindch = entry.kind_character()
2532
outstring = fp + kindch
2533
ui.ui_factory.clear_term()
2535
outstring = '%-8s %s' % (fc, outstring)
2536
if show_ids and fid is not None:
2537
outstring = "%-50s %s" % (outstring, fid)
2578
2538
self.outf.write(outstring + '\n')
2540
self.outf.write(fp + '\0')
2543
self.outf.write(fid)
2544
self.outf.write('\0')
2552
self.outf.write('%-50s %s\n' % (outstring, my_id))
2554
self.outf.write(outstring + '\n')
2581
2559
class cmd_unknowns(Command):
3547
3474
verbose = not is_quiet()
3548
3475
# TODO: should possibly lock the history file...
3549
3476
benchfile = open(".perf_history", "at", buffering=1)
3550
self.add_cleanup(benchfile.close)
3552
3478
test_suite_factory = None
3553
3479
benchfile = None
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)
3481
selftest_kwargs = {"verbose": verbose,
3483
"stop_on_failure": one,
3484
"transport": transport,
3485
"test_suite_factory": test_suite_factory,
3486
"lsprof_timed": lsprof_timed,
3487
"lsprof_tests": lsprof_tests,
3488
"bench_history": benchfile,
3489
"matching_tests_first": first,
3490
"list_only": list_only,
3491
"random_seed": randomize,
3492
"exclude_pattern": exclude,
3494
"load_list": load_list,
3495
"debug_flags": debugflag,
3496
"starting_with": starting_with
3498
selftest_kwargs.update(self.additional_selftest_args)
3499
result = selftest(**selftest_kwargs)
3501
if benchfile is not None:
3573
3503
return int(not result)
3758
3680
view_info = _get_view_info_for_change_reporter(tree)
3759
3681
change_reporter = delta._ChangeReporter(
3760
3682
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:
3685
pb = ui.ui_factory.nested_progress_bar()
3686
cleanups.append(pb.finished)
3688
cleanups.append(tree.unlock)
3689
if location is not None:
3691
mergeable = bundle.read_mergeable_from_url(location,
3692
possible_transports=possible_transports)
3693
except errors.NotABundle:
3697
raise errors.BzrCommandError('Cannot use --uncommitted'
3698
' with bundles or merge directives.')
3700
if revision is not None:
3701
raise errors.BzrCommandError(
3702
'Cannot use -r with merge directives or bundles')
3703
merger, verified = _mod_merge.Merger.from_mergeable(tree,
3706
if merger is None and uncommitted:
3707
if revision is not None and len(revision) > 0:
3708
raise errors.BzrCommandError('Cannot use --uncommitted and'
3709
' --revision at the same time.')
3710
merger = self.get_merger_from_uncommitted(tree, location, pb,
3712
allow_pending = False
3715
merger, allow_pending = self._get_merger_from_branch(tree,
3716
location, revision, remember, possible_transports, pb)
3718
merger.merge_type = merge_type
3719
merger.reprocess = reprocess
3720
merger.show_base = show_base
3721
self.sanity_check_merger(merger)
3722
if (merger.base_rev_id == merger.other_rev_id and
3723
merger.other_rev_id is not None):
3724
note('Nothing to do.')
3727
if merger.interesting_files is not None:
3728
raise errors.BzrCommandError('Cannot pull individual files')
3729
if (merger.base_rev_id == tree.last_revision()):
3730
result = tree.pull(merger.other_branch, False,
3731
merger.other_rev_id)
3732
result.report(self.outf)
3734
if merger.this_basis is None:
3735
raise errors.BzrCommandError(
3736
"This branch has no commits."
3737
" (perhaps you would prefer 'bzr pull')")
3739
return self._do_preview(merger, cleanups)
3741
return self._do_interactive(merger, cleanups)
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, pb)
3787
allow_pending = False
3790
merger, allow_pending = self._get_merger_from_branch(tree,
3791
location, revision, remember, possible_transports, pb)
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)
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):
3743
return self._do_merge(merger, change_reporter, allow_pending,
3746
for cleanup in reversed(cleanups):
3749
def _get_preview(self, merger, cleanups):
3822
3750
tree_merger = merger.make_merger()
3823
3751
tt = tree_merger.make_preview_transform()
3824
self.add_cleanup(tt.finalize)
3752
cleanups.append(tt.finalize)
3825
3753
result_tree = tt.get_preview_tree()
3826
3754
return result_tree
3828
def _do_preview(self, merger):
3756
def _do_preview(self, merger, cleanups):
3829
3757
from bzrlib.diff import show_diff_trees
3830
result_tree = self._get_preview(merger)
3758
result_tree = self._get_preview(merger, cleanups)
3831
3759
show_diff_trees(merger.this_tree, result_tree, self.outf,
3832
3760
old_label='', new_label='')
4023
3950
merge_type = _mod_merge.Merge3Merger
4024
3951
tree, file_list = tree_files(file_list)
4025
3952
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":
3954
parents = tree.get_parent_ids()
3955
if len(parents) != 2:
3956
raise errors.BzrCommandError("Sorry, remerge only works after normal"
3957
" merges. Not cherrypicking or"
3959
repository = tree.branch.repository
3960
interesting_ids = None
3962
conflicts = tree.conflicts()
3963
if file_list is not None:
3964
interesting_ids = set()
3965
for filename in file_list:
3966
file_id = tree.path2id(filename)
3968
raise errors.NotVersionedError(filename)
3969
interesting_ids.add(file_id)
3970
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:
3973
for name, ie in tree.inventory.iter_entries(file_id):
3974
interesting_ids.add(ie.file_id)
3975
new_conflicts = conflicts.select_conflicts(tree, file_list)[0]
3977
# Remerge only supports resolving contents conflicts
3978
allowed_conflicts = ('text conflict', 'contents conflict')
3979
restore_files = [c.path for c in conflicts
3980
if c.typestring in allowed_conflicts]
3981
_mod_merge.transform_tree(tree, tree.basis_tree(), interesting_ids)
3982
tree.set_conflicts(ConflictList(new_conflicts))
3983
if file_list is not None:
3984
restore_files = file_list
3985
for filename in restore_files:
3987
restore(tree.abspath(filename))
3988
except errors.NotConflicted:
3990
# Disable pending merges, because the file texts we are remerging
3991
# have not had those merges performed. If we use the wrong parents
3992
# list, we imply that the working tree text has seen and rejected
3993
# all the changes from the other tree, when in fact those changes
3994
# have not yet been seen.
3995
pb = ui.ui_factory.nested_progress_bar()
3996
tree.set_parent_ids(parents[:1])
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
pb = ui.ui_factory.nested_progress_bar()
4069
tree.set_parent_ids(parents[:1])
4071
merger = _mod_merge.Merger.from_revision_ids(pb,
4073
merger.interesting_ids = interesting_ids
4074
merger.merge_type = merge_type
4075
merger.show_base = show_base
4076
merger.reprocess = reprocess
4077
conflicts = merger.do_merge()
3998
merger = _mod_merge.Merger.from_revision_ids(pb,
4000
merger.interesting_ids = interesting_ids
4001
merger.merge_type = merge_type
4002
merger.show_base = show_base
4003
merger.reprocess = reprocess
4004
conflicts = merger.do_merge()
4006
tree.set_parent_ids(parents)
4079
tree.set_parent_ids(parents)
4081
4010
if conflicts > 0:
4105
4034
name. If you name a directory, all the contents of that directory will be
4108
If you have newly added files since the target revision, they will be
4109
removed. If the files to be removed have been changed, backups will be
4110
created as above. Directories containing unknown files will not be
4037
Any files that have been newly added since that revision will be deleted,
4038
with a backup kept if appropriate. Directories containing unknown files
4039
will not be deleted.
4113
The working tree contains a list of revisions that have been merged but
4114
not yet committed. These revisions will be included as additional parents
4115
of the next commit. Normally, using revert clears that list as well as
4116
reverting the files. If any files are specified, revert leaves the list
4117
of uncommitted merges alone and reverts only the files. Use ``bzr revert
4118
.`` in the tree root to revert all files but keep the recorded merges,
4119
and ``bzr revert --forget-merges`` to clear the pending merge list without
4041
The working tree contains a list of pending merged revisions, which will
4042
be included as parents in the next commit. Normally, revert clears that
4043
list as well as reverting the files. If any files are specified, revert
4044
leaves the pending merge list alone and reverts only the files. Use "bzr
4045
revert ." in the tree root to revert all files but keep the merge record,
4046
and "bzr revert --forget-merges" to clear the pending merge list without
4120
4047
reverting any files.
4122
Using "bzr revert --forget-merges", it is possible to apply all of the
4123
changes from a branch in a single revision. To do this, perform the merge
4124
as desired. Then doing revert with the "--forget-merges" option will keep
4125
the content of the tree as it was, but it will clear the list of pending
4126
merges. The next commit will then contain all of the changes that are
4127
present in the other branch, but without any other parent revisions.
4128
Because this technique forgets where these changes originated, it may
4129
cause additional conflicts on later merges involving the same source and
4133
4050
_see_also = ['cat', 'export']
4304
4219
if remote_branch.base == local_branch.base:
4305
4220
remote_branch = local_branch
4307
local_branch.lock_read()
4308
self.add_cleanup(local_branch.unlock)
4309
4222
local_revid_range = _revision_range_to_revid_range(
4310
4223
_get_revision_range(my_revision, local_branch,
4313
remote_branch.lock_read()
4314
self.add_cleanup(remote_branch.unlock)
4315
4226
remote_revid_range = _revision_range_to_revid_range(
4316
4227
_get_revision_range(revision,
4317
4228
remote_branch, self.name()))
4319
local_extra, remote_extra = find_unmerged(
4320
local_branch, remote_branch, restrict,
4321
backward=not reverse,
4322
include_merges=include_merges,
4323
local_revid_range=local_revid_range,
4324
remote_revid_range=remote_revid_range)
4326
if log_format is None:
4327
registry = log.log_formatter_registry
4328
log_format = registry.get_default(local_branch)
4329
lf = log_format(to_file=self.outf,
4331
show_timezone='original')
4334
if local_extra and not theirs_only:
4335
message("You have %d extra revision(s):\n" %
4337
for revision in iter_log_revisions(local_extra,
4338
local_branch.repository,
4340
lf.log_revision(revision)
4341
printed_local = True
4344
printed_local = False
4346
if remote_extra and not mine_only:
4347
if printed_local is True:
4349
message("You are missing %d revision(s):\n" %
4351
for revision in iter_log_revisions(remote_extra,
4352
remote_branch.repository,
4354
lf.log_revision(revision)
4357
if mine_only and not local_extra:
4358
# We checked local, and found nothing extra
4359
message('This branch is up to date.\n')
4360
elif theirs_only and not remote_extra:
4361
# We checked remote, and found nothing extra
4362
message('Other branch is up to date.\n')
4363
elif not (mine_only or theirs_only or local_extra or
4365
# We checked both branches, and neither one had extra
4367
message("Branches are up to date.\n")
4230
local_branch.lock_read()
4232
remote_branch.lock_read()
4234
local_extra, remote_extra = find_unmerged(
4235
local_branch, remote_branch, restrict,
4236
backward=not reverse,
4237
include_merges=include_merges,
4238
local_revid_range=local_revid_range,
4239
remote_revid_range=remote_revid_range)
4241
if log_format is None:
4242
registry = log.log_formatter_registry
4243
log_format = registry.get_default(local_branch)
4244
lf = log_format(to_file=self.outf,
4246
show_timezone='original')
4249
if local_extra and not theirs_only:
4250
message("You have %d extra revision(s):\n" %
4252
for revision in iter_log_revisions(local_extra,
4253
local_branch.repository,
4255
lf.log_revision(revision)
4256
printed_local = True
4259
printed_local = False
4261
if remote_extra and not mine_only:
4262
if printed_local is True:
4264
message("You are missing %d revision(s):\n" %
4266
for revision in iter_log_revisions(remote_extra,
4267
remote_branch.repository,
4269
lf.log_revision(revision)
4272
if mine_only and not local_extra:
4273
# We checked local, and found nothing extra
4274
message('This branch is up to date.\n')
4275
elif theirs_only and not remote_extra:
4276
# We checked remote, and found nothing extra
4277
message('Other branch is up to date.\n')
4278
elif not (mine_only or theirs_only or local_extra or
4280
# We checked both branches, and neither one had extra
4282
message("Branches are up to date.\n")
4284
remote_branch.unlock()
4286
local_branch.unlock()
4369
4287
if not status_code and parent is None and other_branch is not None:
4370
4288
local_branch.lock_write()
4371
self.add_cleanup(local_branch.unlock)
4372
# handle race conditions - a parent might be set while we run.
4373
if local_branch.get_parent() is None:
4374
local_branch.set_parent(remote_branch.base)
4290
# handle race conditions - a parent might be set while we run.
4291
if local_branch.get_parent() is None:
4292
local_branch.set_parent(remote_branch.base)
4294
local_branch.unlock()
4375
4295
return status_code
4497
4419
bzrdir.BzrDir.open_containing_tree_or_branch(filename)
4498
4420
if wt is not None:
4500
self.add_cleanup(wt.unlock)
4502
4423
branch.lock_read()
4503
self.add_cleanup(branch.unlock)
4504
tree = _get_one_revision_tree('annotate', revision, branch=branch)
4506
self.add_cleanup(tree.unlock)
4508
file_id = wt.path2id(relpath)
4510
file_id = tree.path2id(relpath)
4512
raise errors.NotVersionedError(filename)
4513
file_version = tree.inventory[file_id].revision
4514
if wt is not None and revision is None:
4515
# If there is a tree and we're not annotating historical
4516
# versions, annotate the working tree's content.
4517
annotate_file_tree(wt, file_id, self.outf, long, all,
4520
annotate_file(branch, file_version, file_id, long, all, self.outf,
4425
tree = _get_one_revision_tree('annotate', revision, branch=branch)
4427
file_id = wt.path2id(relpath)
4429
file_id = tree.path2id(relpath)
4431
raise errors.NotVersionedError(filename)
4432
file_version = tree.inventory[file_id].revision
4433
if wt is not None and revision is None:
4434
# If there is a tree and we're not annotating historical
4435
# versions, annotate the working tree's content.
4436
annotate_file_tree(wt, file_id, self.outf, long, all,
4439
annotate_file(branch, file_version, file_id, long, all, self.outf,
4524
4448
class cmd_re_sign(Command):
5039
4964
directly from the merge directive, without retrieving data from a
5042
`bzr send` creates a compact data set that, when applied using bzr
5043
merge, has the same effect as merging from the source branch.
5045
By default the merge directive is self-contained and can be applied to any
5046
branch containing submit_branch in its ancestory without needing access to
5049
If --no-bundle is specified, then Bazaar doesn't send the contents of the
5050
revisions, but only a structured request to merge from the
5051
public_location. In that case the public_branch is needed and it must be
5052
up-to-date and accessible to the recipient. The public_branch is always
5053
included if known, so that people can check it later.
5055
The submit branch defaults to the parent of the source branch, but can be
5056
overridden. Both submit branch and public branch will be remembered in
5057
branch.conf the first time they are used for a particular branch. The
5058
source branch defaults to that containing the working directory, but can
5059
be changed using --from.
5061
In order to calculate those changes, bzr must analyse the submit branch.
5062
Therefore it is most efficient for the submit branch to be a local mirror.
5063
If a public location is known for the submit_branch, that location is used
5064
in the merge directive.
5066
The default behaviour is to send the merge directive by mail, unless -o is
5067
given, in which case it is sent to a file.
4967
If --no-bundle is specified, then public_branch is needed (and must be
4968
up-to-date), so that the receiver can perform the merge using the
4969
public_branch. The public_branch is always included if known, so that
4970
people can check it later.
4972
The submit branch defaults to the parent, but can be overridden. Both
4973
submit branch and public branch will be remembered if supplied.
4975
If a public_branch is known for the submit_branch, that public submit
4976
branch is used in the merge instructions. This means that a local mirror
4977
can be used as your actual submit branch, once you have set public_branch
5069
4980
Mail is sent using your preferred mail program. This should be transparent
5070
4981
on Windows (it uses MAPI). On Linux, it requires the xdg-email utility.
5259
5166
branch, relpath = Branch.open_containing(directory)
5260
5167
branch.lock_write()
5261
self.add_cleanup(branch.unlock)
5263
branch.tags.delete_tag(tag_name)
5264
self.outf.write('Deleted tag %s.\n' % tag_name)
5267
if len(revision) != 1:
5268
raise errors.BzrCommandError(
5269
"Tags can only be placed on a single revision, "
5271
revision_id = revision[0].as_revision_id(branch)
5170
branch.tags.delete_tag(tag_name)
5171
self.outf.write('Deleted tag %s.\n' % tag_name)
5273
revision_id = branch.last_revision()
5274
if (not force) and branch.tags.has_tag(tag_name):
5275
raise errors.TagAlreadyExists(tag_name)
5276
branch.tags.set_tag(tag_name, revision_id)
5277
self.outf.write('Created tag %s.\n' % tag_name)
5174
if len(revision) != 1:
5175
raise errors.BzrCommandError(
5176
"Tags can only be placed on a single revision, "
5178
revision_id = revision[0].as_revision_id(branch)
5180
revision_id = branch.last_revision()
5181
if (not force) and branch.tags.has_tag(tag_name):
5182
raise errors.TagAlreadyExists(tag_name)
5183
branch.tags.set_tag(tag_name, revision_id)
5184
self.outf.write('Created tag %s.\n' % tag_name)
5280
5189
class cmd_tags(Command):
5315
5224
branch.lock_read()
5316
self.add_cleanup(branch.unlock)
5318
graph = branch.repository.get_graph()
5319
rev1, rev2 = _get_revision_range(revision, branch, self.name())
5320
revid1, revid2 = rev1.rev_id, rev2.rev_id
5321
# only show revisions between revid1 and revid2 (inclusive)
5322
tags = [(tag, revid) for tag, revid in tags if
5323
graph.is_between(revid, revid1, revid2)]
5326
elif sort == 'time':
5328
for tag, revid in tags:
5330
revobj = branch.repository.get_revision(revid)
5331
except errors.NoSuchRevision:
5332
timestamp = sys.maxint # place them at the end
5334
timestamp = revobj.timestamp
5335
timestamps[revid] = timestamp
5336
tags.sort(key=lambda x: timestamps[x[1]])
5338
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5339
for index, (tag, revid) in enumerate(tags):
5341
revno = branch.revision_id_to_dotted_revno(revid)
5342
if isinstance(revno, tuple):
5343
revno = '.'.join(map(str, revno))
5344
except errors.NoSuchRevision:
5345
# Bad tag data/merges can lead to tagged revisions
5346
# which are not in this branch. Fail gracefully ...
5348
tags[index] = (tag, revno)
5227
graph = branch.repository.get_graph()
5228
rev1, rev2 = _get_revision_range(revision, branch, self.name())
5229
revid1, revid2 = rev1.rev_id, rev2.rev_id
5230
# only show revisions between revid1 and revid2 (inclusive)
5231
tags = [(tag, revid) for tag, revid in tags if
5232
graph.is_between(revid, revid1, revid2)]
5235
elif sort == 'time':
5237
for tag, revid in tags:
5239
revobj = branch.repository.get_revision(revid)
5240
except errors.NoSuchRevision:
5241
timestamp = sys.maxint # place them at the end
5243
timestamp = revobj.timestamp
5244
timestamps[revid] = timestamp
5245
tags.sort(key=lambda x: timestamps[x[1]])
5247
# [ (tag, revid), ... ] -> [ (tag, dotted_revno), ... ]
5248
for index, (tag, revid) in enumerate(tags):
5250
revno = branch.revision_id_to_dotted_revno(revid)
5251
if isinstance(revno, tuple):
5252
revno = '.'.join(map(str, revno))
5253
except errors.NoSuchRevision:
5254
# Bad tag data/merges can lead to tagged revisions
5255
# which are not in this branch. Fail gracefully ...
5257
tags[index] = (tag, revno)
5350
5260
for tag, revspec in tags:
5351
5261
self.outf.write('%-20s %s\n' % (tag, revspec))