Patchwork [1,of,2] test-context: add a case demonstrating manifest caching problem

login
register
mail settings
Submitter Jun Wu
Date May 26, 2017, 12:36 a.m.
Message ID <379e5047c6472df9de70.1495758961@x1c>
Download mbox | patch
Permalink /patch/20921/
State Accepted
Headers show

Comments

Jun Wu - May 26, 2017, 12:36 a.m.
# HG changeset patch
# User Jun Wu <quark@fb.com>
# Date 1495757192 25200
#      Thu May 25 17:06:32 2017 -0700
# Node ID 379e5047c6472df9de70a5b990b1330e3857c4db
# Parent  2b5953a49f1407f825d65b45986d213cb5c79203
# Available At https://bitbucket.org/quark-zju/hg-draft
#              hg pull https://bitbucket.org/quark-zju/hg-draft -r 379e5047c647
test-context: add a case demonstrating manifest caching problem

This issue was discovered when testing absorb on Windows. What happens are:

  1. ctx.p1().manifestctx gets cached.
     let's call ctx.p1().manifestctx._revlog() "mrevlog1"
  2. repo.manifestlog gets invalidated.
     let's call repo.manifestlog._revlog "mrevlog2"
  3. repo.commitctx(ctx)
     commitctx uses ctx.p1().manifestctx and writes to "mrevlog1"
  4. repo[n].manifest()
     cannot find the manifest node in "mrevlog2"

This patch adds a test case to reproduce the issue.

Patch

diff --git a/tests/test-context.py b/tests/test-context.py
--- a/tests/test-context.py
+++ b/tests/test-context.py
@@ -1,8 +1,10 @@ 
 from __future__ import absolute_import, print_function
 import os
+from mercurial.node import hex
 from mercurial import (
     context,
     encoding,
     hg,
+    scmutil,
     ui as uimod,
 )
@@ -147,2 +149,33 @@  print(actx2.status(other=wcctx,
                    listclean=True))
 print('wcctx._status=%s' % (str(wcctx._status)))
+
+os.chdir('..')
+
+# test manifestlog being changed
+print('== commit with manifestlog invalidated')
+
+repo = hg.repository(u, 'test2', create=1)
+os.chdir('test2')
+
+# make some commits
+for i in [b'1', b'2', b'3']:
+    with open(i, 'wb') as f:
+        f.write(i)
+    status = scmutil.status([], [i], [], [], [], [], [])
+    ctx = context.workingcommitctx(repo, status, text=i, user=b'test@test.com',
+                                   date=(0, 0))
+    ctx.p1().manifest() # side effect: cache manifestctx
+    n = repo.commitctx(ctx)
+    print('commit %s: %s' % (i, hex(n)))
+
+    # touch 00manifest.i mtime so storecache could expire.
+    # repo.__dict__['manifestlog'] is deleted by transaction releasefn.
+    st = repo.svfs.stat('00manifest.i')
+    repo.svfs.utime('00manifest.i', (st.st_mtime + 1, st.st_mtime + 1))
+
+    # read the file just committed
+    try:
+        if repo[n][i].data() != i:
+            print('data mismatch')
+    except Exception as ex:
+        print('cannot read data: %r' % ex)
diff --git a/tests/test-context.py.out b/tests/test-context.py.out
--- a/tests/test-context.py.out
+++ b/tests/test-context.py.out
@@ -45,2 +45,8 @@  wcctx._status=<status modified=['bar-m']
 <status modified=[], added=['bar-r'], removed=[], deleted=[], unknown=[], ignored=[], clean=['foo']>
 wcctx._status=<status modified=['bar-m'], added=['bar-a'], removed=[], deleted=[], unknown=[], ignored=[], clean=[]>
+== commit with manifestlog invalidated
+commit 1: 2efe531a913fa648867ab8824360371679d05a65
+commit 2: 2caca91f6362020334384ebe27bae67315298abf
+cannot read data: LookupError('Q\xa3L\xa5Ou\x8f\xce8\xda<Q\x7f\x9f(\xc9;Li/', '00manifest.i', 'no node')
+commit 3: abd6b0f49f338be22b094ef2b7425e8048f8337b
+cannot read data: LookupError("\x82\x15\xb8\xd3\x85\xf6H'\x9cP'D\x97\x1e\xab\x98O\xbb\x05\x9d", '00manifest.i', 'no node')