Skip to content

Commit c420fdc

Browse files
committed
implement std::process::Command::arg_set()
Only unix implementation yet.
1 parent a2fbdd3 commit c420fdc

File tree

3 files changed

+77
-0
lines changed

3 files changed

+77
-0
lines changed

library/std/src/process.rs

+34
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,40 @@ impl Command {
680680
self
681681
}
682682

683+
/// Sets the argument at index to a new value.
684+
///
685+
/// When one wants to restart a Command again with different
686+
/// arguments the argument list can to be cleared first.
687+
///
688+
/// # Examples
689+
///
690+
/// Basic usage:
691+
///
692+
/// ```no_run
693+
/// #![feature(mutate_command_args)]
694+
/// use std::process::Command;
695+
///
696+
/// // Prepare a command
697+
/// let mut command = Command::new("ls");
698+
/// command.args(["-l", "-a", "FILE"]);
699+
///
700+
/// // Run it with mutated 3rd parameter
701+
/// ["foo", "bar", "baz"].iter()
702+
/// .for_each(
703+
/// |file| {
704+
/// command
705+
/// .arg_set(3, file)
706+
/// .spawn()
707+
/// .unwrap();
708+
/// }
709+
/// );
710+
/// ```
711+
#[unstable(feature = "mutate_command_args", issue = "87379")]
712+
pub fn arg_set<S: AsRef<OsStr>>(&mut self, index: usize, value: S) -> &mut Command {
713+
self.inner.arg_set(index, value.as_ref());
714+
self
715+
}
716+
683717
/// Inserts or updates an environment variable mapping.
684718
///
685719
/// Note that environment variable names are case-insensitive (but case-preserving) on Windows,

library/std/src/process/tests.rs

+36
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,42 @@ fn test_args_clear() {
237237
assert_eq!(stderr, Vec::new());
238238
}
239239

240+
#[test]
241+
fn test_arg_set() {
242+
let mut prog = Command::new("echo");
243+
244+
if cfg!(target_os = "windows") {
245+
prog.args(&["/C", "echo set_me"])
246+
} else {
247+
prog.arg("set_me")
248+
};
249+
250+
if cfg!(target_os = "windows") {
251+
prog.arg_set(2, "echo hello");
252+
} else {
253+
prog.arg_set(1, "hello");
254+
};
255+
256+
let Output { status, stdout, stderr } = prog.output().unwrap();
257+
let output_str = str::from_utf8(&stdout).unwrap();
258+
259+
assert!(status.success());
260+
assert_eq!(output_str.trim().to_string(), "hello");
261+
assert_eq!(stderr, Vec::new());
262+
}
263+
264+
#[test]
265+
#[should_panic]
266+
fn test_arg_set_fail() {
267+
let mut prog = Command::new("echo");
268+
269+
if cfg!(target_os = "windows") {
270+
prog.arg_set(1, "echo hello");
271+
} else {
272+
prog.arg_set(1, "hello");
273+
};
274+
}
275+
240276
#[cfg(all(unix, not(target_os = "android")))]
241277
pub fn env_cmd() -> Command {
242278
Command::new("env")

library/std/src/sys/unix/process/process_common.rs

+7
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,13 @@ impl Command {
199199
self.args.truncate(1);
200200
}
201201

202+
pub fn arg_set(&mut self, index: usize, arg: &OsStr) {
203+
debug_assert!(index >= 1 && index < self.args.len(), "Index out of range");
204+
let arg = os2c(arg, &mut self.saw_nul);
205+
self.argv.0[index] = arg.as_ptr();
206+
self.args[index] = arg;
207+
}
208+
202209
pub fn cwd(&mut self, dir: &OsStr) {
203210
self.cwd = Some(os2c(dir, &mut self.saw_nul));
204211
}

0 commit comments

Comments
 (0)