From e6cc7371d1685f648e52882568c8330373b6c090 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Fri, 24 Jul 2026 00:38:59 +0900 Subject: refactor(symfony-process): remove unused Process API surface Since Process is php-native with no Rust-fidelity obligation (see plugin-class-classification.md), this port only needs to cover what Rust-ported Composer code actually calls. Made the pipes/process_utils modules pub(crate) (nothing outside symfony/process used them) and rebuilt with `--force-warn dead_code` (normally allowed workspace-wide) to find genuinely unreachable methods: Process lost 17 methods, 5 constants, and a private clone helper; ExecutableFinder lost two unused suffix setters; AbstractPipes lost handle_error, whose only caller (a stream_select error-handler registration) was never wired up. Removing several of those setters (set_pty, set_idle_timeout, disable_output/enable_output, set_options) then left the fields they used to write with no remaining writer, so they hold one constant value on every reachable path: pty always false, idle_timeout always None, output_disabled always false, options always {suppress_errors, bypass_shell}. Audited by value (not just call-graph reachability) and removed everything that depended on the now-constant value: - pty: is_pty(), is_pty_supported(), the PTY descriptor branch in UnixPipes::get_descriptors(), and the now-unconstructed Descriptor::Pty variant in shirabe-php-shim (plus its proc_open match arm). - idle_timeout: get_idle_timeout() and check_timeout()'s idle branch; ProcessTimedOutException collapses to the single reachable timeout type (dropped timeout_type/TYPE_GENERAL/TYPE_IDLE/is_general_timeout/ is_idle_timeout/get_exceeded_timeout). - output_disabled: is_output_disabled(), build_callback()'s disabled variant, get_descriptors()'s output_disabled term, and the always-false guard in read_pipes_for_output()/ProcessFailedException (its output section is now unconditional). - options: Drop::drop()'s create_new_console branch can never fire (that key can no longer exist), so it always just stops the process. - has_callback/last_output_time: left write-only once their only readers (the branches above) were gone. - have_read_support: constant true once output_disabled collapsed, so removed from PipesInterface, UnixPipes (incl. its /dev/null null-stream branch), WindowsPipes, and Process::wait()'s dead guard. No behavior change: every removed item/branch had zero callers, or was constant on every reachable call site. --- .../src/symfony/process.rs | 6 +- .../process/exception/process_failed_exception.rs | 12 +- .../exception/process_timed_out_exception.rs | 32 +- .../src/symfony/process/executable_finder.rs | 10 - .../src/symfony/process/pipes.rs | 5 - .../src/symfony/process/pipes/abstract_pipes.rs | 4 - .../src/symfony/process/pipes/pipes_interface.rs | 3 - .../src/symfony/process/pipes/unix_pipes.rs | 34 +- .../src/symfony/process/pipes/windows_pipes.rs | 7 +- .../src/symfony/process/process.rs | 535 +-------------------- 10 files changed, 15 insertions(+), 633 deletions(-) (limited to 'crates/shirabe-external-packages/src/symfony') diff --git a/crates/shirabe-external-packages/src/symfony/process.rs b/crates/shirabe-external-packages/src/symfony/process.rs index 15967bef..3a5656c6 100644 --- a/crates/shirabe-external-packages/src/symfony/process.rs +++ b/crates/shirabe-external-packages/src/symfony/process.rs @@ -1,13 +1,11 @@ pub mod exception; pub mod executable_finder; pub mod php_executable_finder; -pub mod pipes; +pub(crate) mod pipes; pub mod process; -pub mod process_utils; +pub(crate) mod process_utils; pub use exception::*; pub use executable_finder::*; pub use php_executable_finder::*; -pub use pipes::*; pub use process::*; -pub use process_utils::*; diff --git a/crates/shirabe-external-packages/src/symfony/process/exception/process_failed_exception.rs b/crates/shirabe-external-packages/src/symfony/process/exception/process_failed_exception.rs index a3645d62..b99e876a 100644 --- a/crates/shirabe-external-packages/src/symfony/process/exception/process_failed_exception.rs +++ b/crates/shirabe-external-packages/src/symfony/process/exception/process_failed_exception.rs @@ -29,13 +29,11 @@ impl ProcessFailedException { process.get_working_directory().unwrap_or_default(), ); - if !process.is_output_disabled() { - error += &format!( - "\n\nOutput:\n================\n{}\n\nError Output:\n================\n{}", - process.get_output()?, - process.get_error_output()?, - ); - } + error += &format!( + "\n\nOutput:\n================\n{}\n\nError Output:\n================\n{}", + process.get_output()?, + process.get_error_output()?, + ); Ok(Self { message: error, diff --git a/crates/shirabe-external-packages/src/symfony/process/exception/process_timed_out_exception.rs b/crates/shirabe-external-packages/src/symfony/process/exception/process_timed_out_exception.rs index 45cb6939..46564c37 100644 --- a/crates/shirabe-external-packages/src/symfony/process/exception/process_timed_out_exception.rs +++ b/crates/shirabe-external-packages/src/symfony/process/exception/process_timed_out_exception.rs @@ -6,20 +6,11 @@ use crate::symfony::process::process::Process; pub struct ProcessTimedOutException { pub message: String, pub code: i64, - timeout_type: i64, - exceeded_timeout: Option, } impl ProcessTimedOutException { - pub const TYPE_GENERAL: i64 = 1; - pub const TYPE_IDLE: i64 = 2; - - pub fn new(process: &Process, timeout_type: i64) -> Self { - let exceeded_timeout = match timeout_type { - Self::TYPE_GENERAL => process.get_timeout(), - Self::TYPE_IDLE => process.get_idle_timeout(), - _ => panic!("Unknown timeout type \"{}\".", timeout_type), - }; + pub fn new(process: &Process) -> Self { + let exceeded_timeout = process.get_timeout(); let message = format!( "The process \"{}\" exceeded the timeout of {} seconds.", @@ -27,24 +18,7 @@ impl ProcessTimedOutException { exceeded_timeout.map(|t| t.to_string()).unwrap_or_default(), ); - Self { - message, - code: 0, - timeout_type, - exceeded_timeout, - } - } - - pub fn is_general_timeout(&self) -> bool { - Self::TYPE_GENERAL == self.timeout_type - } - - pub fn is_idle_timeout(&self) -> bool { - Self::TYPE_IDLE == self.timeout_type - } - - pub fn get_exceeded_timeout(&self) -> Option { - self.exceeded_timeout + Self { message, code: 0 } } } diff --git a/crates/shirabe-external-packages/src/symfony/process/executable_finder.rs b/crates/shirabe-external-packages/src/symfony/process/executable_finder.rs index 3396b29b..d4891af0 100644 --- a/crates/shirabe-external-packages/src/symfony/process/executable_finder.rs +++ b/crates/shirabe-external-packages/src/symfony/process/executable_finder.rs @@ -25,16 +25,6 @@ impl ExecutableFinder { Self { suffixes: vec![] } } - /// Replaces default suffixes of executable. - pub fn set_suffixes(&mut self, suffixes: Vec) { - self.suffixes = suffixes; - } - - /// Adds new possible suffix to check for executable. - pub fn add_suffix(&mut self, suffix: &str) { - self.suffixes.push(suffix.to_string()); - } - pub fn find(&self, name: &str, default: Option<&str>, extra_dirs: &[String]) -> Option { // windows built-in commands that are present in cmd.exe should not be resolved using PATH as they do not exist as exes if shirabe_php_shim::DIRECTORY_SEPARATOR == "\\" diff --git a/crates/shirabe-external-packages/src/symfony/process/pipes.rs b/crates/shirabe-external-packages/src/symfony/process/pipes.rs index 6a77f5f0..6c3ea7dd 100644 --- a/crates/shirabe-external-packages/src/symfony/process/pipes.rs +++ b/crates/shirabe-external-packages/src/symfony/process/pipes.rs @@ -2,8 +2,3 @@ pub mod abstract_pipes; pub mod pipes_interface; pub mod unix_pipes; pub mod windows_pipes; - -pub use abstract_pipes::*; -pub use pipes_interface::*; -pub use unix_pipes::*; -pub use windows_pipes::*; diff --git a/crates/shirabe-external-packages/src/symfony/process/pipes/abstract_pipes.rs b/crates/shirabe-external-packages/src/symfony/process/pipes/abstract_pipes.rs index f9fb251d..8741926c 100644 --- a/crates/shirabe-external-packages/src/symfony/process/pipes/abstract_pipes.rs +++ b/crates/shirabe-external-packages/src/symfony/process/pipes/abstract_pipes.rs @@ -101,8 +101,4 @@ impl AbstractPipes { None } - - pub fn handle_error(&mut self, _type: i64, msg: String) { - self.last_error = Some(msg); - } } diff --git a/crates/shirabe-external-packages/src/symfony/process/pipes/pipes_interface.rs b/crates/shirabe-external-packages/src/symfony/process/pipes/pipes_interface.rs index 92d584d8..46609bb8 100644 --- a/crates/shirabe-external-packages/src/symfony/process/pipes/pipes_interface.rs +++ b/crates/shirabe-external-packages/src/symfony/process/pipes/pipes_interface.rs @@ -19,9 +19,6 @@ pub trait PipesInterface: std::fmt::Debug { /// Returns if the current state has open file handles or pipes. fn are_open(&self) -> bool; - /// Returns if pipes are able to read output. - fn have_read_support(&self) -> bool; - /// Closes file handles and pipes. fn close(&mut self); diff --git a/crates/shirabe-external-packages/src/symfony/process/pipes/unix_pipes.rs b/crates/shirabe-external-packages/src/symfony/process/pipes/unix_pipes.rs index aff2a544..a7026318 100644 --- a/crates/shirabe-external-packages/src/symfony/process/pipes/unix_pipes.rs +++ b/crates/shirabe-external-packages/src/symfony/process/pipes/unix_pipes.rs @@ -11,22 +11,13 @@ use shirabe_php_shim::{Descriptor, PhpMixed, PhpResource}; pub struct UnixPipes { inner: AbstractPipes, tty_mode: Option, - pty_mode: bool, - have_read_support: bool, } impl UnixPipes { - pub fn new( - tty_mode: Option, - pty_mode: bool, - input: PhpMixed, - have_read_support: bool, - ) -> Self { + pub fn new(tty_mode: Option, input: PhpMixed) -> Self { Self { inner: AbstractPipes::new(input), tty_mode, - pty_mode, - have_read_support, } } } @@ -35,23 +26,12 @@ fn descriptor(items: &[&str]) -> Descriptor { match items { ["pipe", mode] => Descriptor::Pipe(mode.to_string()), ["file", path, mode] => Descriptor::File(path.to_string(), mode.to_string()), - ["pty"] => Descriptor::Pty, _ => panic!("unsupported descriptor spec: {:?}", items), } } impl PipesInterface for UnixPipes { fn get_descriptors(&mut self) -> Vec { - if !self.have_read_support { - let nullstream = - shirabe_php_shim::fopen("/dev/null", "c").expect("fopen('/dev/null') failed"); - return vec![ - descriptor(&["pipe", "r"]), - Descriptor::Resource(nullstream.clone()), - Descriptor::Resource(nullstream), - ]; - } - if self.tty_mode == Some(true) { return vec![ descriptor(&["file", "/dev/tty", "r"]), @@ -60,14 +40,6 @@ impl PipesInterface for UnixPipes { ]; } - if self.pty_mode && Process::is_pty_supported() { - return vec![ - descriptor(&["pty"]), - descriptor(&["pty"]), - descriptor(&["pty"]), - ]; - } - vec![ descriptor(&["pipe", "r"]), descriptor(&["pipe", "w"]), @@ -146,10 +118,6 @@ impl PipesInterface for UnixPipes { read } - fn have_read_support(&self) -> bool { - self.have_read_support - } - fn are_open(&self) -> bool { !self.inner.pipes.is_empty() } diff --git a/crates/shirabe-external-packages/src/symfony/process/pipes/windows_pipes.rs b/crates/shirabe-external-packages/src/symfony/process/pipes/windows_pipes.rs index f721d2b4..72a28e7d 100644 --- a/crates/shirabe-external-packages/src/symfony/process/pipes/windows_pipes.rs +++ b/crates/shirabe-external-packages/src/symfony/process/pipes/windows_pipes.rs @@ -13,11 +13,10 @@ pub struct WindowsPipes { file_handles: IndexMap, lock_handles: IndexMap, read_bytes: IndexMap, - have_read_support: bool, } impl WindowsPipes { - pub fn new(_input: PhpMixed, _have_read_support: bool) -> Self { + pub fn new(_input: PhpMixed) -> Self { // Windows-only path: never constructed on POSIX (DIRECTORY_SEPARATOR is "/"). todo!() } @@ -42,10 +41,6 @@ impl PipesInterface for WindowsPipes { todo!() } - fn have_read_support(&self) -> bool { - self.have_read_support - } - fn are_open(&self) -> bool { !self.inner.pipes.is_empty() && !self.file_handles.is_empty() } diff --git a/crates/shirabe-external-packages/src/symfony/process/process.rs b/crates/shirabe-external-packages/src/symfony/process/process.rs index 5c817c85..5d73c108 100644 --- a/crates/shirabe-external-packages/src/symfony/process/process.rs +++ b/crates/shirabe-external-packages/src/symfony/process/process.rs @@ -2,7 +2,6 @@ use crate::symfony::process::exception::invalid_argument_exception::InvalidArgumentException; use crate::symfony::process::exception::logic_exception::LogicException; -use crate::symfony::process::exception::process_failed_exception::ProcessFailedException; use crate::symfony::process::exception::process_signaled_exception::ProcessSignaledException; use crate::symfony::process::exception::process_timed_out_exception::ProcessTimedOutException; use crate::symfony::process::exception::runtime_exception::RuntimeException; @@ -45,19 +44,15 @@ pub struct ProcessMock { /// start independent PHP processes. pub struct Process { callback: Option, - has_callback: bool, commandline: CommandLine, cwd: Option, env: IndexMap, input: PhpMixed, starttime: Option, - last_output_time: Option, timeout: Option, - idle_timeout: Option, exitcode: Option, fallback_status: IndexMap, process_information: Option>, - output_disabled: bool, stdout: Option, stderr: Option, process: Option, @@ -65,7 +60,6 @@ pub struct Process { incremental_output_offset: i64, incremental_error_output_offset: i64, tty: bool, - pty: bool, options: IndexMap, use_file_handles: bool, process_pipes: Option>, @@ -90,7 +84,6 @@ fn descriptor(items: &[&str]) -> Descriptor { match items { ["pipe", mode] => Descriptor::Pipe(mode.to_string()), ["file", path, mode] => Descriptor::File(path.to_string(), mode.to_string()), - ["pty"] => Descriptor::Pty, _ => panic!("unsupported descriptor spec: {:?}", items), } } @@ -120,18 +113,12 @@ impl Process { pub const STATUS_STARTED: &'static str = "started"; pub const STATUS_TERMINATED: &'static str = "terminated"; - pub const STDIN: i64 = 0; pub const STDOUT: i64 = 1; pub const STDERR: i64 = 2; // Timeout Precision in seconds. pub const TIMEOUT_PRECISION: f64 = 0.2; - pub const ITER_NON_BLOCKING: i64 = 1; - pub const ITER_KEEP_OUTPUT: i64 = 2; - pub const ITER_SKIP_OUT: i64 = 4; - pub const ITER_SKIP_ERR: i64 = 8; - /// Exit codes translation table. fn exit_code_text(code: i64) -> Option<&'static str> { Some(match code { @@ -186,19 +173,15 @@ impl Process { Self { callback: None, - has_callback: false, commandline: CommandLine::Array(Vec::new()), cwd: None, env: IndexMap::new(), input: PhpMixed::Null, starttime: None, - last_output_time: None, timeout: None, - idle_timeout: None, exitcode: None, fallback_status: IndexMap::new(), process_information: None, - output_disabled: false, stdout: None, stderr: None, process: None, @@ -206,7 +189,6 @@ impl Process { incremental_output_offset: 0, incremental_error_output_offset: 0, tty: false, - pty: false, options, use_file_handles: false, process_pipes: None, @@ -264,7 +246,6 @@ impl Process { this.set_input(input)?; this.set_timeout(timeout)?; this.use_file_handles = shirabe_php_shim::DIRECTORY_SEPARATOR == "\\"; - this.pty = false; Ok(this) } @@ -283,22 +264,6 @@ impl Process { Ok(process) } - pub fn __sleep(&self) -> anyhow::Result> { - Err(shirabe_php_shim::BadMethodCallException { - message: "Cannot serialize Symfony\\Component\\Process\\Process".to_string(), - code: 0, - } - .into()) - } - - pub fn __wakeup(&self) -> anyhow::Result<()> { - Err(shirabe_php_shim::BadMethodCallException { - message: "Cannot unserialize Symfony\\Component\\Process\\Process".to_string(), - code: 0, - } - .into()) - } - /// Runs the process. pub fn run( &mut self, @@ -310,19 +275,6 @@ impl Process { self.wait(None) } - /// Runs the process and throws if it exits with a non-zero exit code. - pub fn must_run( - &mut self, - callback: Option, - env: IndexMap, - ) -> anyhow::Result<&mut Self> { - if 0 != self.run(callback, env)? { - return Err(ProcessFailedException::new(self)?.into()); - } - - Ok(self) - } - /// Starts the process and returns after writing the input to STDIN. pub fn start( &mut self, @@ -335,10 +287,7 @@ impl Process { self.reset_process_data(); self.starttime = Some(shirabe_php_shim::microtime()); - self.last_output_time = self.starttime; - let has_callback = callback.is_some(); self.callback = Some(self.build_callback(callback)); - self.has_callback = has_callback; let mut descriptors = self.get_descriptors(); if !self.env.is_empty() { @@ -452,22 +401,6 @@ impl Process { Ok(()) } - /// Restarts the process. The process is cloned before being started. - pub fn restart( - &mut self, - callback: Option, - env: IndexMap, - ) -> anyhow::Result { - if self.is_running() { - return Err(RuntimeException::new("Process is already running.".to_string()).into()); - } - - let mut process = self.clone_process(); - process.start(callback, env)?; - - Ok(process) - } - /// Waits for the process to terminate. pub fn wait(&mut self, callback: Option) -> anyhow::Result { self.require_process_is_started("wait")?; @@ -475,13 +408,6 @@ impl Process { self.update_status(false); if let Some(callback) = callback { - if !self.process_pipes.as_ref().unwrap().have_read_support() { - self.stop(0.0, None); - return Err(LogicException::new( - "Pass the callback to the \"Process::start\" method or call enableOutput to use a callback with \"Process::wait\".".to_string(), - ) - .into()); - } self.callback = Some(self.build_callback(Some(callback))); } @@ -522,63 +448,6 @@ impl Process { Ok(self.exitcode.unwrap_or(0)) } - /// Waits until the callback returns true. - pub fn wait_until(&mut self, callback: UserCallback) -> anyhow::Result { - self.require_process_is_started("waitUntil")?; - self.update_status(false); - - if !self.process_pipes.as_ref().unwrap().have_read_support() { - self.stop(0.0, None); - return Err(LogicException::new( - "Pass the callback to the \"Process::start\" method or call enableOutput to use a callback with \"Process::waitUntil\".".to_string(), - ) - .into()); - } - let mut callback = self.build_callback(Some(callback)); - - let mut ready = false; - loop { - self.check_timeout()?; - let running = if shirabe_php_shim::DIRECTORY_SEPARATOR == "\\" { - self.is_running() - } else { - self.process_pipes.as_ref().unwrap().are_open() - }; - let output = self.process_pipes.as_mut().unwrap().read_and_write( - running, - shirabe_php_shim::DIRECTORY_SEPARATOR != "\\" || !running, - ); - - for (r#type, data) in output { - if r#type != 3 { - let r = callback( - self, - if Self::STDOUT == r#type { - Self::OUT - } else { - Self::ERR - }, - &data, - ); - ready = r || ready; - } else if !self.fallback_status.contains_key("signaled") { - self.fallback_status.insert( - "exitcode".to_string(), - PhpMixed::Int(data.trim().parse().unwrap_or(0)), - ); - } - } - if ready { - return Ok(true); - } - if !running { - return Ok(false); - } - - shirabe_php_shim::usleep(1000); - } - } - /// Returns the Pid (process identifier), if applicable. pub fn get_pid(&mut self) -> Option { if self.is_running() { @@ -591,51 +460,6 @@ impl Process { } } - /// Sends a POSIX signal to the process. - pub fn signal(&mut self, signal: i64) -> anyhow::Result<&mut Self> { - self.do_signal(signal, true)?; - - Ok(self) - } - - /// Disables fetching output and error output from the underlying process. - pub fn disable_output(&mut self) -> anyhow::Result<&mut Self> { - if self.is_running() { - return Err(RuntimeException::new( - "Disabling output while the process is running is not possible.".to_string(), - ) - .into()); - } - if self.idle_timeout.is_some() { - return Err(LogicException::new( - "Output cannot be disabled while an idle timeout is set.".to_string(), - ) - .into()); - } - - self.output_disabled = true; - - Ok(self) - } - - /// Enables fetching output and error output from the underlying process. - pub fn enable_output(&mut self) -> anyhow::Result<&mut Self> { - if self.is_running() { - return Err(RuntimeException::new( - "Enabling output while the process is running is not possible.".to_string(), - ) - .into()); - } - - self.output_disabled = false; - - Ok(self) - } - - pub fn is_output_disabled(&self) -> bool { - self.output_disabled - } - /// Returns the current output of the process (STDOUT). pub fn get_output(&mut self) -> anyhow::Result { if let Some(mock) = &self.mock { @@ -650,102 +474,6 @@ impl Process { ) } - /// Returns the output incrementally. - pub fn get_incremental_output(&mut self) -> anyhow::Result { - self.read_pipes_for_output("getIncrementalOutput", false)?; - - let latest = shirabe_php_shim::stream_get_contents3( - self.stdout.as_ref().unwrap(), - -1, - self.incremental_output_offset, - ); - self.incremental_output_offset = - shirabe_php_shim::ftell(self.stdout.as_ref().unwrap()).unwrap_or(0); - - Ok(latest.unwrap_or_default()) - } - - /// Returns an iterator to the output of the process, with the output type as keys. - /// - /// PHP returns a `\Generator`; lacking generators, this collects the yielded chunks eagerly. - pub fn get_iterator(&mut self, flags: i64) -> anyhow::Result> { - self.read_pipes_for_output("getIterator", false)?; - - let clear_output = (Self::ITER_KEEP_OUTPUT & flags) == 0; - let blocking = (Self::ITER_NON_BLOCKING & flags) == 0; - let yield_out = (Self::ITER_SKIP_OUT & flags) == 0; - let yield_err = (Self::ITER_SKIP_ERR & flags) == 0; - - let mut yields = Vec::new(); - while self.callback.is_some() - || (yield_out && !shirabe_php_shim::feof(self.stdout.as_ref().unwrap())) - || (yield_err && !shirabe_php_shim::feof(self.stderr.as_ref().unwrap())) - { - let mut got_out = false; - let mut got_err = false; - - if yield_out { - let out = shirabe_php_shim::stream_get_contents3( - self.stdout.as_ref().unwrap(), - -1, - self.incremental_output_offset, - ) - .unwrap_or_default(); - - if !out.is_empty() { - got_out = true; - if clear_output { - self.clear_output(); - } else { - self.incremental_output_offset = - shirabe_php_shim::ftell(self.stdout.as_ref().unwrap()).unwrap_or(0); - } - - yields.push((Self::OUT.to_string(), out)); - } - } - - if yield_err { - let err = shirabe_php_shim::stream_get_contents3( - self.stderr.as_ref().unwrap(), - -1, - self.incremental_error_output_offset, - ) - .unwrap_or_default(); - - if !err.is_empty() { - got_err = true; - if clear_output { - self.clear_error_output(); - } else { - self.incremental_error_output_offset = - shirabe_php_shim::ftell(self.stderr.as_ref().unwrap()).unwrap_or(0); - } - - yields.push((Self::ERR.to_string(), err)); - } - } - - if !blocking && !got_out && !got_err { - yields.push((Self::OUT.to_string(), String::new())); - } - - self.check_timeout()?; - self.read_pipes_for_output("getIterator", blocking)?; - } - - Ok(yields) - } - - /// Clears the process output. - pub fn clear_output(&mut self) -> &mut Self { - shirabe_php_shim::ftruncate(self.stdout.as_ref().unwrap(), 0); - shirabe_php_shim::fseek(self.stdout.as_ref().unwrap(), 0, shirabe_php_shim::SEEK_SET); - self.incremental_output_offset = 0; - - self - } - /// Returns the current error output of the process (STDERR). pub fn get_error_output(&mut self) -> anyhow::Result { if let Some(mock) = &self.mock { @@ -760,30 +488,6 @@ impl Process { ) } - /// Returns the errorOutput incrementally. - pub fn get_incremental_error_output(&mut self) -> anyhow::Result { - self.read_pipes_for_output("getIncrementalErrorOutput", false)?; - - let latest = shirabe_php_shim::stream_get_contents3( - self.stderr.as_ref().unwrap(), - -1, - self.incremental_error_output_offset, - ); - self.incremental_error_output_offset = - shirabe_php_shim::ftell(self.stderr.as_ref().unwrap()).unwrap_or(0); - - Ok(latest.unwrap_or_default()) - } - - /// Clears the process error output. - pub fn clear_error_output(&mut self) -> &mut Self { - shirabe_php_shim::ftruncate(self.stderr.as_ref().unwrap(), 0); - shirabe_php_shim::fseek(self.stderr.as_ref().unwrap(), 0, shirabe_php_shim::SEEK_SET); - self.incremental_error_output_offset = 0; - - self - } - /// Returns the exit code returned by the process. pub fn get_exit_code(&mut self) -> Option { if self.mock.is_some() { @@ -811,18 +515,6 @@ impl Process { self.get_exit_code() == Some(0) } - /// Returns true if the child process has been terminated by an uncaught signal. - pub fn has_been_signaled(&mut self) -> anyhow::Result { - self.require_process_is_terminated("hasBeenSignaled")?; - - Ok(self - .process_information - .as_ref() - .and_then(|i| i.get("signaled")) - .map(shirabe_php_shim::php_truthy) - .unwrap_or(false)) - } - /// Returns the number of the signal that caused the child process to terminate. pub fn get_term_signal(&mut self) -> anyhow::Result { self.require_process_is_terminated("getTermSignal")?; @@ -842,30 +534,6 @@ impl Process { Ok(termsig.unwrap_or(0)) } - /// Returns true if the child process has been stopped by a signal. - pub fn has_been_stopped(&mut self) -> anyhow::Result { - self.require_process_is_terminated("hasBeenStopped")?; - - Ok(self - .process_information - .as_ref() - .and_then(|i| i.get("stopped")) - .map(shirabe_php_shim::php_truthy) - .unwrap_or(false)) - } - - /// Returns the number of the signal that caused the child process to stop. - pub fn get_stop_signal(&mut self) -> anyhow::Result { - self.require_process_is_terminated("getStopSignal")?; - - Ok(self - .process_information - .as_ref() - .and_then(|i| i.get("stopsig")) - .and_then(|v| v.as_int()) - .unwrap_or(0)) - } - /// Checks if the process is currently running. pub fn is_running(&mut self) -> bool { if Self::STATUS_STARTED != self.status { @@ -893,13 +561,6 @@ impl Process { Self::STATUS_TERMINATED == self.status } - /// Gets the process status (one of: ready, started, terminated). - pub fn get_status(&mut self) -> String { - self.update_status(false); - - self.status.clone() - } - /// Stops the process. pub fn stop(&mut self, timeout: f64, signal: Option) -> Option { let timeout_micro = shirabe_php_shim::microtime() + timeout; @@ -935,8 +596,6 @@ impl Process { /// Adds a line to the STDOUT stream. pub fn add_output(&mut self, line: &str) { - self.last_output_time = Some(shirabe_php_shim::microtime()); - let stdout = self.stdout.as_ref().unwrap(); shirabe_php_shim::fseek(stdout, 0, shirabe_php_shim::SEEK_END); shirabe_php_shim::fwrite(stdout, line, Some(line.len() as i64)); @@ -949,8 +608,6 @@ impl Process { /// Adds a line to the STDERR stream. pub fn add_error_output(&mut self, line: &str) { - self.last_output_time = Some(shirabe_php_shim::microtime()); - let stderr = self.stderr.as_ref().unwrap(); shirabe_php_shim::fseek(stderr, 0, shirabe_php_shim::SEEK_END); shirabe_php_shim::fwrite(stderr, line, Some(line.len() as i64)); @@ -961,11 +618,6 @@ impl Process { ); } - /// Gets the last output time in seconds. - pub fn get_last_output_time(&self) -> Option { - self.last_output_time - } - /// Gets the command line to be executed. pub fn get_command_line(&self) -> String { match &self.commandline { @@ -983,11 +635,6 @@ impl Process { self.timeout } - /// Gets the process idle timeout in seconds (max. time since last output). - pub fn get_idle_timeout(&self) -> Option { - self.idle_timeout - } - /// Sets the process timeout (max. runtime) in seconds. pub fn set_timeout(&mut self, timeout: Option) -> anyhow::Result<&mut Self> { self.timeout = self.validate_timeout(timeout)?; @@ -995,20 +642,6 @@ impl Process { Ok(self) } - /// Sets the process idle timeout (max. time since last output) in seconds. - pub fn set_idle_timeout(&mut self, timeout: Option) -> anyhow::Result<&mut Self> { - if timeout.is_some() && self.output_disabled { - return Err(LogicException::new( - "Idle timeout cannot be set while the output is disabled.".to_string(), - ) - .into()); - } - - self.idle_timeout = self.validate_timeout(timeout)?; - - Ok(self) - } - /// Enables or disables the TTY mode. pub fn set_tty(&mut self, tty: bool) -> anyhow::Result<&mut Self> { if shirabe_php_shim::DIRECTORY_SEPARATOR == "\\" && tty { @@ -1035,18 +668,6 @@ impl Process { self.tty } - /// Sets PTY mode. - pub fn set_pty(&mut self, bool: bool) -> &mut Self { - self.pty = bool; - - self - } - - /// Returns PTY state. - pub fn is_pty(&self) -> bool { - self.pty - } - /// Gets the working directory. pub fn get_working_directory(&self) -> Option { if self.cwd.is_none() { @@ -1058,18 +679,6 @@ impl Process { self.cwd.clone() } - /// Sets the current working directory. - pub fn set_working_directory(&mut self, cwd: &str) -> &mut Self { - self.cwd = Some(cwd.to_string()); - - self - } - - /// Gets the environment variables. - pub fn get_env(&self) -> &IndexMap { - &self.env - } - /// Sets the environment variables. pub fn set_env(&mut self, env: IndexMap) -> &mut Self { self.env = env; @@ -1077,11 +686,6 @@ impl Process { self } - /// Gets the Process input. - pub fn get_input(&self) -> &PhpMixed { - &self.input - } - /// Sets the input. pub fn set_input(&mut self, input: PhpMixed) -> anyhow::Result<&mut Self> { if self.is_running() { @@ -1108,64 +712,7 @@ impl Process { { self.stop(0.0, None); - return Err(ProcessTimedOutException::new( - self, - ProcessTimedOutException::TYPE_GENERAL, - ) - .into()); - } - - if let Some(idle_timeout) = self.idle_timeout - && idle_timeout < shirabe_php_shim::microtime() - self.last_output_time.unwrap_or(0.0) - { - self.stop(0.0, None); - - return Err( - ProcessTimedOutException::new(self, ProcessTimedOutException::TYPE_IDLE).into(), - ); - } - - Ok(()) - } - - pub fn get_start_time(&self) -> anyhow::Result { - if !self.is_started() { - return Err(LogicException::new( - "Start time is only available after process start.".to_string(), - ) - .into()); - } - - Ok(self.starttime.unwrap()) - } - - /// Defines options to pass to the underlying proc_open(). - pub fn set_options(&mut self, options: IndexMap) -> anyhow::Result<()> { - if self.is_running() { - return Err(RuntimeException::new( - "Setting options while the process is running is not possible.".to_string(), - ) - .into()); - } - - let default_options = self.options.clone(); - let existing_options = [ - "blocking_pipes", - "create_process_group", - "create_new_console", - ]; - - for (key, value) in options { - if !existing_options.contains(&key.as_str()) { - self.options = default_options; - return Err(LogicException::new(format!( - "Invalid option \"{}\" passed to \"Symfony\\Component\\Process\\Process::setOptions()\". Supported options are \"{}\".", - key, - existing_options.join("\", \"") - )) - .into()); - } - self.options.insert(key, value); + return Err(ProcessTimedOutException::new(self).into()); } Ok(()) @@ -1193,46 +740,15 @@ impl Process { }) } - /// Returns whether PTY is supported on the current operating system. - pub fn is_pty_supported() -> bool { - static RESULT: OnceLock = OnceLock::new(); - - *RESULT.get_or_init(|| { - if shirabe_php_shim::DIRECTORY_SEPARATOR == "\\" { - return false; - } - - let mut pipes = IndexMap::new(); - shirabe_php_shim::proc_open( - "echo 1 >/dev/null", - &[ - descriptor(&["pty"]), - descriptor(&["pty"]), - descriptor(&["pty"]), - ], - &mut pipes, - None, - None, - None, - ) - .is_ok() - }) - } - /// Creates the descriptors needed by the proc_open. fn get_descriptors(&mut self) -> Vec { // TODO(plugin): $this->input instanceof \Iterator -> rewind() is not modeled. if shirabe_php_shim::DIRECTORY_SEPARATOR == "\\" { - self.process_pipes = Some(Box::new(WindowsPipes::new( - self.input.clone(), - !self.output_disabled || self.has_callback, - ))); + self.process_pipes = Some(Box::new(WindowsPipes::new(self.input.clone()))); } else { self.process_pipes = Some(Box::new(UnixPipes::new( Some(self.is_tty()), - self.is_pty(), self.input.clone(), - !self.output_disabled || self.has_callback, ))); } @@ -1242,17 +758,6 @@ impl Process { /// Builds up the callback used by wait(). fn build_callback(&self, callback: Option) -> ProcessCallback { let mut callback = callback; - if self.output_disabled { - return Box::new( - move |_this: &mut Process, r#type: &str, data: &str| -> bool { - match callback.as_mut() { - Some(cb) => cb(r#type, data), - None => false, - } - }, - ); - } - let out = Self::OUT; Box::new( @@ -1355,10 +860,6 @@ impl Process { /// Reads pipes for the freshest output. fn read_pipes_for_output(&mut self, caller: &str, blocking: bool) -> anyhow::Result<()> { - if self.output_disabled { - return Err(LogicException::new("Output has been disabled.".to_string()).into()); - } - self.require_process_is_started(caller)?; self.update_status(blocking); @@ -1790,40 +1291,10 @@ impl Process { } result } - - /// Clone the process configuration, mirroring PHP `clone $this` followed by `__clone` - /// (which calls resetProcessData). Runtime state is reset, not copied. - fn clone_process(&self) -> Process { - let mut process = Self::empty(); - process.has_callback = self.has_callback; - process.commandline = self.commandline.clone(); - process.cwd = self.cwd.clone(); - process.env = self.env.clone(); - process.input = self.input.clone(); - process.timeout = self.timeout; - process.idle_timeout = self.idle_timeout; - process.output_disabled = self.output_disabled; - process.tty = self.tty; - process.pty = self.pty; - process.options = self.options.clone(); - process.use_file_handles = self.use_file_handles; - process - } } impl Drop for Process { fn drop(&mut self) { - if self - .options - .get("create_new_console") - .map(shirabe_php_shim::php_truthy) - .unwrap_or(false) - { - if let Some(p) = self.process_pipes.as_mut() { - p.close(); - } - } else { - self.stop(0.0, None); - } + self.stop(0.0, None); } } -- cgit v1.3.1