Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for batch execution of command #360

Merged
merged 2 commits into from
Nov 12, 2018
Merged

Conversation

kimsnj
Copy link
Contributor

@kimsnj kimsnj commented Nov 11, 2018

This aims at implementing #274

Note: for this first version, arg_max is not taken into account.

Copy link
Owner

@sharkdp sharkdp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome stuff! Thank you very much for working on this.

I played around with this a little bit and got a panic when doing this (I know it's wrong):

fd -X "echo {}"

Any idea what's going on?

cmd.arg(arg.generate("").as_ref());
}
}

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we add the following lines here:

cmd.stdin(Stdio::inherit());
cmd.stdout(Stdio::inherit());
cmd.stderr(Stdio::inherit());

we can use --exec-batch with interactive terminal commands such as vim.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's indeed much better with these lines added.

@@ -44,3 +44,16 @@ pub fn job(
cmd.generate_and_execute(&value, Arc::clone(&out_perm));
}
}

pub fn batch(rx: Receiver<WorkerResult>, cmd: &CommandTemplate, show_filesystem_errors: bool) {
let paths = rx.iter().filter_map(|value| match value {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

src/exec/mod.rs Outdated
/// Execution mode of the command
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ExecutionMode {
/// Command is executed for each path found
Copy link
Owner

@sharkdp sharkdp Nov 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

path found => search result?

src/exec/mod.rs Outdated
CommandTemplate { args, mode }
}

fn tokens_number(&self) -> usize {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we rename this to number_of_tokens or something similar? It sounds like it returns the number of a specific token.

src/exec/mod.rs Outdated
execute_command(cmd, &out_perm)
}

pub fn is_batch(&self) -> bool {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe rename this to batch_mode or in_batch_mode?

// Check for exit status.
if output.status.success() {
panic!(
"fd exited successfully. Expected error {} did not occur.",
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use error '{}' did not occur. here?


/// Assert that calling *fd* in the specified path under the root working directory,
/// and with the specified arguments produces an error with the expected message.
fn assert_error_subdirectory<P: AsRef<Path>>(&self, path: P, args: &[&str], expected: &str) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great!


// Compare actual output to expected output.
let actual = String::from_utf8_lossy(&output.stderr);
if expected.len() <= actual.len() && expected != &actual[..expected.len()] {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just expected != actual? Is this stripping the [fd error] prefix?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The errors regarding the conflict between exec and exec-batch is generated by clap… With the usage message.
This allows to have just the error message in the test.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. Could we also use ends_with(..) here?

Copy link
Contributor Author

@kimsnj kimsnj Nov 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would actually be start_with (as usage is after the error). And indeed, it would be cleaner!

tests/tests.rs Outdated
assert_exec_batch_output("--exec-batch");
}

// Shell script execution using -x
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is redundant. If you want to keep it, please modify the docstring to use -X instead of -x.

tests/tests.rs Outdated
let (te, abs_path) = get_test_env_with_abs_path(DEFAULT_DIRS, DEFAULT_FILES);
let te = te.normalize_line(true);

// TODO Windows tests: D:file.txt \file.txt \\server\share\file.txt ...
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm okay with leaving the Windows tests as To Do, but what does this comment describe?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I must admit to a copy/paste (incl. this comment).
The cfg!(windows) clause is already present in the exec test, and being on linux right now, I couldn't try it out.
I guess the comment is mainly linked to the first test (absolute paths), which may have several forms on windows depending of file location (drive, network,…). But this is just a theory.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I must admit that I forgot about this part 😄. Let's just say TODO: Tests for Windows here.

@kimsnj
Copy link
Contributor Author

kimsnj commented Nov 11, 2018

Thanks for the review!

Looking at:

fd -X "echo {}"

I only read from the rx iterator chain for arguments other than first one (supposed to be the executable).
So in this case, the receiver is not read at all, and thus the thread ends fast, drops rx… And the transmitters panics when trying to send!

I see a few options to handle this case:

  • Just apply the same generation on the first argument. This would launch echo a echo b echo c…
  • In case of a single argument in input, split by white-space before parsing the command.
  • Reject entries that do not have a ArgumentTemplate::Text as first arg.

Any opinions?

I would be tempted by option 2, but not sure if there are some weird cases to consider.

@sharkdp
Copy link
Owner

sharkdp commented Nov 11, 2018

Any opinions?

I would be tempted by option 2, but not sure if there are some weird cases to consider.

I would just go with option three. I think it doesn't make sense to allow placeholders in the first argument for --exec-once (for --exec, you could use something like fd --type executable --exec "{}" to run all executables in a directory).

@sharkdp sharkdp merged commit 6b40a07 into sharkdp:master Nov 12, 2018
@sharkdp
Copy link
Owner

sharkdp commented Nov 12, 2018

Thank you very much for the updates!

@kimsnj
Copy link
Contributor Author

kimsnj commented Nov 12, 2018

You're welcome!
Glad I can contribute to such a neat CLI ! :)

@kimsnj kimsnj deleted the batch_exec branch November 12, 2018 22:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants