diff options
| author | Mike Frysinger <vapier@google.com> | 2023-10-14 01:25:50 +0545 |
|---|---|---|
| committer | LUCI <gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-10-13 20:52:46 +0000 |
| commit | 3b8f9535c772178d8adeb1e0e4fc5916e311490a (patch) | |
| tree | da9f8c3bcf723d6ed0019b8d3ce3461c50894555 | |
| parent | 8f4f98582ef5f99db96e383400c3acf85e0eeb52 (diff) | |
| download | git-repo-3b8f9535c772178d8adeb1e0e4fc5916e311490a.tar.gz | |
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>
| -rw-r--r-- | hooks.py | 63 |
1 files changed, 3 insertions, 60 deletions
| @@ -12,11 +12,8 @@ | |||
| 12 | # See the License for the specific language governing permissions and | 12 | # See the License for the specific language governing permissions and |
| 13 | # limitations under the License. | 13 | # limitations under the License. |
| 14 | 14 | ||
| 15 | import errno | ||
| 16 | import json | ||
| 17 | import os | 15 | import os |
| 18 | import re | 16 | import re |
| 19 | import subprocess | ||
| 20 | import sys | 17 | import sys |
| 21 | import traceback | 18 | import traceback |
| 22 | import urllib.parse | 19 | import urllib.parse |
| @@ -298,43 +295,6 @@ class RepoHook(object): | |||
| 298 | 295 | ||
| 299 | return interp | 296 | return interp |
| 300 | 297 | ||
| 301 | def _ExecuteHookViaReexec(self, interp, context, **kwargs): | ||
| 302 | """Execute the hook script through |interp|. | ||
| 303 | |||
| 304 | Note: Support for this feature should be dropped ~Jun 2021. | ||
| 305 | |||
| 306 | Args: | ||
| 307 | interp: The Python program to run. | ||
| 308 | context: Basic Python context to execute the hook inside. | ||
| 309 | kwargs: Arbitrary arguments to pass to the hook script. | ||
| 310 | |||
| 311 | Raises: | ||
| 312 | HookError: When the hooks failed for any reason. | ||
| 313 | """ | ||
| 314 | # This logic needs to be kept in sync with _ExecuteHookViaImport below. | ||
| 315 | script = """ | ||
| 316 | import json, os, sys | ||
| 317 | path = '''%(path)s''' | ||
| 318 | kwargs = json.loads('''%(kwargs)s''') | ||
| 319 | context = json.loads('''%(context)s''') | ||
| 320 | sys.path.insert(0, os.path.dirname(path)) | ||
| 321 | data = open(path).read() | ||
| 322 | exec(compile(data, path, 'exec'), context) | ||
| 323 | context['main'](**kwargs) | ||
| 324 | """ % { | ||
| 325 | "path": self._script_fullpath, | ||
| 326 | "kwargs": json.dumps(kwargs), | ||
| 327 | "context": json.dumps(context), | ||
| 328 | } | ||
| 329 | |||
| 330 | # We pass the script via stdin to avoid OS argv limits. It also makes | ||
| 331 | # unhandled exception tracebacks less verbose/confusing for users. | ||
| 332 | cmd = [interp, "-c", "import sys; exec(sys.stdin.read())"] | ||
| 333 | proc = subprocess.Popen(cmd, stdin=subprocess.PIPE) | ||
| 334 | proc.communicate(input=script.encode("utf-8")) | ||
| 335 | if proc.returncode: | ||
| 336 | raise HookError("Failed to run %s hook." % (self._hook_type,)) | ||
| 337 | |||
| 338 | def _ExecuteHookViaImport(self, data, context, **kwargs): | 298 | def _ExecuteHookViaImport(self, data, context, **kwargs): |
| 339 | """Execute the hook code in |data| directly. | 299 | """Execute the hook code in |data| directly. |
| 340 | 300 | ||
| @@ -412,30 +372,13 @@ context['main'](**kwargs) | |||
| 412 | # See what version of python the hook has been written against. | 372 | # See what version of python the hook has been written against. |
| 413 | data = open(self._script_fullpath).read() | 373 | data = open(self._script_fullpath).read() |
| 414 | interp = self._ExtractInterpFromShebang(data) | 374 | interp = self._ExtractInterpFromShebang(data) |
| 415 | reexec = False | ||
| 416 | if interp: | 375 | if interp: |
| 417 | prog = os.path.basename(interp) | 376 | prog = os.path.basename(interp) |
| 418 | if prog.startswith("python2") and sys.version_info.major != 2: | 377 | if prog.startswith("python2"): |
| 419 | reexec = True | 378 | raise HookError("Python 2 is not supported") |
| 420 | elif prog.startswith("python3") and sys.version_info.major == 2: | ||
| 421 | reexec = True | ||
| 422 | |||
| 423 | # Attempt to execute the hooks through the requested version of | ||
| 424 | # Python. | ||
| 425 | if reexec: | ||
| 426 | try: | ||
| 427 | self._ExecuteHookViaReexec(interp, context, **kwargs) | ||
| 428 | except OSError as e: | ||
| 429 | if e.errno == errno.ENOENT: | ||
| 430 | # We couldn't find the interpreter, so fallback to | ||
| 431 | # importing. | ||
| 432 | reexec = False | ||
| 433 | else: | ||
| 434 | raise | ||
| 435 | 379 | ||
| 436 | # Run the hook by importing directly. | 380 | # Run the hook by importing directly. |
| 437 | if not reexec: | 381 | self._ExecuteHookViaImport(data, context, **kwargs) |
| 438 | self._ExecuteHookViaImport(data, context, **kwargs) | ||
| 439 | finally: | 382 | finally: |
| 440 | # Restore sys.path and CWD. | 383 | # Restore sys.path and CWD. |
| 441 | sys.path = orig_syspath | 384 | sys.path = orig_syspath |
