Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- Handle invalid working directories gracefully when using `--full-path`, see #1900 (@Xavrir).
- Fire the "search pattern contains a path separator" diagnostic for any pattern containing `/`, not just patterns that happen to name an existing directory. Preserves the legacy Windows behaviour that also flags native `\` separators when the pattern resolves to a real directory. See #1873.
- Fix bug where passing "-" as a directory argument didn't actually search that directory, see #849 (@Sean-Kenneth-Doherty).
- Preserve `--exec-batch` command order when batching multiple commands, see #2033 (@cyphercodes).

# 10.4.2

Expand Down
39 changes: 30 additions & 9 deletions src/exec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,25 +102,46 @@ impl CommandSet {

match builders {
Ok(mut builders) => {
for path in paths {
for builder in &mut builders {
if let Err(e) = builder.push(&path, path_separator) {
return handle_cmd_error(Some(&builder.cmd), e);
}
}
if builders.len() == 1 {
let builder = &mut builders[0];
return match Self::execute_batch_builder(builder, paths, path_separator) {
Ok(exit_code) => exit_code,
Err(e) => handle_cmd_error(Some(&builder.cmd), e),
};
}

let paths: Vec<_> = paths.collect();
let mut exit_codes = Vec::with_capacity(builders.len());
for builder in &mut builders {
if let Err(e) = builder.finish() {
return handle_cmd_error(Some(&builder.cmd), e);
match Self::execute_batch_builder(builder, paths.iter(), path_separator) {
Ok(exit_code) => exit_codes.push(exit_code),
Err(e) => return handle_cmd_error(Some(&builder.cmd), e),
}
}

merge_exitcodes(builders.iter().map(|b| b.exit_code()))
merge_exitcodes(exit_codes)
}
Err(e) => handle_cmd_error(None, e),
}
}

fn execute_batch_builder<I, P>(
builder: &mut CommandBuilder,
paths: I,
path_separator: Option<&str>,
) -> io::Result<ExitCode>
where
I: IntoIterator<Item = P>,
P: AsRef<Path>,
{
for path in paths {
builder.push(path.as_ref(), path_separator)?;
}

builder.finish()?;

Ok(builder.exit_code())
}
}

/// Represents a multi-exec command as it is built.
Expand Down
40 changes: 40 additions & 0 deletions tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2073,6 +2073,46 @@ fn test_exec_batch_with_limit() {
);
}

#[test]
fn test_exec_batch_multi_with_limit_preserves_command_order() {
// TODO Test for windows
if cfg!(windows) {
return;
}

let te = TestEnv::new(DEFAULT_DIRS, DEFAULT_FILES);

let output = te.assert_success_and_get_output(
".",
&[
"foo",
"--batch-size=2",
"--exec-batch",
"echo",
"first",
"{}",
";",
"--exec-batch",
"echo",
"second",
"{}",
],
);
let stdout = String::from_utf8_lossy(&output.stdout);
let prefixes: Vec<_> = stdout
.lines()
.map(|line| line.split_whitespace().next().unwrap())
.collect();

assert_eq!(
prefixes,
&["first", "first", "first", "second", "second", "second"]
);
for line in stdout.lines() {
assert_eq!(3, line.split_whitespace().count());
}
}

/// Shell script execution (--exec) with a custom --path-separator
#[test]
fn test_exec_with_separator() {
Expand Down