# HG changeset patch # User Durham Goode # Date 1378867774 25200 # Node ID d184bae667e41d953648aa3c2641a3608c27f45a # Parent dfefb719eb92ed6cb72a2101db9ea5ccb70650fa log: make file log slow path usable on large repos Running "hg log " on large repos took a very, very long time because it first read ctx.files() for every commit before even starting to process the results. This change makes the ctx.files() check lazy, which makes the command start producing results immediately. diff -r dfefb719eb92 -r d184bae667e4 mercurial/cmdutil.py --- a/mercurial/cmdutil.py Fri Sep 13 15:40:04 2013 -0500 +++ b/mercurial/cmdutil.py Tue Sep 10 19:49:34 2013 -0700 @@ -1172,12 +1172,34 @@ 'filenames')) # The slow path checks files modified in every changeset. - for i in sorted(revs): - ctx = change(i) - matches = filter(match, ctx.files()) - if matches: - fncache[i] = matches - wanted.add(i) + # This is really slow on large repos, so compute the set lazily. + class lazywantedset(object): + def __init__(self): + self.set = set() + self.revs = set(revs) + + # No need to worry about locality here because it will be accessed + # in the same order as the increasing window below. + def __contains__(self, value): + if value in self.set: + return True + elif not value in self.revs: + return False + else: + self.revs.discard(value) + ctx = change(value) + matches = filter(match, ctx.files()) + if matches: + fncache[value] = matches + self.set.add(value) + return True + return False + + def discard(self, value): + self.revs.discard(value) + self.set.discard(value) + + wanted = lazywantedset() class followfilter(object): def __init__(self, onlyfirst=False):