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

Tokio-less APIs? #6

Open
RaitoBezarius opened this issue Mar 9, 2023 · 3 comments
Open

Tokio-less APIs? #6

RaitoBezarius opened this issue Mar 9, 2023 · 3 comments

Comments

@RaitoBezarius
Copy link

Hi there, thank you for the amazing package :)

I am trying to use it in a project where I would like to have a std::process::Command-like API without any tokio/async/await stuff, do you think it is possible? I can also send a PR if you tell me what would you accept as a change regarding this.

Thank you!

@ysndr
Copy link
Contributor

ysndr commented Mar 9, 2023

Thank you!

Our usecase is very much async focused so all the command stuff is very async centric and non async ways are currently not easily exposed.
Though Async stops after the Run trait and its impls.

It should be possible to define a RunSync trait and corresponding impl of a sync CommandLine backend, i.e. a sync version of

async fn run_command<M: CommandMode, A, B: NixCliCommand<Own = A>>(
&self,
command: &B,
nix_args: &NixArgs,
json: bool,
) -> Result<M::Output, M::Error> {
let args = vec![
// apply default args always applicable
self.defaults.config_args.to_args(),
self.defaults.common_args.to_args(),
nix_args.to_args(),
B::SUBCOMMAND.iter().map(ToString::to_string).collect(),
// apply command specific defaults if applicable
// as defined by the command impl
B::EVAL_ARGS
.map(|_| self.defaults.eval_args.to_args())
.unwrap_or_default(),
B::FLAKE_ARGS
.map(|_| self.defaults.flake_args.to_args())
.unwrap_or_default(),
if json {
vec!["--json".to_string()]
} else {
vec![]
},
command.args(),
self.defaults.extra_args.clone(),
];
let mut command = Command::new(self.nix_bin.as_deref().unwrap_or("nix"));
command
.envs(&self.defaults.environment)
.args(args.into_iter().flatten());
if let Some(ref cwd) = nix_args.cwd {
command.current_dir(cwd);
}
M::run(&mut command).await
}

If we go down that path both async and sync impls should share as much code as possible, so they do not become a maintenance burden

@RaitoBezarius
Copy link
Author

RaitoBezarius commented Mar 9, 2023 via email

@ysndr
Copy link
Contributor

ysndr commented Mar 9, 2023

Putting it behind feature flags in either direction would make sense.
Either way, we should look to share everything but the lines that are related to async commands.

let mut command = Command::new(self.nix_bin.as_deref().unwrap_or("nix"));
command
.envs(&self.defaults.environment)
.args(args.into_iter().flatten());
if let Some(ref cwd) = nix_args.cwd {
command.current_dir(cwd);
}
M::run(&mut command).await

n.b. its able to "downgrade" a tokio command to an std command, perhaps its possible to go the other way around as well. than it should be a fairly minimal difference.

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

No branches or pull requests

2 participants