comparison mercurial/scmutil.py @ 45720:508dfd1c18df

scmutil: move walkchangerevs() from cmdutil It's no longer a command-level function, but a pure helper to walk revisions in a windowed way. This change will help eliminate reverse dependency of revset.py -> grep.py -> cmdutil.py in future patches.
author Yuya Nishihara <yuya@tcha.org>
date Sun, 04 Oct 2020 13:17:57 +0900
parents d2e1dcd4490d
children 8f07f5a9c3de
comparison
equal deleted inserted replaced
45719:c10c87c8fe79 45720:508dfd1c18df
758 spec = revsetlang.formatspec(b'%d', spec) 758 spec = revsetlang.formatspec(b'%d', spec)
759 allspecs.append(spec) 759 allspecs.append(spec)
760 return repo.anyrevs(allspecs, user=True, localalias=localalias) 760 return repo.anyrevs(allspecs, user=True, localalias=localalias)
761 761
762 762
763 def increasingwindows(windowsize=8, sizelimit=512):
764 while True:
765 yield windowsize
766 if windowsize < sizelimit:
767 windowsize *= 2
768
769
770 def walkchangerevs(repo, revs, makefilematcher, prepare):
771 '''Iterate over files and the revs in a "windowed" way.
772
773 Callers most commonly need to iterate backwards over the history
774 in which they are interested. Doing so has awful (quadratic-looking)
775 performance, so we use iterators in a "windowed" way.
776
777 We walk a window of revisions in the desired order. Within the
778 window, we first walk forwards to gather data, then in the desired
779 order (usually backwards) to display it.
780
781 This function returns an iterator yielding contexts. Before
782 yielding each context, the iterator will first call the prepare
783 function on each context in the window in forward order.'''
784
785 if not revs:
786 return []
787 change = repo.__getitem__
788
789 def iterate():
790 it = iter(revs)
791 stopiteration = False
792 for windowsize in increasingwindows():
793 nrevs = []
794 for i in pycompat.xrange(windowsize):
795 rev = next(it, None)
796 if rev is None:
797 stopiteration = True
798 break
799 nrevs.append(rev)
800 for rev in sorted(nrevs):
801 ctx = change(rev)
802 prepare(ctx, makefilematcher(ctx))
803 for rev in nrevs:
804 yield change(rev)
805
806 if stopiteration:
807 break
808
809 return iterate()
810
811
763 def meaningfulparents(repo, ctx): 812 def meaningfulparents(repo, ctx):
764 """Return list of meaningful (or all if debug) parentrevs for rev. 813 """Return list of meaningful (or all if debug) parentrevs for rev.
765 814
766 For merges (two non-nullrev revisions) both parents are meaningful. 815 For merges (two non-nullrev revisions) both parents are meaningful.
767 Otherwise the first parent revision is considered meaningful if it 816 Otherwise the first parent revision is considered meaningful if it