Repository navigation
Expand file tree
/
Copy pathcommand_utils.py
More file actions
83 lines (73 loc) · 2.63 KB
/
Copy pathcommand_utils.py
File metadata and controls
83 lines (73 loc) · 2.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import locale
import os
import subprocess
from pathlib import Path
COMMAND_TIMEOUT_SECONDS = 120
def _output_encoding() -> str:
return "oem" if os.name == "nt" else (locale.getpreferredencoding(False) or "utf-8")
def run_command(command: str, working_directory: str = "") -> dict:
command = str(command or "").strip()
if not command:
return {
"success": False,
"message": "Enter a command first.",
"output": "",
"exit_code": None,
}
try:
cwd = Path(working_directory).expanduser() if working_directory else Path.cwd()
cwd = cwd.resolve()
except (OSError, RuntimeError) as exc:
return {
"success": False,
"message": f"Invalid working directory: {exc}",
"output": "",
"exit_code": None,
}
if not cwd.is_dir():
return {
"success": False,
"message": f"Working directory does not exist: {cwd}",
"output": "",
"exit_code": None,
}
shell = os.environ.get("COMSPEC", "cmd.exe") if os.name == "nt" else "/bin/zsh"
shell_args = [shell, "/d", "/s", "/c", command] if os.name == "nt" else [shell, "-c", command]
creation_flags = getattr(subprocess, "CREATE_NO_WINDOW", 0)
try:
completed = subprocess.run(
shell_args,
cwd=str(cwd),
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
timeout=COMMAND_TIMEOUT_SECONDS,
check=False,
creationflags=creation_flags,
)
output = completed.stdout.decode(_output_encoding(), errors="replace")
return {
"success": completed.returncode == 0,
"message": "Command completed." if completed.returncode == 0 else "Command failed.",
"output": output,
"exit_code": completed.returncode,
"working_directory": str(cwd),
}
except subprocess.TimeoutExpired as exc:
partial_output = exc.stdout or b""
if isinstance(partial_output, bytes):
partial_output = partial_output.decode(_output_encoding(), errors="replace")
return {
"success": False,
"message": f"Command timed out after {COMMAND_TIMEOUT_SECONDS} seconds.",
"output": partial_output,
"exit_code": None,
"working_directory": str(cwd),
}
except OSError as exc:
return {
"success": False,
"message": f"Could not start command: {exc}",
"output": "",
"exit_code": None,
"working_directory": str(cwd),
}