mergedriver: fix the invalidation flakiness by setting sys.dont_write_bytecode

Summary:
D8464848 added code to invalidate merge drivers after running them, for reasons described in that diff.

But it turns out deleting from sys.modules is not enough, because Python will occasionally write a `.pyc` of the original hook, and re-use it when loading again, thus bypassing the invalidation.

This doesn't happen at all on my Mac, but happens approximately every other time when running on CentOS. Thanks to DurhamG who discovered the flakiness.

This fixes the flakiness of the test, and AFAIK this would be a problem in the wild, too, though we haven't heard of it yet.

Reviewed By: singhsrb

Differential Revision: D8675720

fbshipit-source-id: bec8fec6af9a362db1f0dd5d262932cbda6137ff
This commit is contained in:
Phil Cohen 2018-06-29 10:28:56 -07:00 committed by Facebook Github Bot
parent 03a6aad6f7
commit 73acd830dd
2 changed files with 9 additions and 3 deletions

View File

@ -114,6 +114,11 @@ def _rundriver(repo, ms, op, wctx, labels):
raise error.ConfigError(_("merge driver must be a python hook"))
ms.commit()
raised = False
# Don't write .pyc files for the loaded hooks (restore this setting
# after running). Like the `loadedmodules` fix below, this is to prevent
# drivers changed during a rebase from being loaded inconsistently.
origbytecodesetting = sys.dont_write_bytecode
sys.dont_write_bytecode = True
origmodules = set(sys.modules.keys())
try:
res = hook.runhooks(
@ -149,6 +154,7 @@ def _rundriver(repo, ms, op, wctx, labels):
loadedmodules = set(sys.modules.keys()) - origmodules
for mod in loadedmodules:
del sys.modules[mod]
sys.dont_write_bytecode = origbytecodesetting
return r, raised

View File

@ -21,7 +21,7 @@ Test mergedriver invalidation with IMM.
> pass
> EOF
$ cat >> driver/generators.py <<EOF
$ cat > driver/generators.py <<EOF
> VERSION = "BASE"
> def someFunction(repo):
> repo.ui.warn("base's someFunction() called\n")
@ -40,7 +40,7 @@ conflicts, though a conflict would work too). Otherwise, mergedriver won't run.
Next, off of BASE, make an API change to the driver.
$ cat >> driver/__init__.py <<EOF
$ cat > driver/__init__.py <<EOF
> from .generators import someFunction, VERSION
>
> def preprocess(ui, repo, hooktype, mergestate, wctx, labels=None):
@ -56,7 +56,7 @@ Next, off of BASE, make an API change to the driver.
> def conclude(ui, repo, hooktype, mergestate, wctx, labels=None):
> pass
> EOF
$ cat >> driver/generators.py <<EOF
$ cat > driver/generators.py <<EOF
> VERSION = "NEW"
>
> def someFunction(repo, new_required_arg):