Mercurial > hg
changeset 23700:a4958cdb2202
context: cache self._status correctly at workingctx.status
Before this patch, "workingctx.status" always replaces "self._status"
by the recent result, even though:
- status isn't calculated against the parent of the working directory, or
- specified "match" isn't "always" one
(status is only visible partially)
If "workingctx" object is shared between some procedures indirectly
referring "ctx._status", this incorrect caching may cause unexpected
result: for example, "ctx._status" is used via "manifest()", "files()"
and so on.
To cache "self._status" correctly at "workingctx.status", this patch
overwrites "self._status" in "workingctx._buildstatus" only when:
- status is calculated against the parent of the working directory, and
- specified "match" is "always" one
This patch can be applied (and effective) only on default branch,
because procedure around "basectx.status" is much different between
stable and default: for example, overwriting "self._status" itself is
executed not in "workingctx._buildstatus" but in
"workingctx._poststatus", on stable branch.
author | FUJIWARA Katsunori <foozy@lares.dti.ne.jp> |
---|---|
date | Wed, 31 Dec 2014 17:55:43 +0900 |
parents | fe17a6fb220d |
children | 76320e2ed0a8 |
files | mercurial/context.py tests/test-context.py tests/test-context.py.out |
diffstat | 3 files changed, 49 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/context.py Tue Dec 23 18:30:46 2014 -0800 +++ b/mercurial/context.py Wed Dec 31 17:55:43 2014 +0900 @@ -1444,7 +1444,9 @@ s = super(workingctx, self)._buildstatus(other, s, match, listignored, listclean, listunknown) - self._status = s + elif match.always(): + # cache for performance + self._status = s return s def _matchstatus(self, other, match):
--- a/tests/test-context.py Tue Dec 23 18:30:46 2014 -0800 +++ b/tests/test-context.py Wed Dec 31 17:55:43 2014 +0900 @@ -50,3 +50,42 @@ for d in ctxb.diff(ctxa, git=True): print d + +# test safeness and correctness of "cxt.status()" +print '= checking context.status():' + +# ancestor "wcctx ~ 2" +actx2 = repo['.'] + +repo.wwrite('bar-m', 'bar-m\n', '') +repo.wwrite('bar-r', 'bar-r\n', '') +repo[None].add(['bar-m', 'bar-r']) +repo.commit(text='add bar-m, bar-r', date="0 0") + +# ancestor "wcctx ~ 1" +actx1 = repo['.'] + +repo.wwrite('bar-m', 'bar-m bar-m\n', '') +repo.wwrite('bar-a', 'bar-a\n', '') +repo[None].add(['bar-a']) +repo[None].forget(['bar-r']) + +# status at this point: +# M bar-m +# A bar-a +# R bar-r +# C foo + +from mercurial import scmutil + +print '== checking workingctx.status:' + +wctx = repo[None] +print 'wctx._status=%s' % (str(wctx._status)) + +print actx1.status(other=wctx, + match=scmutil.matchfiles(repo, ['bar-m', 'foo'])) +print 'wctx._status=%s' % (str(wctx._status)) +print actx2.status(other=wctx, + match=scmutil.matchfiles(repo, ['bar-m', 'foo'])) +print 'wctx._status=%s' % (str(wctx._status))
--- a/tests/test-context.py.out Tue Dec 23 18:30:46 2014 -0800 +++ b/tests/test-context.py.out Wed Dec 31 17:55:43 2014 +0900 @@ -11,3 +11,10 @@ foo +bar += checking context.status(): +== checking workingctx.status: +wctx._status=<status modified=['bar-m'], added=['bar-a'], removed=['bar-r'], deleted=[], unknown=[], ignored=[], clean=[]> +<status modified=['bar-m'], added=[], removed=[], deleted=[], unknown=[], ignored=[], clean=[]> +wctx._status=<status modified=['bar-m'], added=['bar-a'], removed=['bar-r'], deleted=[], unknown=[], ignored=[], clean=[]> +<status modified=[], added=['bar-m'], removed=[], deleted=[], unknown=[], ignored=[], clean=[]> +wctx._status=<status modified=['bar-m'], added=['bar-a'], removed=['bar-r'], deleted=[], unknown=[], ignored=[], clean=[]>