209
206
if specific_fileid:
210
207
mutter('get log for file_id %r', specific_fileid)
208
generate_merge_revisions = getattr(lf, 'supports_merge_revisions', False)
209
allow_single_merge_revision = getattr(lf,
210
'supports_single_merge_revision', False)
211
view_revisions = calculate_view_revisions(branch, start_revision,
212
end_revision, direction,
214
generate_merge_revisions,
215
allow_single_merge_revision)
212
216
if search is not None:
213
217
searchRE = re.compile(search, re.IGNORECASE)
222
generate_tags = getattr(lf, 'supports_tags', False)
224
if branch.supports_tags():
225
rev_tag_dict = branch.tags.get_reverse_tag_dict()
227
generate_delta = verbose and getattr(lf, 'supports_delta', False)
229
# now we just print all the revisions
231
for (rev_id, revno, merge_depth), rev, delta in _iter_revisions(
232
branch.repository, view_revisions, generate_delta):
234
if not searchRE.search(rev.message):
237
lr = LogRevision(rev, revno, merge_depth, delta,
238
rev_tag_dict.get(rev_id))
242
if log_count >= limit:
246
def calculate_view_revisions(branch, start_revision, end_revision, direction,
247
specific_fileid, generate_merge_revisions,
248
allow_single_merge_revision):
249
if (not generate_merge_revisions and start_revision is end_revision is
250
None and direction == 'reverse' and specific_fileid is None):
251
return _linear_view_revisions(branch)
217
253
mainline_revs, rev_nos, start_rev_id, end_rev_id = \
218
254
_get_mainline_revs(branch, start_revision, end_revision)
219
255
if not mainline_revs:
222
258
if direction == 'reverse':
223
259
start_rev_id, end_rev_id = end_rev_id, start_rev_id
225
legacy_lf = getattr(lf, 'log_revision', None) is None
227
# pre-0.17 formatters use show for mainline revisions.
228
# how should we show merged revisions ?
229
# pre-0.11 api: show_merge
230
# 0.11-0.16 api: show_merge_revno
231
show_merge_revno = getattr(lf, 'show_merge_revno', None)
232
show_merge = getattr(lf, 'show_merge', None)
233
if show_merge is None and show_merge_revno is None:
234
# no merged-revno support
235
generate_merge_revisions = False
237
generate_merge_revisions = True
238
# tell developers to update their code
239
symbol_versioning.warn('LogFormatters should provide log_revision '
240
'instead of show and show_merge_revno since bzr 0.17.',
241
DeprecationWarning, stacklevel=3)
243
generate_merge_revisions = getattr(lf, 'supports_merge_revisions',
245
261
generate_single_revision = False
246
262
if ((not generate_merge_revisions)
247
263
and ((start_rev_id and (start_rev_id not in rev_nos))
248
264
or (end_rev_id and (end_rev_id not in rev_nos)))):
249
265
generate_single_revision = ((start_rev_id == end_rev_id)
250
and getattr(lf, 'supports_single_merge_revision', False))
266
and allow_single_merge_revision)
251
267
if not generate_single_revision:
252
268
raise BzrCommandError('Selected log formatter only supports '
253
269
'mainline revisions.')
271
287
min_depth = min([d for r,n,d in view_revisions])
272
288
if min_depth != 0:
273
289
view_revisions = [(r,n,d-min_depth) for r,n,d in view_revisions]
276
generate_tags = getattr(lf, 'supports_tags', False)
278
if branch.supports_tags():
279
rev_tag_dict = branch.tags.get_reverse_tag_dict()
281
generate_delta = verbose and getattr(lf, 'supports_delta', False)
283
def iter_revisions():
290
return view_revisions
293
def _linear_view_revisions(branch):
294
start_revno, start_revision_id = branch.last_revision_info()
295
repo = branch.repository
296
revision_ids = repo.iter_reverse_revision_history(start_revision_id)
297
for num, revision_id in enumerate(revision_ids):
298
yield revision_id, str(start_revno - num), 0
301
def _iter_revisions(repository, view_revisions, generate_delta):
303
view_revisions = iter(view_revisions)
305
cur_view_revisions = [d for x, d in zip(range(num), view_revisions)]
306
if len(cur_view_revisions) == 0:
284
309
# r = revision, n = revno, d = merge depth
285
revision_ids = [r for r, n, d in view_revisions]
287
repository = branch.repository
290
revisions = repository.get_revisions(revision_ids[:num])
292
deltas = repository.get_deltas_for_revisions(revisions)
293
cur_deltas = dict(izip((r.revision_id for r in revisions),
295
for revision in revisions:
296
yield revision, cur_deltas.get(revision.revision_id)
297
revision_ids = revision_ids[num:]
298
num = min(int(num * 1.5), 200)
300
# now we just print all the revisions
302
for ((rev_id, revno, merge_depth), (rev, delta)) in \
303
izip(view_revisions, iter_revisions()):
306
if not searchRE.search(rev.message):
310
lr = LogRevision(rev, revno, merge_depth, delta,
311
rev_tag_dict.get(rev_id))
314
# support for legacy (pre-0.17) LogFormatters
317
lf.show(revno, rev, delta, rev_tag_dict.get(rev_id))
319
lf.show(revno, rev, delta)
321
if show_merge_revno is None:
322
lf.show_merge(rev, merge_depth)
325
lf.show_merge_revno(rev, merge_depth, revno,
326
rev_tag_dict.get(rev_id))
328
lf.show_merge_revno(rev, merge_depth, revno)
331
if log_count >= limit:
310
revision_ids = [r for (r, n, d) in cur_view_revisions]
311
revisions = repository.get_revisions(revision_ids)
313
deltas = repository.get_deltas_for_revisions(revisions)
314
cur_deltas = dict(izip((r.revision_id for r in revisions),
316
for view_data, revision in izip(cur_view_revisions, revisions):
317
yield view_data, revision, cur_deltas.get(revision.revision_id)
318
num = min(int(num * 1.5), 200)
335
321
def _get_mainline_revs(branch, start_revision, end_revision):
474
460
weave_modifed_revisions = set(file_weave.versions())
475
461
# build the ancestry of each revision in the graph
476
462
# - only listing the ancestors that change the specific file.
477
rev_graph = branch.repository.get_revision_graph(mainline_revisions[-1])
478
sorted_rev_list = topo_sort(rev_graph)
463
graph = branch.repository.get_graph()
464
# This asks for all mainline revisions, which means we only have to spider
465
# sideways, rather than depth history. That said, its still size-of-history
466
# and should be addressed.
467
parent_map = dict(((key, value) for key, value in
468
graph.iter_ancestry(mainline_revisions) if value is not None))
469
sorted_rev_list = topo_sort(parent_map.items())
480
471
for rev in sorted_rev_list:
481
parents = rev_graph[rev]
472
parents = parent_map[rev]
482
473
if rev not in weave_modifed_revisions and len(parents) == 1:
483
474
# We will not be adding anything new, so just use a reference to
484
475
# the parent ancestry.
520
511
for revision_id in revision_ids:
521
512
yield revision_id, str(rev_nos[revision_id]), 0
514
graph = branch.repository.get_graph()
515
# This asks for all mainline revisions, which means we only have to spider
516
# sideways, rather than depth history. That said, its still size-of-history
517
# and should be addressed.
518
parent_map = dict(((key, value) for key, value in
519
graph.iter_ancestry(mainline_revs) if value is not None))
520
# filter out ghosts; merge_sort errors on ghosts.
521
rev_graph = _strip_NULL_ghosts(parent_map)
523
522
merge_sorted_revisions = merge_sort(
524
branch.repository.get_revision_graph(mainline_revs[-1]),
525
524
mainline_revs[-1],
527
526
generate_revno=True)
639
634
supports_delta = True
640
635
supports_tags = True
642
@deprecated_method(zero_seventeen)
643
def show(self, revno, rev, delta, tags=None):
644
lr = LogRevision(rev, revno, 0, delta, tags)
645
return self.log_revision(lr)
647
@deprecated_method(zero_seventeen)
648
def show_merge_revno(self, rev, merge_depth, revno, tags=None):
649
"""Show a merged revision rev, with merge_depth and a revno."""
650
lr = LogRevision(rev, revno, merge_depth, tags=tags)
651
return self.log_revision(lr)
653
637
def log_revision(self, revision):
654
638
"""Log a revision, either merged or not."""
655
639
indent = ' ' * revision.merge_depth