mirror of
https://github.com/facebook/sapling.git
synced 2024-10-07 07:17:55 +03:00
context: fix sanity check in metadataonlyctx
Summary: Previously, this check was subtly wrong, causing it to fail for empty commits (which have the same manifest as their parents). Update the check to ensure the actual thing we want to ensure -- that the caller isn't creating incorrect commits. The failure would happen in this case: ``` B empty commit (manifest Am) | A draft commit (manifest Am) / M master (manifest Mm) ``` When metaediting `A`, `metaedit` would then "rebase" `B` onto `A'` to create `B'`, with both `A'` and `B'` reusing `Am` as their manifest. The old check would fail here because the parent of `Am` is `Mm`, but the manifest of `A'` (the parent of `B'`) is `Am`, so when checking the manifest of the parent against the parent of the manifest, we would find that `Am != Mm` and fail. The actual check we wanted was that the manifest of the parent of `B'` is the same as the manifest of the parent of `B` -- which the old check approximated as long as no manifests were reused in the stack. As this is not sufficient with empty commits, we instead want to check that the manifest of the old parent matches the manifest of the new parent, which we now do. By avoid reading `manifest.parents`, this would also avoid some lazy tree fetches, therefore speed up metaedit in certain cases. Reviewed By: quark-zju Differential Revision: D9013995 fbshipit-source-id: 4d0b05fc9bb81d115cd87ba2bf98aa253ae6f88b
This commit is contained in:
parent
2b7e9e5e8b
commit
9e51fdef40
@ -2925,18 +2925,23 @@ class metadataonlyctx(committablectx):
|
||||
parents.append(repo[nullid])
|
||||
p1, p2 = self._parents = parents
|
||||
|
||||
# sanity check to ensure that the reused manifest parents are
|
||||
# manifests of our commit parents
|
||||
mp1, mp2 = self.manifestctx().parents
|
||||
if p1 != nullid and p1.manifestnode() != mp1:
|
||||
# sanity check to ensure that our parent's manifest has not changed
|
||||
# from our original parent's manifest to ensure the caller is not
|
||||
# creating invalid commits
|
||||
ops = [repo[p] for p in originalctx.parents() if p is not None]
|
||||
while len(ops) < 2:
|
||||
ops.append(repo[nullid])
|
||||
op1, op2 = ops
|
||||
|
||||
if p1.manifestnode() != op1.manifestnode():
|
||||
raise RuntimeError(
|
||||
"can't reuse the manifest: "
|
||||
"its p1 (%s) doesn't match the new ctx p1 (%s)"
|
||||
% (hex(p1.manifestnode()), hex(mp1))
|
||||
"new p1 manifest (%s) is not the old p1 manifest (%s)"
|
||||
% (hex(p1.manifestnode()), hex(op1.manifestnode()))
|
||||
)
|
||||
if p2 != nullid and p2.manifestnode() != mp2:
|
||||
if p2.manifestnode() != op2.manifestnode():
|
||||
raise RuntimeError(
|
||||
"can't reuse the manifest: " "its p2 doesn't match the new ctx p2"
|
||||
"new p2 manifest (%s) is not the old p2 manifest (%s)"
|
||||
% (hex(p2.manifestnode()), hex(op2.manifestnode()))
|
||||
)
|
||||
|
||||
self._files = originalctx.files()
|
||||
|
@ -37,7 +37,7 @@ Tests about metadataonlyctx
|
||||
summary: Changed
|
||||
|
||||
$ hg --config extensions.metaedit=$TESTTMP/metaedit.py metaedit 'parents=0' 2>&1 | egrep '^RuntimeError'
|
||||
RuntimeError: can't reuse the manifest: its p1 (007d8c9d88841325f5c6b06371b35b4e8a2b1a83) doesn't match the new ctx p1 (cb5cbbc1bfbf24cc34b9e8c16914e9caa2d2a7fd)
|
||||
RuntimeError: new p1 manifest (007d8c9d88841325f5c6b06371b35b4e8a2b1a83) is not the old p1 manifest (cb5cbbc1bfbf24cc34b9e8c16914e9caa2d2a7fd)
|
||||
|
||||
$ hg --config extensions.metaedit=$TESTTMP/metaedit.py metaedit 'user=foo <foo@example.com>'
|
||||
$ hg log -r tip
|
||||
|
@ -391,5 +391,17 @@ Test copying obsmarkers
|
||||
Test empty commit
|
||||
$ hg co -q 1be7301b35ae
|
||||
$ hg commit --config ui.allowemptycommit=true -m empty
|
||||
$ hg metaedit -r ".^" -m "parent of empty commit" 2>&1 | grep RuntimeError
|
||||
RuntimeError: can't reuse the manifest: its p1 (c74667c33d85705d7872136b99225b744c924aa5) doesn't match the new ctx p1 (eb79886383871977bccdb3000c275a279f0d4c99)
|
||||
$ hg metaedit -r ".^" -m "parent of empty commit"
|
||||
$ glog -r 'all()'
|
||||
@ 11:e582f22eefc0@default(draft) empty
|
||||
|
|
||||
o 10:539393debc47@default(draft) parent of empty commit
|
||||
|
|
||||
| o 8:52bc6136aa97@default(draft) D
|
||||
| |
|
||||
| x 6:19437442f9e4@default(draft) C
|
||||
|/
|
||||
o 5:888bb4818188@default(draft) B1
|
||||
|
|
||||
o 0:426bada5c675@default(draft) A
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user