261021.2.2 · d5365d3fa0caafee5a43b5b36ba4de471670aec2
Merge branch 'master' into master
reading declarations
Changes to src/exec/mod.rs. All files
@@ -6,12 +6,12 @@ use std::io; use std::iter; use std::path::{Path, PathBuf}; use std::process::Stdio;-use std::sync::Mutex; -use anyhow::{bail, Result};+use anyhow::{Result, bail}; use argmax::Command; -use crate::exit_codes::{merge_exitcodes, ExitCode};+use crate::exec::command::OutputBuffer;+use crate::exit_codes::{ExitCode, merge_exitcodes}; use crate::fmt::{FormatTemplate, Token}; use self::command::{execute_commands, handle_cmd_error};@@ -43,7 +43,7 @@ impl CommandSet { mode: ExecutionMode::OneByOne, commands: input .into_iter()- .map(CommandTemplate::new)+ .map(|args| CommandTemplate::new(args, ExecutionMode::OneByOne)) .collect::<Result<_>>()?, }) }@@ -59,13 +59,10 @@ impl CommandSet { commands: input .into_iter() .map(|args| {- let cmd = CommandTemplate::new(args)?;+ let cmd = CommandTemplate::new(args, ExecutionMode::Batch)?; if cmd.number_of_tokens() > 1 { bail!("Only one placeholder allowed for batch commands"); }- if cmd.args[0].has_tokens() {- bail!("First argument of exec-batch is expected to be a fixed executable");- } Ok(cmd) }) .collect::<Result<Vec<_>>>()?,@@ -80,14 +77,14 @@ impl CommandSet { &self, input: &Path, path_separator: Option<&str>,- out_perm: &Mutex<()>,+ null_separator: bool, buffer_output: bool, ) -> ExitCode { let commands = self .commands .iter() .map(|c| c.generate(input, path_separator));- execute_commands(commands, out_perm, buffer_output)+ execute_commands(commands, OutputBuffer::new(null_separator), buffer_output) } pub fn execute_batch<I>(&self, paths: I, limit: usize, path_separator: Option<&str>) -> ExitCode@@ -220,7 +217,7 @@ struct CommandTemplate { } impl CommandTemplate {- fn new<I, S>(input: I) -> Result<Self>+ fn new<I, S>(input: I, mode: ExecutionMode) -> Result<Self> where I: IntoIterator<Item = S>, S: AsRef<str>,@@ -245,6 +242,11 @@ impl CommandTemplate { bail!("No executable provided for --exec or --exec-batch"); } + // A placeholder as the executable is meaningful for `--exec` but never for `--exec-batch`.+ if mode == ExecutionMode::Batch && args[0].has_tokens() {+ bail!("First argument of --exec-batch must be a fixed executable, not a placeholder");+ }+ // If a placeholder token was not supplied, append one at the end of the command. if !has_placeholder { args.push(FormatTemplate::Tokens(vec![Token::Placeholder]));@@ -365,7 +367,8 @@ mod tests { #[test] fn tokens_with_literal_braces() {- let template = CommandTemplate::new(vec!["{{}}", "{{", "{.}}"]).unwrap();+ let template =+ CommandTemplate::new(vec!["{{}}", "{{", "{.}}"], ExecutionMode::OneByOne).unwrap(); assert_eq!( generate_str(&template, "foo"), vec!["{}", "{", "{.}", "foo"]@@ -374,8 +377,9 @@ mod tests { #[test] fn tokens_with_literal_braces_and_placeholder() {- let template = CommandTemplate::new(vec!["{{{},end}"]).unwrap();- assert_eq!(generate_str(&template, "foo"), vec!["{foo,end}"]);+ let template =+ CommandTemplate::new(vec!["echo", "{{{},end}"], ExecutionMode::OneByOne).unwrap();+ assert_eq!(generate_str(&template, "foo"), vec!["echo", "{foo,end}"]); } #[test]@@ -421,7 +425,9 @@ mod tests { #[test] fn template_no_args() {- assert!(CommandTemplate::new::<Vec<_>, &'static str>(vec![]).is_err());+ assert!(+ CommandTemplate::new::<Vec<_>, &'static str>(vec![], ExecutionMode::OneByOne).is_err()+ ); } #[test]@@ -429,6 +435,13 @@ mod tests { assert!(CommandSet::new(vec![vec!["echo"], vec![]]).is_err()); } + #[test]+ fn placeholder_as_executable_rejected() {+ assert!(CommandSet::new(vec![vec!["{}"]]).is_ok());+ assert!(CommandSet::new(vec![vec!["{/}", "arg"]]).is_ok());+ assert!(CommandSet::new_batch(vec![vec!["{}"]]).is_err());+ }+ #[test] fn generate_custom_path_separator() { let arg = FormatTemplate::Tokens(vec![Token::Placeholder]);