Coder Social home page Coder Social logo

xshell's Introduction

xshell: Making Rust a Better Bash

xshell provides a set of cross-platform utilities for writing cross-platform and ergonomic "bash" scripts.

Example

//! Clones a git repository and publishes it to crates.io.
use xshell::{cmd, Shell};

fn main() -> anyhow::Result<()> {
    let sh = Shell::new()?;

    let user = "matklad";
    let repo = "xshell";
    cmd!(sh, "git clone https://github.com/{user}/{repo}.git").run()?;
    sh.change_dir(repo);

    let test_args = ["-Zunstable-options", "--report-time"];
    cmd!(sh, "cargo test -- {test_args...}").run()?;

    let manifest = sh.read_file("Cargo.toml")?;
    let version = manifest
        .split_once("version = \"")
        .and_then(|it| it.1.split_once('\"'))
        .map(|it| it.0)
        .ok_or_else(|| anyhow::format_err!("can't find version field in the manifest"))?;

    cmd!(sh, "git tag {version}").run()?;

    let dry_run = if sh.var("CI").is_ok() { None } else { Some("--dry-run") };
    cmd!(sh, "cargo publish {dry_run...}").run()?;

    Ok(())
}

See the docs for more.

If you like the ideas behind xshell, you will enjoy dax.

xshell's People

Contributors

alexxbb avatar azdavis avatar bors[bot] avatar cad97 avatar cgwalters avatar elichai avatar fkrull avatar matklad avatar oberblastmeister avatar smoelius avatar thomcc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xshell's Issues

Consider adding a `fn finish(self) -> Result<()>` to RAII values

There's a handful of things that do interesting things when dropped, like Pushd and Pushenv. However, their drop impls can fail.

We might want to add something like fn finish(self) -> Result<()> that can be called in user code that 'does the drop impl' but allows reporting errors instead of panicking/ignoring them.

We should also decide on whether we want to panic or ignore errors when dropping. std likes to ignore them and asserts 'dtors should not panic'.

Allow not displaying command

First off, thanks for this cool library. This is pretty much what I didn't know I was looking for!

I need to pass a sensitive parameter to a command (shoutout to SignTool for only taking passwords as a commandline argument...). It would be great if there was a way to tell xshell to not print the command it is running.

Returning Child with spawn

Hey,

