hooks: drop support for Python 2

Stop running old repohooks via python2.  Abort immediately with a
clear error for the user.

Bug: 302871152
Change-Id: I750c6cbbf3c7950e249512bb1bd023c32587eef5
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/389454
Reviewed-by: Aravind Vasudevan <aravindvasudev@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
Commit-Queue: Mike Frysinger <vapier@google.com>
This commit is contained in:
Mike Frysinger 2023-10-14 01:25:50 +05:45 committed by LUCI
parent 8f4f98582e
commit 3b8f9535c7

View File

@ -12,11 +12,8 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import errno
import json
import os import os
import re import re
import subprocess
import sys import sys
import traceback import traceback
import urllib.parse import urllib.parse
@ -298,43 +295,6 @@ class RepoHook(object):
return interp return interp
def _ExecuteHookViaReexec(self, interp, context, **kwargs):
"""Execute the hook script through |interp|.
Note: Support for this feature should be dropped ~Jun 2021.
Args:
interp: The Python program to run.
context: Basic Python context to execute the hook inside.
kwargs: Arbitrary arguments to pass to the hook script.
Raises:
HookError: When the hooks failed for any reason.
"""
# This logic needs to be kept in sync with _ExecuteHookViaImport below.
script = """
import json, os, sys
path = '''%(path)s'''
kwargs = json.loads('''%(kwargs)s''')
context = json.loads('''%(context)s''')
sys.path.insert(0, os.path.dirname(path))
data = open(path).read()
exec(compile(data, path, 'exec'), context)
context['main'](**kwargs)
""" % {
"path": self._script_fullpath,
"kwargs": json.dumps(kwargs),
"context": json.dumps(context),
}
# We pass the script via stdin to avoid OS argv limits. It also makes
# unhandled exception tracebacks less verbose/confusing for users.
cmd = [interp, "-c", "import sys; exec(sys.stdin.read())"]
proc = subprocess.Popen(cmd, stdin=subprocess.PIPE)
proc.communicate(input=script.encode("utf-8"))
if proc.returncode:
raise HookError("Failed to run %s hook." % (self._hook_type,))
def _ExecuteHookViaImport(self, data, context, **kwargs): def _ExecuteHookViaImport(self, data, context, **kwargs):
"""Execute the hook code in |data| directly. """Execute the hook code in |data| directly.
@ -412,30 +372,13 @@ context['main'](**kwargs)
# See what version of python the hook has been written against. # See what version of python the hook has been written against.
data = open(self._script_fullpath).read() data = open(self._script_fullpath).read()
interp = self._ExtractInterpFromShebang(data) interp = self._ExtractInterpFromShebang(data)
reexec = False
if interp: if interp:
prog = os.path.basename(interp) prog = os.path.basename(interp)
if prog.startswith("python2") and sys.version_info.major != 2: if prog.startswith("python2"):
reexec = True raise HookError("Python 2 is not supported")
elif prog.startswith("python3") and sys.version_info.major == 2:
reexec = True
# Attempt to execute the hooks through the requested version of
# Python.
if reexec:
try:
self._ExecuteHookViaReexec(interp, context, **kwargs)
except OSError as e:
if e.errno == errno.ENOENT:
# We couldn't find the interpreter, so fallback to
# importing.
reexec = False
else:
raise
# Run the hook by importing directly. # Run the hook by importing directly.
if not reexec: self._ExecuteHookViaImport(data, context, **kwargs)
self._ExecuteHookViaImport(data, context, **kwargs)
finally: finally:
# Restore sys.path and CWD. # Restore sys.path and CWD.
sys.path = orig_syspath sys.path = orig_syspath