aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe-external-packages/src/symfony/console
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-06-24 03:09:17 +0900
committernsfisis <nsfisis@gmail.com>2026-06-24 03:09:17 +0900
commitc5fc34a106a706ac12925c4df273a926811d260b (patch)
tree24e798c4a00b32aa1a1f155b705d02fba9895875 /crates/shirabe-external-packages/src/symfony/console
parentb2b321a26f6a628ee8e6757eb8577613e2024e70 (diff)
downloadphp-shirabe-c5fc34a106a706ac12925c4df273a926811d260b.tar.gz
php-shirabe-c5fc34a106a706ac12925c4df273a926811d260b.tar.zst
php-shirabe-c5fc34a106a706ac12925c4df273a926811d260b.zip
feat(process): redesign proc_* on PhpResource process handles
proc_open/proc_close/proc_get_status/proc_terminate represented the process handle as a PhpMixed, which cannot hold a live child process or its pipes, so they were stubs or todo!(). Model the handle as a new PhpResource::Process variant and child pipes as a StreamBacking::Pipe, with a native Descriptor enum for descriptorspec; proc_open now returns io::Result and fills pipes as IndexMap<i64, PhpResource>. Rewire the Symfony Process pipes and the Console terminal/cursor onto the new types, removing the "PhpMixed cannot carry a PhpResource" todo!()s. The remaining todo!()s are genuine syscall leaves (proc_terminate signal delivery, stream_select, stream_set_blocking, posix_kill, pty, fd>=3) left unimplemented since no syscall crate is introduced. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe-external-packages/src/symfony/console')
-rw-r--r--crates/shirabe-external-packages/src/symfony/console/cursor.rs27
-rw-r--r--crates/shirabe-external-packages/src/symfony/console/helper/question_helper.rs15
-rw-r--r--crates/shirabe-external-packages/src/symfony/console/terminal.rs67
3 files changed, 49 insertions, 60 deletions
diff --git a/crates/shirabe-external-packages/src/symfony/console/cursor.rs b/crates/shirabe-external-packages/src/symfony/console/cursor.rs
index 811553f..c36f9b5 100644
--- a/crates/shirabe-external-packages/src/symfony/console/cursor.rs
+++ b/crates/shirabe-external-packages/src/symfony/console/cursor.rs
@@ -181,31 +181,20 @@ impl Cursor {
let is_tty_supported = if shirabe_php_shim::function_exists("proc_open") {
*IS_TTY_SUPPORTED.get_or_init(|| {
- let mut pipes = shirabe_php_shim::PhpMixed::Null;
- shirabe_php_shim::php_truthy(&shirabe_php_shim::proc_open(
+ let mut pipes = indexmap::IndexMap::new();
+ shirabe_php_shim::proc_open(
"echo 1 >/dev/null",
- &vec![
- shirabe_php_shim::PhpMixed::List(vec![
- shirabe_php_shim::PhpMixed::String("file".to_string()),
- shirabe_php_shim::PhpMixed::String("/dev/tty".to_string()),
- shirabe_php_shim::PhpMixed::String("r".to_string()),
- ]),
- shirabe_php_shim::PhpMixed::List(vec![
- shirabe_php_shim::PhpMixed::String("file".to_string()),
- shirabe_php_shim::PhpMixed::String("/dev/tty".to_string()),
- shirabe_php_shim::PhpMixed::String("w".to_string()),
- ]),
- shirabe_php_shim::PhpMixed::List(vec![
- shirabe_php_shim::PhpMixed::String("file".to_string()),
- shirabe_php_shim::PhpMixed::String("/dev/tty".to_string()),
- shirabe_php_shim::PhpMixed::String("w".to_string()),
- ]),
+ &[
+ shirabe_php_shim::Descriptor::File("/dev/tty".to_string(), "r".to_string()),
+ shirabe_php_shim::Descriptor::File("/dev/tty".to_string(), "w".to_string()),
+ shirabe_php_shim::Descriptor::File("/dev/tty".to_string(), "w".to_string()),
],
&mut pipes,
None,
None,
None,
- ))
+ )
+ .is_ok()
})
} else {
false
diff --git a/crates/shirabe-external-packages/src/symfony/console/helper/question_helper.rs b/crates/shirabe-external-packages/src/symfony/console/helper/question_helper.rs
index 1fc90bd..2bdd929 100644
--- a/crates/shirabe-external-packages/src/symfony/console/helper/question_helper.rs
+++ b/crates/shirabe-external-packages/src/symfony/console/helper/question_helper.rs
@@ -377,13 +377,14 @@ impl QuestionHelper {
// Read a keypress
while !shirabe_php_shim::feof(input_stream) {
while is_stdin
- && 0 == shirabe_php_shim::stream_select(
- &mut r,
- &mut w.clone(),
- &mut w.clone(),
- 0,
- Some(100),
- )
+ && Some(0)
+ == shirabe_php_shim::stream_select(
+ &mut r,
+ &mut w.clone(),
+ &mut w.clone(),
+ 0,
+ Some(100),
+ )
{
// Give signal handlers a chance to run
r = vec![input_stream.clone()];
diff --git a/crates/shirabe-external-packages/src/symfony/console/terminal.rs b/crates/shirabe-external-packages/src/symfony/console/terminal.rs
index ac4009e..c02b87f 100644
--- a/crates/shirabe-external-packages/src/symfony/console/terminal.rs
+++ b/crates/shirabe-external-packages/src/symfony/console/terminal.rs
@@ -208,49 +208,48 @@ impl Terminal {
return None;
}
- let descriptorspec: Vec<PhpMixed> = vec![
- PhpMixed::List(vec![
- PhpMixed::String("pipe".to_string()),
- PhpMixed::String("w".to_string()),
- ]),
- PhpMixed::List(vec![
- PhpMixed::String("pipe".to_string()),
- PhpMixed::String("w".to_string()),
- ]),
+ // Sparse PHP descriptorspec `[1 => ['pipe', 'w'], 2 => ['pipe', 'w']]`: fd 0 is inherited.
+ let descriptorspec = [
+ shirabe_php_shim::Descriptor::Inherit,
+ shirabe_php_shim::Descriptor::Pipe("w".to_string()),
+ shirabe_php_shim::Descriptor::Pipe("w".to_string()),
];
- let _cp = if shirabe_php_shim::function_exists("sapi_windows_cp_set") {
+ let cp = if shirabe_php_shim::function_exists("sapi_windows_cp_set") {
shirabe_php_shim::sapi_windows_cp_get(None)
} else {
0
};
- let mut pipes = PhpMixed::Null;
- let process =
- shirabe_php_shim::proc_open(command, &descriptorspec, &mut pipes, None, None, None);
- if !shirabe_php_shim::php_truthy(&process) {
- return None;
+ let mut pipes: indexmap::IndexMap<i64, shirabe_php_shim::PhpResource> =
+ indexmap::IndexMap::new();
+ let process = match shirabe_php_shim::proc_open(
+ command,
+ &descriptorspec,
+ &mut pipes,
+ None,
+ None,
+ None,
+ ) {
+ Ok(process) => process,
+ Err(_) => return None,
+ };
+
+ let info = pipes
+ .get(&1)
+ .and_then(shirabe_php_shim::stream_get_contents);
+ if let Some(pipe) = pipes.get(&1) {
+ shirabe_php_shim::fclose(pipe);
}
+ if let Some(pipe) = pipes.get(&2) {
+ shirabe_php_shim::fclose(pipe);
+ }
+ shirabe_php_shim::proc_close(&process);
- // $pipes[1] and $pipes[2] from proc_open's output array.
- let _pipe1 = php_pipe(&pipes, 1);
- let _pipe2 = php_pipe(&pipes, 2);
- // TODO(phase-d): the pipe contents are read via stream_get_contents() and the pipes are
- // fclose()d, but they are PHP stream resources the PhpMixed pipe list cannot hold.
- todo!(
- "Terminal: reading proc_open pipes needs PhpResource handles the PhpMixed pipe list cannot carry"
- );
- }
-}
+ if cp != 0 {
+ shirabe_php_shim::sapi_windows_cp_set(cp);
+ }
-/// Indexes into the `$pipes` array populated by proc_open.
-fn php_pipe(pipes: &PhpMixed, index: i64) -> PhpMixed {
- match pipes {
- PhpMixed::List(list) => list.get(index as usize).cloned().unwrap_or(PhpMixed::Null),
- PhpMixed::Array(array) => array
- .get(&index.to_string())
- .map(|v| v.clone())
- .unwrap_or(PhpMixed::Null),
- _ => PhpMixed::Null,
+ info
}
}