summaryrefslogtreecommitdiffstats
path: root/hooks.py
diff options
context:
space:
mode:
Diffstat (limited to 'hooks.py')
-rw-r--r--hooks.py63
1 files changed, 3 insertions, 60 deletions
diff --git a/hooks.py b/hooks.py
index decf0699..337c2627 100644
--- a/hooks.py
+++ b/hooks.py
@@ -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
15import errno
16import json
17import os 15import os
18import re 16import re
19import subprocess
20import sys 17import sys
21import traceback 18import traceback
22import urllib.parse 19import 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 = """
316import json, os, sys
317path = '''%(path)s'''
318kwargs = json.loads('''%(kwargs)s''')
319context = json.loads('''%(context)s''')
320sys.path.insert(0, os.path.dirname(path))
321data = open(path).read()
322exec(compile(data, path, 'exec'), context)
323context['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