mirror of
https://github.com/dredx/prole.git
synced 2026-09-23 12:03:59 +00:00
- Add build-context helper to copy Docker context safely (ignore runtime data, keep symlinks) - Update UI and core actions to use ~/.prole/build and shared copy helper - Add/adjust tests and scripts; introduce knoe ops helpers and update manifests Co-authored-by: Junie <junie@jetbrains.com>
94 lines
2.4 KiB
Python
94 lines
2.4 KiB
Python
from __future__ import annotations
|
|
|
|
import subprocess
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
from typing import Callable, Mapping, Sequence
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class CommandFailed(RuntimeError):
|
|
cmd: Sequence[str]
|
|
returncode: int
|
|
stdout: str
|
|
stderr: str
|
|
|
|
def __str__(self) -> str: # pragma: no cover
|
|
cmd_str = " ".join(self.cmd)
|
|
return f"Command failed ({self.returncode}): {cmd_str}"
|
|
|
|
|
|
def run(
|
|
cmd: Sequence[str],
|
|
*,
|
|
cwd: Path | None = None,
|
|
env: Mapping[str, str] | None = None,
|
|
input_text: str | None = None,
|
|
timeout: float | None = None,
|
|
) -> subprocess.CompletedProcess[str]:
|
|
return subprocess.run(
|
|
list(cmd),
|
|
cwd=str(cwd) if cwd is not None else None,
|
|
env=dict(env) if env is not None else None,
|
|
input=input_text,
|
|
text=True,
|
|
capture_output=True,
|
|
timeout=timeout,
|
|
)
|
|
|
|
|
|
def check(
|
|
cmd: Sequence[str],
|
|
*,
|
|
cwd: Path | None = None,
|
|
env: Mapping[str, str] | None = None,
|
|
input_text: str | None = None,
|
|
timeout: float | None = None,
|
|
) -> subprocess.CompletedProcess[str]:
|
|
proc = run(cmd, cwd=cwd, env=env, input_text=input_text, timeout=timeout)
|
|
if proc.returncode != 0:
|
|
raise CommandFailed(cmd=cmd, returncode=proc.returncode, stdout=proc.stdout, stderr=proc.stderr)
|
|
return proc
|
|
|
|
|
|
def run_streaming(
|
|
cmd: Sequence[str],
|
|
*,
|
|
cwd: Path | None = None,
|
|
env: Mapping[str, str] | None = None,
|
|
stdin_text: str | None = None,
|
|
on_line: Callable[[str], None] | None = None,
|
|
) -> int:
|
|
"""Run a subprocess and stream stdout/stderr lines to `on_line`.
|
|
|
|
Returns the process return code.
|
|
"""
|
|
|
|
p = subprocess.Popen(
|
|
list(cmd),
|
|
cwd=str(cwd) if cwd is not None else None,
|
|
env=dict(env) if env is not None else None,
|
|
stdin=subprocess.PIPE if stdin_text is not None else None,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.STDOUT,
|
|
text=True,
|
|
bufsize=1,
|
|
)
|
|
|
|
try:
|
|
if stdin_text is not None and p.stdin is not None:
|
|
p.stdin.write(stdin_text)
|
|
p.stdin.close()
|
|
|
|
if p.stdout is not None:
|
|
for line in p.stdout:
|
|
if on_line is not None:
|
|
on_line(line.rstrip("\n"))
|
|
return p.wait()
|
|
finally:
|
|
try:
|
|
if p.stdout is not None:
|
|
p.stdout.close()
|
|
except Exception:
|
|
pass
|