History cache not cleared on edit, and can follow renames
This commit is contained in:
parent
687b0f5ced
commit
b754b9ac5a
|
@ -1,5 +1,3 @@
|
||||||
import collections
|
|
||||||
import itertools
|
|
||||||
import os
|
import os
|
||||||
import posixpath
|
import posixpath
|
||||||
import re
|
import re
|
||||||
|
@ -115,33 +113,52 @@ class WikiPage(HookMixin):
|
||||||
"""Get page history.
|
"""Get page history.
|
||||||
|
|
||||||
History can take a long time to generate for repositories with many commits.
|
History can take a long time to generate for repositories with many commits.
|
||||||
This returns an iterator to avoid having to load them all at once.
|
This returns an iterator to avoid having to load them all at once, and caches
|
||||||
|
as it goes.
|
||||||
|
|
||||||
:return: iter -- Iterator over dicts
|
:return: iter -- Iterator over dicts
|
||||||
|
|
||||||
"""
|
"""
|
||||||
cache_complete = False
|
cache_head = []
|
||||||
cached_revs = cache.get(self._cache_key('history')) or []
|
cache_tail = cache.get(self._cache_key('history')) or [{'_cache_missing': True}]
|
||||||
start_sha = None
|
while True:
|
||||||
if cached_revs:
|
if not cache_tail:
|
||||||
if cached_revs[-1] == 'TAIL':
|
|
||||||
del cached_revs[-1]
|
|
||||||
cache_complete = True
|
|
||||||
else:
|
|
||||||
start_sha = cached_revs[-1]['sha']
|
|
||||||
for rev in cached_revs:
|
|
||||||
yield rev
|
|
||||||
if cache_complete:
|
|
||||||
return
|
return
|
||||||
|
for index, cached_rev in enumerate(cache_tail):
|
||||||
|
if cached_rev.get("_cache_missing"):
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
yield cached_rev
|
||||||
|
cache_head.extend(cache_tail[:index])
|
||||||
|
cache_tail = cache_tail[index+1:]
|
||||||
|
start_sha = cached_rev.get('sha')
|
||||||
|
end_sha = cache_tail[0].get('sha') if cache_tail else None
|
||||||
|
for rev in self._iter_revs(start_sha=start_sha, end_sha=end_sha, filename=cached_rev.get('filename')):
|
||||||
|
cache_head.append(rev)
|
||||||
|
placeholder = {
|
||||||
|
'_cache_missing': True,
|
||||||
|
'sha': rev['sha'],
|
||||||
|
'filename': rev['new_filename']
|
||||||
|
}
|
||||||
|
cache.set(self._cache_key('history'), cache_head + [placeholder] + cache_tail)
|
||||||
|
yield rev
|
||||||
|
cache.set(self._cache_key('history'), cache_head + cache_tail)
|
||||||
|
|
||||||
|
def _iter_revs(self, start_sha=None, end_sha=None, filename=None):
|
||||||
|
if end_sha:
|
||||||
|
end_sha = [end_sha]
|
||||||
if not len(self.wiki.repo.open_index()):
|
if not len(self.wiki.repo.open_index()):
|
||||||
# Index is empty, no commits
|
# Index is empty, no commits
|
||||||
return
|
return
|
||||||
walker = iter(self.wiki.repo.get_walker(paths=[self.filename], include=start_sha, follow=True))
|
filename = filename or self.filename
|
||||||
|
walker = iter(self.wiki.repo.get_walker(paths=[filename],
|
||||||
|
include=start_sha,
|
||||||
|
exclude=end_sha,
|
||||||
|
follow=True))
|
||||||
if start_sha:
|
if start_sha:
|
||||||
# If we are not starting from HEAD, we already have the start commit
|
# If we are not starting from HEAD, we already have the start commit
|
||||||
next(walker)
|
next(walker)
|
||||||
filename = self.filename
|
filename = self.filename
|
||||||
try:
|
|
||||||
for entry in walker:
|
for entry in walker:
|
||||||
change_type = None
|
change_type = None
|
||||||
for change in entry.changes():
|
for change in entry.changes():
|
||||||
|
@ -156,12 +173,10 @@ class WikiPage(HookMixin):
|
||||||
time=entry.commit.author_time,
|
time=entry.commit.author_time,
|
||||||
message=entry.commit.message,
|
message=entry.commit.message,
|
||||||
sha=entry.commit.id,
|
sha=entry.commit.id,
|
||||||
type=change_type)
|
type=change_type,
|
||||||
cached_revs.append(r)
|
new_filename=change.new.path,
|
||||||
|
old_filename=change.old.path)
|
||||||
yield r
|
yield r
|
||||||
cached_revs.append('TAIL')
|
|
||||||
finally:
|
|
||||||
cache.set(self._cache_key('history'), cached_revs)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def history_cache(self):
|
def history_cache(self):
|
||||||
|
@ -169,13 +184,12 @@ class WikiPage(HookMixin):
|
||||||
|
|
||||||
:return: tuple -- (cached items, cache complete?)
|
:return: tuple -- (cached items, cache complete?)
|
||||||
"""
|
"""
|
||||||
cache_complete = False
|
cached_revs = cache.get(self._cache_key('history'))
|
||||||
cached_revs = cache.get(self._cache_key('history')) or []
|
if not cached_revs:
|
||||||
if cached_revs:
|
return 0, False
|
||||||
if cached_revs[-1] == 'TAIL':
|
elif any(rev.get('_cache_missing') for rev in cached_revs):
|
||||||
del cached_revs[-1]
|
return len(cached_revs) - 1, False
|
||||||
cache_complete = True
|
return len(cached_revs), True
|
||||||
return len(cached_revs), cache_complete
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def partials(self):
|
def partials(self):
|
||||||
|
@ -222,9 +236,14 @@ class WikiPage(HookMixin):
|
||||||
|
|
||||||
return username, email
|
return username, email
|
||||||
|
|
||||||
def _clear_cache(self):
|
def _invalidate_cache(self, save_history=None):
|
||||||
for p in ['data', 'history']:
|
cache.delete(self._cache_key('data'))
|
||||||
cache.delete(self._cache_key(p))
|
if save_history:
|
||||||
|
if not save_history[0].get('_cache_missing'):
|
||||||
|
save_history = [{'_cache_missing': True}] + save_history
|
||||||
|
cache.set(self._cache_key('history'), save_history)
|
||||||
|
else:
|
||||||
|
cache.delete(self._cache_key('history'))
|
||||||
|
|
||||||
def delete(self, username=None, email=None, message=None):
|
def delete(self, username=None, email=None, message=None):
|
||||||
"""Delete page.
|
"""Delete page.
|
||||||
|
@ -245,7 +264,7 @@ class WikiPage(HookMixin):
|
||||||
email=email,
|
email=email,
|
||||||
message=message,
|
message=message,
|
||||||
files=[self.filename])
|
files=[self.filename])
|
||||||
self._clear_cache()
|
self._invalidate_cache()
|
||||||
return commit
|
return commit
|
||||||
|
|
||||||
def rename(self, new_name, username=None, email=None, message=None):
|
def rename(self, new_name, username=None, email=None, message=None):
|
||||||
|
@ -283,11 +302,12 @@ class WikiPage(HookMixin):
|
||||||
message=message,
|
message=message,
|
||||||
files=[old_filename, new_filename])
|
files=[old_filename, new_filename])
|
||||||
|
|
||||||
self._clear_cache()
|
old_history = cache.get(self._cache_key('history'))
|
||||||
|
self._invalidate_cache()
|
||||||
self.name = new_name
|
self.name = new_name
|
||||||
self.filename = new_filename
|
self.filename = new_filename
|
||||||
# We need to clear the cache for the new name as well as the old
|
# We need to clear the cache for the new name as well as the old
|
||||||
self._clear_cache()
|
self._invalidate_cache(save_history=old_history)
|
||||||
|
|
||||||
return commit
|
return commit
|
||||||
|
|
||||||
|
@ -323,7 +343,8 @@ class WikiPage(HookMixin):
|
||||||
message=message,
|
message=message,
|
||||||
files=[self.filename])
|
files=[self.filename])
|
||||||
|
|
||||||
self._clear_cache()
|
old_history = cache.get(self._cache_key('history'))
|
||||||
|
self._invalidate_cache(save_history=old_history)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def revert(self, commit_sha, message, username, email):
|
def revert(self, commit_sha, message, username, email):
|
||||||
|
|
Loading…
Reference in a new issue