Skip to content

Configuration order of stdio joining and redirection matters #116

Description

@13k

Issue

Looks like the order in which joining (Expression::stdout_to_stderr, Expression::stderr_to_stdout) and redirection (Expression::std{out,err}_path) configuration methods are called results in different behaviors (could also be considered incorrect behavior).

If redirection is used before joining, the joining configuration is ignored:

//# duct = "0.13.7"

use duct::cmd;

fn main() {
    let cmd = cmd!("sh", "-c", "echo out && echo err 1>&2")
        .stdout_path("/tmp/out")
        .stderr_to_stdout();

    println!("{:?}", cmd);

    cmd.run().expect("command error");
}
❱ cargo play -q duct.rs 
Io(StderrToStdout, Io(StdoutPath("/tmp/out"), Cmd(["sh", "-c", "echo out && echo err 1>&2"])))
err

❱ cat /tmp/out
out

If redirection is set up after joining, it works as expected:

let cmd = cmd!("sh", "-c", "echo out && echo err 1>&2")
    .stderr_to_stdout()
    .stdout_path("/tmp/out");
}
❱ cargo play -q duct.rs 
Io(StdoutPath("/tmp/out"), Io(StderrToStdout, Cmd(["sh", "-c", "echo out && echo err 1>&2"])))

❱ cat /tmp/out
out
err

Discussion

Since Expression is structured as a binary tree, I'm not sure how to solve this. Rearranging tree nodes in a custom precedence order seems overkill.

Generating an intermediary flat structure from the tree, then sorting it by precedence, seems more viable. In this case, IoExpressionInner could implement Ord with a custom precedence ordering.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions