75 lines
2.5 KiB
Python
75 lines
2.5 KiB
Python
# #region Tooling.DrRecovery.Git.Runner [C:3] [TYPE Module] [SEMANTICS dr,recovery]
|
|
# @BRIEF Run bounded local Git subprocesses with closed configuration and owned process-group cleanup.
|
|
import os
|
|
import resource
|
|
import signal
|
|
import subprocess
|
|
import tempfile
|
|
from dr_recovery_io import Refused, require
|
|
|
|
# #region Tooling.DrRecovery.Git.Runner.Limits [C:3] [TYPE Function] [SEMANTICS dr,recovery]
|
|
def _limits():
|
|
resource.setrlimit(resource.RLIMIT_CPU, (30, 30))
|
|
resource.setrlimit(resource.RLIMIT_FSIZE, (128 * 1024 * 1024, 128 * 1024 * 1024))
|
|
resource.setrlimit(resource.RLIMIT_AS, (1024 * 1024 * 1024, 1024 * 1024 * 1024))
|
|
# #endregion Tooling.DrRecovery.Git.Runner.Limits
|
|
|
|
|
|
# #region Tooling.DrRecovery.Git.Command [C:3] [TYPE Function]
|
|
def git(root, args, code, output_limit=128 * 1024):
|
|
env = dict(
|
|
PATH="/usr/bin:/bin",
|
|
HOME="/nonexistent",
|
|
GIT_CONFIG_NOSYSTEM="1",
|
|
GIT_CONFIG_GLOBAL="/dev/null",
|
|
GIT_CONFIG_SYSTEM="/dev/null",
|
|
GIT_TERMINAL_PROMPT="0",
|
|
GIT_CONFIG_COUNT="0",
|
|
GIT_NO_REPLACE_OBJECTS="1",
|
|
GIT_OPTIONAL_LOCKS="0",
|
|
GIT_NO_LAZY_FETCH="1",
|
|
)
|
|
command = [
|
|
"/usr/bin/git",
|
|
"--git-dir=" + str(root),
|
|
"-c",
|
|
"protocol.allow=never",
|
|
"-c",
|
|
"core.hooksPath=/dev/null",
|
|
*args,
|
|
]
|
|
with tempfile.TemporaryFile() as stdout, tempfile.TemporaryFile() as stderr:
|
|
try:
|
|
process = subprocess.Popen(
|
|
command,
|
|
env=env,
|
|
stdin=subprocess.DEVNULL,
|
|
stdout=stdout,
|
|
stderr=stderr,
|
|
start_new_session=True,
|
|
preexec_fn=_limits,
|
|
)
|
|
except (OSError, subprocess.SubprocessError):
|
|
raise Refused("DR_RECOVERY_GIT_UNAVAILABLE") from None
|
|
try:
|
|
result = process.wait(timeout=30)
|
|
except subprocess.TimeoutExpired:
|
|
try:
|
|
os.killpg(process.pid, signal.SIGKILL)
|
|
except ProcessLookupError:
|
|
pass # The owned child/group can exit between the timeout and kill.
|
|
process.wait()
|
|
raise Refused("DR_RECOVERY_LIMIT") from None
|
|
require(result >= 0, "DR_RECOVERY_LIMIT")
|
|
require(result == 0, code)
|
|
require(
|
|
stdout.tell() <= output_limit and stderr.tell() <= 128 * 1024,
|
|
"DR_RECOVERY_LIMIT",
|
|
)
|
|
stdout.seek(0)
|
|
return stdout.read(output_limit + 1)
|
|
|
|
|
|
# #endregion Tooling.DrRecovery.Git.Command
|
|
# #endregion Tooling.DrRecovery.Git.Runner
|