1
1
<?php
2
2
3
- class ProcessResult {
4
- public $ stdout ;
5
- public $ stderr ;
3
+ readonly class ProcessResult {
4
+ public function __construct (
5
+ public string $ stdout ,
6
+ public string $ stderr ,
7
+ ) {}
8
+ }
9
+
10
+ readonly class UnescapedArg {
11
+ public function __construct (
12
+ public string $ arg ,
13
+ ) {}
6
14
}
7
15
8
16
function runCommand (array $ args , ?string $ cwd = null ): ProcessResult {
9
- $ cmd = implode (' ' , array_map ('escapeshellarg ' , $ args ));
17
+ $ cmd = implode (' ' , array_map (function (string |UnescapedArg $ v ): string {
18
+ return $ v instanceof UnescapedArg
19
+ ? $ v ->arg
20
+ : escapeshellarg ($ v );
21
+ }, $ args ));
10
22
$ pipes = null ;
11
- $ result = new ProcessResult ();
12
23
$ descriptorSpec = [0 => ['pipe ' , 'r ' ], 1 => ['pipe ' , 'w ' ], 2 => ['pipe ' , 'w ' ]];
13
24
fwrite (STDOUT , "> $ cmd \n" );
14
25
$ processHandle = proc_open ($ cmd , $ descriptorSpec , $ pipes , $ cwd ?? getcwd (), null );
@@ -22,6 +33,8 @@ function runCommand(array $args, ?string $cwd = null): ProcessResult {
22
33
stream_set_blocking ($ stdout , false );
23
34
stream_set_blocking ($ stderr , false );
24
35
36
+ $ stdoutStr = '' ;
37
+ $ stderrStr = '' ;
25
38
$ stdoutEof = false ;
26
39
$ stderrEof = false ;
27
40
@@ -35,9 +48,9 @@ function runCommand(array $args, ?string $cwd = null): ProcessResult {
35
48
foreach ($ read as $ stream ) {
36
49
$ chunk = fgets ($ stream );
37
50
if ($ stream === $ stdout ) {
38
- $ result -> stdout .= $ chunk ;
51
+ $ stdoutStr .= $ chunk ;
39
52
} elseif ($ stream === $ stderr ) {
40
- $ result -> stderr .= $ chunk ;
53
+ $ stderrStr .= $ chunk ;
41
54
}
42
55
}
43
56
@@ -47,6 +60,8 @@ function runCommand(array $args, ?string $cwd = null): ProcessResult {
47
60
48
61
fclose ($ stdout );
49
62
fclose ($ stderr );
63
+
64
+ $ result = new ProcessResult ($ stdoutStr , $ stderrStr );
50
65
51
66
$ statusCode = proc_close ($ processHandle );
52
67
if ($ statusCode !== 0 ) {
0 commit comments