I'm enjoying your crate, but I hit the wall. Let's say, I would like to execute a command that outputs in threads

 all_servers.par_iter().try_for_each(op: |server: &Server| {
    cmd!(
        sh,
        "command with output"
    )

what happens that the output interleaves, and I have no way to know which thread outputs what. The only solution is to read the output and prefix it with Id, but that is not possible with your crate, right?

Doing xshell::pushd with a directory created with xshell::mktemp_d panics

It seems like an obvious use but I'm probably missing something. Is this behavior intended?

fn main() {
    println!(
        "Current working directory: {}",
        xshell::cwd().unwrap().display()
    );

    let tmp = xshell::mktemp_d().unwrap();

    println!("Created temporary directory: {}", tmp.path().display());

    // Enter directory in child block so pushd guard is dropped before tmp
    {
        let _cwd = xshell::pushd(tmp.path()).unwrap();

        println!(
            "Current working directory: {}",
            xshell::cwd().unwrap().display()
        );
    }
}

Gives:

Current working directory: /path/to/example/
Created temporary directory: /tmp/xshell-tmp-dir-0
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `1`,
 right: `0`: calling write() with an active read guard on the same thread would deadlock', ~/.cargo/registry/src/github.com-1ecc6299db9ec823/xshell-0.1.14/src/gsl.rs:44:13

Inconsistencies between run()/output()/read()/read_err()

Currently run() ignores stdin() and output()/read()/read_err() ignore quiet() (as it's always implied). It seems like either the documentation should get updated to reflect this, or the functionality made consistent.

Proposing:

run() method

    pub fn run(&self) -> Result<()> {
        if !self.data.quiet {
            eprintln!("$ {}", self);
        }
        let mut command = self.to_command();
        let status = command.status().map_err(|err| Error::new_cmd_io(self, err))?;
        self.check_status(status)?;
        Ok(())
    }

becomes

    pub fn run(&self) -> Result<()> {
        self.output_impl(false, false).map(|_| ())
    }

output_impl() method adds

        if !self.data.quiet {
            eprintln!("$ {}", self);
        }

Nonexistent current directory results in confusing error message

I tried this code:

#[test]
fn huh() -> Result<()> {
    let sh = Shell::new()?;
    sh.change_dir("nonexistent");
    cmd!(sh, "which echo").run()?;
    Ok(())
}

And I saw this:

running 1 test
$ which echo
Error: command not found: `which`
test huh ... FAILED

IMHO, the error message should indicate that the current directory does not exist, rather than say "command not found".

Really nice tool, BTW.

Bug: Multiple blank flags seem to cause errors with cmd!

This could will result in an error:

use xshell::cmd;
fn main() {
    let x = (false).then_some("-s").unwrap_or_default();
    let y = (false).then_some("-b").unwrap_or_default();
    let sh = xshell::Shell::new().unwrap();
    cmd!(sh, "git status {x} {y}").run().unwrap();
}

Error

$ git status  
fatal: empty string is not a valid pathspec. please use . instead if you meant to match all paths
thread 'main' panicked at src/main.rs:7:42:
called `Result::unwrap()` on an `Err` value: command exited with non-zero code `git status  `: 128

Despite the fact git status is a valid command, as is git status -s -b

But this will not:

use xshell::cmd;
fn main() {
    let x = (false).then_some("-s").unwrap_or_default();
    let y = (false).then_some("-b").unwrap_or_default();
    let sh = xshell::Shell::new().unwrap();
    cmd!(sh, "git status").run().unwrap();
}

Ran into this bug when working on Bevy Game Engine, where the same thing caused issues with a cargo test. Except the error was:

command exited with non-zero code `cargo test --workspace --lib --bins --tests --benches  `: 1
error: unexpected argument '' found

Improve error messages

When given bad input, the macro doesn't provide very helpful messages at the moment. The unwraps and panics need to be turned into compile_errors and given user-friendly descriptions.

xshell command fails to communicate with a running app

Hi.

with inspiration from matklad/config/xtool. I have ported all my rust-script scripts and bash script to a cargo project.

However, I am having a hard time porting my termhere script. the xshell version fails to open a new tab in Zellij Action.

This is the original script:

#!/bin/sh

# takes the path as an argument (e.g. /opt)
if [ -n "$1" ]; then
  path="$1"
else
  echo "::: No path passed. Use '$HOME' as default"
  path="$HOME"
fi

zellij action new-tab --layout "default" --cwd "$path"

The xshell version

use xshell::{cmd, Shell};

fn home() -> anyhow::Result<String> {
    Ok(std::env::var("HOME")?)
}

fn here(sh: &Shell, pwd: &str) -> anyhow::Result<()> {
    let args = ["--layout", "default", "--cwd", pwd];
    println!("Opening terminal in `{pwd}`");
    cmd!(sh, "zellij action new-tab {args...}").run()?;
    Ok(())
}

pub(crate) fn run(sh: &Shell) -> anyhow::Result<()> {
    let flags = xflags::parse_or_exit! {
        optional pwd: String
    };

    match flags.pwd {
        Some(p) => here(sh, &p)?,
        None => here(sh, &home()?)?,
    };

    Ok(())
}

Both scripts run fine if executed directly in the terminal. but the xshell version can't work inside the emacs function (which is my primary workflow). However, the (b)ash version works well:

(defun terminal-here ()
  "Open a new terminal with current directory as PWD"
  (interactive)
  (message "Opening terminal in %s" default-directory)
  ;; Need to use `expand-file-name` to expand `~` into a full path
  ;; Otherwise, termhere fallback to `$HOME`
  (start-process "" nil "termhere"  (expand-file-name default-directory)))

Any idea how to debug this issue?

Thanks for xshell ❤️

Fork command to background

So i am trying to rewrite my polybar launch script in rust, in basg you can for a command to the background with the & symbol like so

MONITOR=$m polybar --reload mainbar-bspwm -c ~/.config/polybar/config.ini &

Is there a way to do this with xshell?

Allowing self.field in cmd! macro

Hi,

Would it be possible to allow using self.field in cmd! macros ?
For example, this would allow to use a struct to store common args of commands.

struct Commons {
    sh: Shell,
    field: String,
}

impl Commons {
    fn execute(&self) {
        let command = cmd!(self.sh, "echo {self.field}");
        command.run();
    }
}

I have not attempted to make the change, so that i don't know if it would be possible.

If the self. is removed from the above code, the compiler hints at something that would work.

error[E0425]: cannot find value `field` in this scope
  --> src/main.rs:88:13
   |
88 | /             "
89 | |             echo {field}
90 | |             "
   | |_____________^ help: you might have meant to use the available field: `self.field`

Interiour mutability seems unnecessary

At the time of writing this, xshell (v0.2.3) uses interiour mutability inside the Shell:

xshell/src/lib.rs

Lines 381 to 384 in af75dd4

pub struct Shell {
cwd: RefCell<PathBuf>,
env: RefCell<HashMap<OsString, OsString>>,
}

To me, this seems unnecessary & error prone.

The path value is mutated in

  • Shell::change_dir (it could just as well accept &mut self I don't immediately see the need for IM here)
  • Shell::set_var (again, could accept &mut self)
  • PushDir::new/PushDir::drop and PushEnv::new/PushEnv::drop

Push* guards are a bit more tricky to re-design, but they are also IMO the most error prone part — guards being disconnected from the object they are guarding seems fragile (although I can't come up with a really bad example, so maybe I'm imagining...).

Instead I think it would be better and more "rusty" to either

  1. Store a &mut Shell inside of Push* and implement DerefMut<Target = Shell> — this still feels a little bit weird, because you can still mutate the guarded object, but at least it uses no interiour mutability
  2. Implement all the methods on Push*, such that they don't even need to mutate Shell (possibly use a trait such that you can nest Push*es) — IMO the nicer approach, but requires more design work

In both cases the way you use push_dir/push_env changes to be more akin to mutexes for example:

// old
let _guard = sh.push_dir(user);
cmd!(sh, "git clone https://github.com/{user}/{repo}.git").run()?;

// new
let sh = sh.push_dir(user);
cmd!(sh, "git clone https://github.com/{user}/{repo}.git").run()?;

Either way this is just something that came to my mind while I was using xshell. I want to design/implement those API changes, my question thus is: would you like for these changes to be upstreamed, or should I create a fork? :)

How to make `cmd` prompt the user

Hi.

I would like to make podman system prune prompt [y/N] to user as it is executed in shell.

Shell:

~
❯ podman system prune
WARNING! This command removes:
        - all stopped containers
        - all networks not used by at least one container
        - all dangling images
        - all dangling build cache

Are you sure you want to continue? [y/N]

Xshell:

❯ clean
🧽 Cleaning dagling images
$ podman system prune
WARNING! This command removes:
        - all stopped containers
        - all networks not used by at least one container
        - all dangling images
        - all dangling build cache

Are you sure you want to continue? [y/N] Error: EOF
Error: command exited with non-zero code `podman system prune`: 125
    println!("🧽 Cleaning dagling images");
    cmd!(sh, "podman system prune").run()?;

One option is to use yes-or-no function such https://github.com/matklad/config/blob/0b4e7f1f31678a5f7aee27d212f0832baed722b2/xtool/src/amend.rs#L14, but it doesn't solve the original problem. It will not work with the command that has no -y or --assumeyes flag.

Thanks for xshell ❤️

Add Error::is_not_found or similar

Use case: Some automation tools require other binaries to be installed. I would like to catch when that is not the case and print installation instructions.

Implement `Clone` for `Shell`?

There are two fundamental parts to an xshell::Shell: https://docs.rs/xshell/latest/src/xshell/lib.rs.html#383

Both cwd and env have T in RefCell<T> that can be cloned, so a "deep clone" (not a RefCell clone) could be implemented for Shell. It would be useful to do this in order to create "related" shells (e.g. nix style development shells) from a current shell.

cwd can already be reported via current_dir, and PR #78 aims to expose similar functionality for env. Therefore, it would be possible to create a new shell (Shell::new()) that is a clone of an existing shell by setting its current working directory and environment variables appropriately using set_var (based on the output of the proposed vars_os method on the original shell).

So, implementing Clone would provide this functionality in an idiomatic form?

Single quotes prevent interpolation

let pwd = env::var("PWD").unwrap();
cmd!("echo 'Hello from {pwd}'").run()?;

produces

Hello from {pwd}

instead of the expected

Hello from /home/ngirard/....

`echo_cmd` using stdout instead of stderr is kind of annoying.

I use xshell in some projects that involve code generation. It's nice for these have a way to print the output to stdout, so that I can do just inspect it visually, or manually redirect it to a file, rather than have it always directly overwrite the output file.

This means in practice, at least for these scripts, all messages that aren't part of the actual output (e.g. informational stuff and verbose output), needs to use stderr. This isn't too bad, but echo_cmd only has options to use stdout/disable, and is on by default.

I don't know the best solution here. I'd rather not have to configure this on every invocation of xshell::cmd! (although it's fine if that's what you'd prefer — see option 4). Here are some solutions that come to mind:

  1. Just changing it to use stderr always would obviously be fine by me, if you didn't have strong feelings about writing to stderr/stdout by default.

  2. I think an cargo feature for it would work fine too — it's not exactly a normal feature use case, but I don't expect xshell to be used by libraries substantially separate from the original application.

  3. If it were me, I'd also consider using a global AtomicBool for the default, and having a global function (Well, a static method on to xshell::Cmd) to set it to one or the other. This is rather cludgey, but would work, and isn't a ton of effort.

  4. Having it be configured on a per-xshell::cmd! basis would be still be better than the status quo, since I could at least wrap it in a macro that configures it for me to always use stderr.

    I guess the most natural way this would look would be for echo_cmd to take Option<OutStream> (where enum OutStream { Stdout, Stderr }), but this is a breaking change (well, barring some trait shenanigans to allow it to still continue accepting a bool I guess). So, if you'd prefer this, let me know what the broad strokes of the API should be (e.g. accept Option, new function orthogonal to echo_cmd that does nothing if it's false, do trait shenanigans to avoid breaking changes while extending what echo_cmd accepts, ... etc)

    This has the benefit of being the only option that doesn't assume this should behave the same for all invocations of xshell::cmd!. I think that assumption is reasonable, but perhaps that's not a good assumption.

  5. Having a cargo feature to use log! or something might work too, although I'm not already using log, and would need to do some finagling to make things work, since now I'd need to depend on log, and find or write a logger impl that uses stderr, and add code to enable it by default since I think that's useful still...

    So, while this is in some ways the most "correct" option, but would be my least favorite, since it's the biggest hassle. That said, it would still work.

Any of these would be fine by me, and I could contribute any of them if they'd be accepted. (It's more or less in the order that I find palatable, but that's also essentially the same as the order of "most work -> least work" in terms of using this)

Thanks.

Cannot interpolate numerical values with cmd! macro

the trait `AsRef<OsStr>` is not implemented for `u32`

I can see the point of AsRef<OsStr> since regular strings and paths behave as expected (Display would present a problem), but many external programs take numerical parameters.

I wonder what the consequences are of using Debug instead?

README clarification about cross-platform

xshell provides a set of cross-platform utilities for writing ergonomic "bash" scripts

when I see bash in quotes, and read cross-platform, and know it is doing this stuff from within rust, my mind tells me:

Oh, this must use a rust-native reimplementation of common *NIX shell utilities

But reading more, I get the idea that... it is something else, and running "sed -e ..." with this tool on windows would fail on a bare windows without extra BASH utilities installed, for example.
Thus, I would like to see this clarified in the README and docs - in what way is this cross-platform?

Please provide pipe functionality

Hi,

I love using xshell and the xtask approach, but what I am completely missing is support for piping commands together.

Please provide a functionality to pipe commands like
cmd!("echo hi") | cmd!("grep i").run()?
or
cmd!("echo hi").pipe("grep i").run()?

Thanks

Can we have the old API back?

I recently saw the announcement of xshell 0.2. I'm a very happy user of 0.1 and can not see what having to keep around a Shell instance buys me. I wasn't actually aware that the process-global environment was being changed previously (though I never touched the probably more problematic pushenv, only pushd and cmd!), I would have assumed that xshell has its own global / thread-local / whatever state tracking that its commands use.

Would you consider returning cmd! without the leading sh argument and global pushd (plus maybe pushenv) as a layer on top of the new Shell API?

Questions regarding this project?

So I have some questions regarding this project:

  1. Am I legally allowed to use this crate and close source my source code (not that I am planning to do this)?
  2. Would it run the same on Linux and Windows?
  3. Does this actually run shell scripts or is it all native?
  4. Say if I wanted to delete all the file names except one specific file name, what would exactly be the command?

Clarify in which sense the shell provides "independence of the host environment"

The docs say

Reliability: no shell injection by construction, good error messages with file paths, non-zero exit status is an error, independence of the host environment, etc.

I first thought this would mean that the shell doesn't forward the entire host environment to the called programs. However, a quick test with cmd!(Shell::new()?, "env").run()? showed that the environment is forwarded. It might be worth clarifying what is meant by "independence" here.

Get exit code of commands with inherited stdout/stderr

I have a use case where I'm running some subcommands of a CLI tool using xshell that may take some time and so would like to have their output appear immediately on the terminal where the CLI tool was invoked. As far as I understand, this is what Cmd::run will do by making stdout and stderr inherited. However, I also want to look at the exit code of the xshell Command to check why it failed (if it failed).

Currently, Cmd::run returns a Result with xshell::Error in the Err case, which is... very opaque (it basically just implements Error, so you can print it out). The contained ErrorKind does have a Variant CmdStatus { cmd: CmdData, status: ExitStatus } which you get if check_status fails, but there's a Doc comment on that enum that says "Note: this is intentionally not public.".

What I'm currently doing is calling Cmd::output instead to get the Output and the contained ExitStatus and then re-emitting the Output's stdout and stderr manually. This works, but has the downside of introducing a very noticeable delay between running the subcommand and seeing it's output, since in particular the output doesn't show up "live" but instead only appears when the subcommand has either succeeded or failed. But I don't know how to change that, since Cmd::output calls output_impl(true, true) directly.

Escaped quotation mark not handled properly

The following:

let foobar = "foo bar";
xshell::cmd!("ls \"{foobar}\"");

fails with:

error[E0765]: unterminated double quote string
  --> websites/print_css/src/main.rs:90:29
   |
90 | ...                   xshell::cmd!("ls \"{foobar}\"");
   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Adding a space after the last escaped quotation mark works:

let foobar = "foo bar";
xshell::cmd!("ls \"{foobar}\" ");

`stdin` broken since release `0.2.3`

Since 0.2.3 the run function now uses output_impl and output_impl is missing the option to allow stdin to be Stdio::inherit(), which I guess should have been the default behaviour. In practice this breaks interaction with commands being executed by run.

I think https://github.com/matklad/xshell/blob/master/src/lib.rs#L1011-L1014 should account for the case where one wants stdin to be inherited. So possibly output_impl also needs a ignore_stdin argument to switch stdin to Stdio::none(). If you want I can write a piece of code to demonstrate the bug.

Failure on Windows when running `npm ...`

The following script works perfectly fine on Linux systems, but will fail on Windows (command not found)

cmd!(sh,"npm --help").run()?;

The reason for that seems to be related to
rust-lang/rust#42791

I'm not sure if there's an easy fix for this at all, but I figured that it would be worthwhile to at least open an issue for it. This way, it's at least documented somewhere.

Feature request: Add a way to *extend* an existing `Cmd` with syntax very similar to `cmd!`

The cmd! macro is great: commands are quickly written, very readable, and whitespace-safe. However, when the shell scripting becomes a bit more complicated, one quickly hits a frustrating limitation: I have a lot of cmd! invocations in my script that are very similar, but there is no good way to abstract the commonalities into a helper function. The problem is that the cmd! macro can be used only exactly once per command, so it's not possible to have a helper prepare a Cmd value with all the things that are common across my script and then later conveniently add more arguments to it.

In my case, what I'd like to be able to do looks roughly like this:

fn cargo(&self, subcommand: &str) -> Cmd {
  // ...
  cmd!("cargo +{toolchain} {subcommand} {cargo_extra_flags...} --manifest-path={manifest_path}")
    .env(...)
}

fn other_function(&self, ...) {
  extend_cmd!(
    self.cargo("build"),
    "--bins --tests {quiet_flag...} {args...}",
  ).run()?;
}

But currently, I have to instead either repeat the cargo +{toolchain} {subcommand} {cargo_extra_flags...} --manifest-path={manifest_path} part everywhere or write

fn other_function(&self, ...) {
  let cmd = self.cargo("build")
    .args(&["--bins", "--tests"])
    .args(quiet_flag)
    .args(args)
}

which is a lot less readable than what one can do with cmd!.

Remove all files inside a directory

Hi.

I am having a hard time removing all files inside a directory. With bash, I can use rm -rf /home/user/.tmp/* (note asterisk).
With xshell, it doesn't work.

    cmd!(sh, "rm -rf /home/user/.tmp/*").run()?;  // ⚠️, doesn't work
    sh.remove_path("/home/user/.tmp/*")?;  // ⚠️, doesn't work

My only option is to remove the .tmp directory and recreate it again.
Is there any way to tell xshell to remove the content of a directory, similar to .tmp/*, leaving the parent directory (.tmp) intact?

Thanks a lot for xshell ❤️

Add a `cmds!` that runs multiple

Basically would allow going from e.g.:

cmd!(sh, "foo --blah").run()?;
cmd!(sh, "othercmd --somearg --otherarg").run()?;
cmd!(sh, "bar --baz").run()?;

to

cmds!(sh, "foo --blah
othercmd --somearg --otherarg
bar --baz").run()?;

Happy to try implementing this if you agree; roughtly I think we'd return a struct CmdList(Vec<Cmd>) in this case whose only method is fn run(self) -> Result<()> or so?

Optional syntax for multiple arguments as well as for one optional argument

Bool then function suits pretty good in terms of optional arguments, but current cmd! do not support Option with multiple arguments.

Having optional syntax available for multiple arguments as well as for one argument gives cleaner code. So instead of writing every time if condition { ... } else { ... } for several arguments we can use Option either for one argument and many arguments.
With that feature this code from documentation

let check = if true { &["--", "--check"] } else { &[][..] };
assert_eq!(
    cmd!("cargo fmt {check...}").to_string(),
    "cargo fmt -- --check"
);

let dry_run = if true { Some("--dry-run") } else { None };
assert_eq!(
    cmd!("git push {dry_run...}").to_string(),
    "git push --dry-run"
);

Can be rewritten as

let condition = true;
let check = condition.then(|| &["--", "--check"]);
assert_eq!(
    cmd!("cargo fmt {check...}").to_string(),
    "cargo fmt -- --check"
);

let dry_run = condition.then(|| "--dry-run");
assert_eq!(
    cmd!("git push {dry_run...}").to_string(),
    "git push --dry-run"
);

Document that tests require a gnu-like shell

Specifically, running tests in Powershell, I ran into test failures (in the details below), but everything passed in Git Bash. Specifically, it looks like use of false and echo failed.

Tests don't necessarily need to pass in every shell context out there (though it would be convenient, since xshell is trying to make exactly that more practical); it'd just be nice to document the required environment.

Alternative solutions:

  • Rewrite the failing tests to not use echo/false, just (ab)using cargo, clippy, and/or rustc, which are known to be present instead
  • Provide shims for echo and false for prominent non-gnu-like shells as people request them
Test failures on Powershell
failures:

---- program_interpolation stdout ----
thread 'program_interpolation' panicked at 'called `Result::unwrap()` on an `Err` value: command not found: `echo`', tests\it.rs:34:46
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

---- ignore_status stdout ----
thread 'ignore_status' panicked at 'called `Result::unwrap()` on an `Err` value: command not found: `false`', tests\it.rs:82:55

---- interpolation_move stdout ----
thread 'interpolation_move' panicked at 'called `Result::unwrap()` on an `Err` value: command not found: `echo`', tests\it.rs:49:47

---- interpolation stdout ----
thread 'interpolation' panicked at 'called `Result::unwrap()` on an `Err` value: command not found: `echo`', tests\it.rs:27:46

---- multiline stdout ----
thread 'multiline' panicked at 'called `Result::unwrap()` on an `Err` value: command not found: `echo`', tests\it.rs:20:6

---- interpolation_concatenation stdout ----
thread 'interpolation_concatenation' panicked at 'called `Result::unwrap()` on an `Err` value: command not found: `echo`', tests\it.rs:42:54

---- exit_status stdout ----
thread 'exit_status' panicked at 'assertion failed: `(left == right)`
  left: `"command not found: `false`"`,
 right: `"command `false` failed, exit code: 1"`', tests\it.rs:77:5

---- interpolation_spat stdout ----
thread 'interpolation_spat' panicked at 'called `Result::unwrap()` on an `Err` value: command not found: `echo`', tests\it.rs:59:59

---- escape stdout ----
thread 'escape' panicked at 'called `Result::unwrap()` on an `Err` value: command not found: `echo`', tests\it.rs:107:60

failures:
    escape
    exit_status
    ignore_status
    interpolation
    interpolation_concatenation
    interpolation_move
    interpolation_spat
    multiline
    program_interpolation

test result: FAILED. 17 passed; 9 failed; 0 ignored; 0 measured; 0 filtered out; finished in 5.03s

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.