Refactor core::run in order to address many of the issues
mentioned in #2625. This change makes the module more oriented around Process values instead of having to deal with process ids directly. Apart from issues mentioned in #2625, other changes include: - Changing the naming to be more consistent - Process/process is now used instead of a mixture of Program/program and Process/process. - More docs/tests. Some io/scheduler related issues remain (mentioned in #2625).
This commit is contained in:
parent
d577eafff3
commit
76c31217be
12 changed files with 703 additions and 493 deletions
|
@ -10,8 +10,6 @@
|
||||||
|
|
||||||
use core::prelude::*;
|
use core::prelude::*;
|
||||||
|
|
||||||
use core::libc::c_int;
|
|
||||||
use core::run::spawn_process;
|
|
||||||
use core::run;
|
use core::run;
|
||||||
|
|
||||||
#[cfg(target_os = "win32")]
|
#[cfg(target_os = "win32")]
|
||||||
|
@ -38,86 +36,35 @@ fn target_env(lib_path: &str, prog: &str) -> ~[(~str,~str)] {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
#[cfg(target_os = "freebsd")]
|
#[cfg(target_os = "freebsd")]
|
||||||
fn target_env(_lib_path: &str, _prog: &str) -> ~[(~str,~str)] {
|
fn target_env(_lib_path: &str, _prog: &str) -> ~[(~str,~str)] {
|
||||||
~[]
|
os::env()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Result {status: int, out: ~str, err: ~str}
|
pub struct Result {status: int, out: ~str, err: ~str}
|
||||||
|
|
||||||
// FIXME (#2659): This code is duplicated in core::run::program_output
|
|
||||||
pub fn run(lib_path: &str,
|
pub fn run(lib_path: &str,
|
||||||
prog: &str,
|
prog: &str,
|
||||||
args: &[~str],
|
args: &[~str],
|
||||||
env: ~[(~str, ~str)],
|
env: ~[(~str, ~str)],
|
||||||
input: Option<~str>) -> Result {
|
input: Option<~str>) -> Result {
|
||||||
let pipe_in = os::pipe();
|
|
||||||
let pipe_out = os::pipe();
|
|
||||||
let pipe_err = os::pipe();
|
|
||||||
let pid = spawn_process(prog, args,
|
|
||||||
&Some(env + target_env(lib_path, prog)),
|
|
||||||
&None, pipe_in.in, pipe_out.out, pipe_err.out);
|
|
||||||
|
|
||||||
os::close(pipe_in.in);
|
let env = env + target_env(lib_path, prog);
|
||||||
os::close(pipe_out.out);
|
let mut proc = run::Process::new(prog, args, run::ProcessOptions {
|
||||||
os::close(pipe_err.out);
|
env: Some(env.slice(0, env.len())),
|
||||||
if pid == -1i32 {
|
dir: None,
|
||||||
os::close(pipe_in.out);
|
in_fd: None,
|
||||||
os::close(pipe_out.in);
|
out_fd: None,
|
||||||
os::close(pipe_err.in);
|
err_fd: None
|
||||||
fail!();
|
});
|
||||||
|
|
||||||
|
for input.each |input| {
|
||||||
|
proc.input().write_str(*input);
|
||||||
}
|
}
|
||||||
|
let output = proc.finish_with_output();
|
||||||
|
|
||||||
|
Result {
|
||||||
writeclose(pipe_in.out, input);
|
status: output.status,
|
||||||
let p = comm::PortSet::new();
|
out: str::from_bytes(output.output),
|
||||||
let ch = p.chan();
|
err: str::from_bytes(output.error)
|
||||||
do task::spawn_sched(task::SingleThreaded) || {
|
|
||||||
let errput = readclose(pipe_err.in);
|
|
||||||
ch.send((2, errput));
|
|
||||||
}
|
|
||||||
let ch = p.chan();
|
|
||||||
do task::spawn_sched(task::SingleThreaded) || {
|
|
||||||
let output = readclose(pipe_out.in);
|
|
||||||
ch.send((1, output));
|
|
||||||
}
|
|
||||||
let status = run::waitpid(pid);
|
|
||||||
let mut errs = ~"";
|
|
||||||
let mut outs = ~"";
|
|
||||||
let mut count = 2;
|
|
||||||
while count > 0 {
|
|
||||||
match p.recv() {
|
|
||||||
(1, s) => {
|
|
||||||
outs = s;
|
|
||||||
}
|
|
||||||
(2, s) => {
|
|
||||||
errs = s;
|
|
||||||
}
|
|
||||||
_ => { fail!() }
|
|
||||||
};
|
|
||||||
count -= 1;
|
|
||||||
};
|
|
||||||
return Result {status: status, out: outs, err: errs};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn writeclose(fd: c_int, s: Option<~str>) {
|
|
||||||
if s.is_some() {
|
|
||||||
let writer = io::fd_writer(fd, false);
|
|
||||||
writer.write_str(s.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
os::close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn readclose(fd: c_int) -> ~str {
|
|
||||||
unsafe {
|
|
||||||
// Copied from run::program_output
|
|
||||||
let file = os::fdopen(fd);
|
|
||||||
let reader = io::FILE_reader(file, false);
|
|
||||||
let mut buf = ~"";
|
|
||||||
while !reader.eof() {
|
|
||||||
let bytes = reader.read_bytes(4096u);
|
|
||||||
str::push_str(&mut buf, str::from_bytes(bytes));
|
|
||||||
}
|
|
||||||
os::fclose(file);
|
|
||||||
return buf;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -415,7 +415,7 @@ fn test() {
|
||||||
prep.declare_input("file", pth.to_str(), digest_file(&pth));
|
prep.declare_input("file", pth.to_str(), digest_file(&pth));
|
||||||
do prep.exec |_exe| {
|
do prep.exec |_exe| {
|
||||||
let out = Path("foo.o");
|
let out = Path("foo.o");
|
||||||
run::run_program("gcc", [~"foo.c", ~"-o", out.to_str()]);
|
run::process_status("gcc", [~"foo.c", ~"-o", out.to_str()]);
|
||||||
out.to_str()
|
out.to_str()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -412,20 +412,20 @@ pub fn check_whole_compiler(code: &str,
|
||||||
pub fn removeIfExists(filename: &Path) {
|
pub fn removeIfExists(filename: &Path) {
|
||||||
// So sketchy!
|
// So sketchy!
|
||||||
assert!(!contains(filename.to_str(), " "));
|
assert!(!contains(filename.to_str(), " "));
|
||||||
run::program_output("bash", [~"-c", ~"rm " + filename.to_str()]);
|
run::process_status("bash", [~"-c", ~"rm " + filename.to_str()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn removeDirIfExists(filename: &Path) {
|
pub fn removeDirIfExists(filename: &Path) {
|
||||||
// So sketchy!
|
// So sketchy!
|
||||||
assert!(!contains(filename.to_str(), " "));
|
assert!(!contains(filename.to_str(), " "));
|
||||||
run::program_output("bash", [~"-c", ~"rm -r " + filename.to_str()]);
|
run::process_status("bash", [~"-c", ~"rm -r " + filename.to_str()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_running(exe_filename: &Path) -> happiness {
|
pub fn check_running(exe_filename: &Path) -> happiness {
|
||||||
let p = run::program_output(
|
let p = run::process_output(
|
||||||
"/Users/jruderman/scripts/timed_run_rust_program.py",
|
"/Users/jruderman/scripts/timed_run_rust_program.py",
|
||||||
[exe_filename.to_str()]);
|
[exe_filename.to_str()]);
|
||||||
let comb = p.out + ~"\n" + p.err;
|
let comb = str::from_bytes(p.output) + ~"\n" + str::from_bytes(p.error);
|
||||||
if str::len(comb) > 1u {
|
if str::len(comb) > 1u {
|
||||||
error!("comb comb comb: %?", comb);
|
error!("comb comb comb: %?", comb);
|
||||||
}
|
}
|
||||||
|
@ -461,33 +461,35 @@ pub fn check_running(exe_filename: &Path) -> happiness {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_compiling(filename: &Path) -> happiness {
|
pub fn check_compiling(filename: &Path) -> happiness {
|
||||||
let p = run::program_output(
|
let p = run::process_output(
|
||||||
"/Users/jruderman/code/rust/build/x86_64-apple-darwin/\
|
"/Users/jruderman/code/rust/build/x86_64-apple-darwin/stage1/bin/rustc",
|
||||||
stage1/bin/rustc",
|
|
||||||
[filename.to_str()]);
|
[filename.to_str()]);
|
||||||
|
|
||||||
|
let out = str::from_bytes(p.output);
|
||||||
|
let err = str::from_bytes(p.error);
|
||||||
|
|
||||||
//error!("Status: %d", p.status);
|
//error!("Status: %d", p.status);
|
||||||
if p.status == 0 {
|
if p.status == 0 {
|
||||||
passed
|
passed
|
||||||
} else if p.err != ~"" {
|
} else if !err.is_empty() {
|
||||||
if contains(p.err, "error:") {
|
if err.contains("error:") {
|
||||||
cleanly_rejected(~"rejected with span_error")
|
cleanly_rejected(~"rejected with span_error")
|
||||||
} else {
|
} else {
|
||||||
error!("Stderr: %?", p.err);
|
error!("Stderr: %?", err);
|
||||||
failed(~"Unfamiliar error message")
|
failed(~"Unfamiliar error message")
|
||||||
}
|
}
|
||||||
} else if contains(p.out, "Assertion") && contains(p.out, "failed") {
|
} else if out.contains("Assertion") && out.contains("failed") {
|
||||||
error!("Stdout: %?", p.out);
|
error!("Stdout: %?", out);
|
||||||
failed(~"Looks like an llvm assertion failure")
|
failed(~"Looks like an llvm assertion failure")
|
||||||
} else if contains(p.out, "internal compiler error unimplemented") {
|
} else if out.contains("internal compiler error unimplemented") {
|
||||||
known_bug(~"Something unimplemented")
|
known_bug(~"Something unimplemented")
|
||||||
} else if contains(p.out, "internal compiler error") {
|
} else if out.contains("internal compiler error") {
|
||||||
error!("Stdout: %?", p.out);
|
error!("Stdout: %?", out);
|
||||||
failed(~"internal compiler error")
|
failed(~"internal compiler error")
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
error!("%?", p.status);
|
error!("%?", p.status);
|
||||||
error!("!Stdout: %?", p.out);
|
error!("!Stdout: %?", out);
|
||||||
failed(~"What happened?")
|
failed(~"What happened?")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -608,9 +610,7 @@ pub fn check_roundtrip_convergence(code: @~str, maxIters: uint) {
|
||||||
error!("Did not converge after %u iterations!", i);
|
error!("Did not converge after %u iterations!", i);
|
||||||
write_file(&Path("round-trip-a.rs"), *oldv);
|
write_file(&Path("round-trip-a.rs"), *oldv);
|
||||||
write_file(&Path("round-trip-b.rs"), *newv);
|
write_file(&Path("round-trip-b.rs"), *newv);
|
||||||
run::run_program("diff",
|
run::process_status("diff", [~"-w", ~"-u", ~"round-trip-a.rs", ~"round-trip-b.rs"]);
|
||||||
[~"-w", ~"-u", ~"round-trip-a.rs",
|
|
||||||
~"round-trip-b.rs"]);
|
|
||||||
fail!("Mismatch");
|
fail!("Mismatch");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,7 +163,7 @@ fn cmd_test(args: &[~str]) -> ValidUsage {
|
||||||
let test_exec = Path(filename).filestem().unwrap() + "test~";
|
let test_exec = Path(filename).filestem().unwrap() + "test~";
|
||||||
invoke("rustc", &[~"--test", filename.to_owned(),
|
invoke("rustc", &[~"--test", filename.to_owned(),
|
||||||
~"-o", test_exec.to_owned()], rustc::main);
|
~"-o", test_exec.to_owned()], rustc::main);
|
||||||
let exit_code = run::run_program(~"./" + test_exec, []);
|
let exit_code = run::process_status(~"./" + test_exec, []);
|
||||||
Valid(exit_code)
|
Valid(exit_code)
|
||||||
}
|
}
|
||||||
_ => Invalid
|
_ => Invalid
|
||||||
|
@ -176,7 +176,7 @@ fn cmd_run(args: &[~str]) -> ValidUsage {
|
||||||
let exec = Path(filename).filestem().unwrap() + "~";
|
let exec = Path(filename).filestem().unwrap() + "~";
|
||||||
invoke("rustc", &[filename.to_owned(), ~"-o", exec.to_owned()],
|
invoke("rustc", &[filename.to_owned(), ~"-o", exec.to_owned()],
|
||||||
rustc::main);
|
rustc::main);
|
||||||
let exit_code = run::run_program(~"./"+exec, prog_args);
|
let exit_code = run::process_status(~"./"+exec, prog_args);
|
||||||
Valid(exit_code)
|
Valid(exit_code)
|
||||||
}
|
}
|
||||||
_ => Invalid
|
_ => Invalid
|
||||||
|
|
|
@ -403,14 +403,14 @@ pub mod write {
|
||||||
cc_args.push(object.to_str());
|
cc_args.push(object.to_str());
|
||||||
cc_args.push(assembly.to_str());
|
cc_args.push(assembly.to_str());
|
||||||
|
|
||||||
let prog = run::program_output(cc_prog, cc_args);
|
let prog = run::process_output(cc_prog, cc_args);
|
||||||
|
|
||||||
if prog.status != 0 {
|
if prog.status != 0 {
|
||||||
sess.err(fmt!("building with `%s` failed with code %d",
|
sess.err(fmt!("building with `%s` failed with code %d",
|
||||||
cc_prog, prog.status));
|
cc_prog, prog.status));
|
||||||
sess.note(fmt!("%s arguments: %s",
|
sess.note(fmt!("%s arguments: %s",
|
||||||
cc_prog, str::connect(cc_args, " ")));
|
cc_prog, str::connect(cc_args, " ")));
|
||||||
sess.note(prog.err + prog.out);
|
sess.note(str::from_bytes(prog.error + prog.output));
|
||||||
sess.abort_if_errors();
|
sess.abort_if_errors();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -817,19 +817,19 @@ pub fn link_binary(sess: Session,
|
||||||
let cc_args = link_args(sess, obj_filename, out_filename, lm);
|
let cc_args = link_args(sess, obj_filename, out_filename, lm);
|
||||||
debug!("%s link args: %s", cc_prog, str::connect(cc_args, " "));
|
debug!("%s link args: %s", cc_prog, str::connect(cc_args, " "));
|
||||||
// We run 'cc' here
|
// We run 'cc' here
|
||||||
let prog = run::program_output(cc_prog, cc_args);
|
let prog = run::process_output(cc_prog, cc_args);
|
||||||
if 0 != prog.status {
|
if 0 != prog.status {
|
||||||
sess.err(fmt!("linking with `%s` failed with code %d",
|
sess.err(fmt!("linking with `%s` failed with code %d",
|
||||||
cc_prog, prog.status));
|
cc_prog, prog.status));
|
||||||
sess.note(fmt!("%s arguments: %s",
|
sess.note(fmt!("%s arguments: %s",
|
||||||
cc_prog, str::connect(cc_args, " ")));
|
cc_prog, str::connect(cc_args, " ")));
|
||||||
sess.note(prog.err + prog.out);
|
sess.note(str::from_bytes(prog.error + prog.output));
|
||||||
sess.abort_if_errors();
|
sess.abort_if_errors();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up on Darwin
|
// Clean up on Darwin
|
||||||
if sess.targ_cfg.os == session::os_macos {
|
if sess.targ_cfg.os == session::os_macos {
|
||||||
run::run_program("dsymutil", [output.to_str()]);
|
run::process_status("dsymutil", [output.to_str()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the temporary object file if we aren't saving temps
|
// Remove the temporary object file if we aren't saving temps
|
||||||
|
|
|
@ -12,7 +12,7 @@ use core::prelude::*;
|
||||||
|
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use core::run;
|
use core::run;
|
||||||
use core::run::ProgramOutput;
|
use core::run::ProcessOutput;
|
||||||
use core::result::Result;
|
use core::result::Result;
|
||||||
use extra::getopts;
|
use extra::getopts;
|
||||||
|
|
||||||
|
@ -89,27 +89,27 @@ pub fn default_config(input_crate: &Path) -> Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Process = ~fn((&str), (&[~str])) -> ProgramOutput;
|
type Process = ~fn((&str), (&[~str])) -> ProcessOutput;
|
||||||
|
|
||||||
pub fn mock_program_output(_prog: &str, _args: &[~str]) -> ProgramOutput {
|
pub fn mock_process_output(_prog: &str, _args: &[~str]) -> ProcessOutput {
|
||||||
ProgramOutput {
|
ProcessOutput {
|
||||||
status: 0,
|
status: 0,
|
||||||
out: ~"",
|
output: ~[],
|
||||||
err: ~""
|
error: ~[]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn program_output(prog: &str, args: &[~str]) -> ProgramOutput {
|
pub fn process_output(prog: &str, args: &[~str]) -> ProcessOutput {
|
||||||
run::program_output(prog, args)
|
run::process_output(prog, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_config(args: &[~str]) -> Result<Config, ~str> {
|
pub fn parse_config(args: &[~str]) -> Result<Config, ~str> {
|
||||||
parse_config_(args, program_output)
|
parse_config_(args, process_output)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_config_(
|
pub fn parse_config_(
|
||||||
args: &[~str],
|
args: &[~str],
|
||||||
program_output: Process
|
process_output: Process
|
||||||
) -> Result<Config, ~str> {
|
) -> Result<Config, ~str> {
|
||||||
let args = args.tail();
|
let args = args.tail();
|
||||||
let opts = vec::unzip(opts()).first();
|
let opts = vec::unzip(opts()).first();
|
||||||
|
@ -117,7 +117,7 @@ pub fn parse_config_(
|
||||||
Ok(matches) => {
|
Ok(matches) => {
|
||||||
if matches.free.len() == 1 {
|
if matches.free.len() == 1 {
|
||||||
let input_crate = Path(*matches.free.head());
|
let input_crate = Path(*matches.free.head());
|
||||||
config_from_opts(&input_crate, &matches, program_output)
|
config_from_opts(&input_crate, &matches, process_output)
|
||||||
} else if matches.free.is_empty() {
|
} else if matches.free.is_empty() {
|
||||||
Err(~"no crates specified")
|
Err(~"no crates specified")
|
||||||
} else {
|
} else {
|
||||||
|
@ -133,7 +133,7 @@ pub fn parse_config_(
|
||||||
fn config_from_opts(
|
fn config_from_opts(
|
||||||
input_crate: &Path,
|
input_crate: &Path,
|
||||||
matches: &getopts::Matches,
|
matches: &getopts::Matches,
|
||||||
program_output: Process
|
process_output: Process
|
||||||
) -> Result<Config, ~str> {
|
) -> Result<Config, ~str> {
|
||||||
|
|
||||||
let config = default_config(input_crate);
|
let config = default_config(input_crate);
|
||||||
|
@ -175,11 +175,11 @@ fn config_from_opts(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let program_output = Cell(program_output);
|
let process_output = Cell(process_output);
|
||||||
let result = do result::chain(result) |config| {
|
let result = do result::chain(result) |config| {
|
||||||
let pandoc_cmd = getopts::opt_maybe_str(matches, opt_pandoc_cmd());
|
let pandoc_cmd = getopts::opt_maybe_str(matches, opt_pandoc_cmd());
|
||||||
let pandoc_cmd = maybe_find_pandoc(
|
let pandoc_cmd = maybe_find_pandoc(
|
||||||
&config, pandoc_cmd, program_output.take());
|
&config, pandoc_cmd, process_output.take());
|
||||||
do result::chain(pandoc_cmd) |pandoc_cmd| {
|
do result::chain(pandoc_cmd) |pandoc_cmd| {
|
||||||
result::Ok(Config {
|
result::Ok(Config {
|
||||||
pandoc_cmd: pandoc_cmd,
|
pandoc_cmd: pandoc_cmd,
|
||||||
|
@ -209,7 +209,7 @@ fn parse_output_style(output_style: &str) -> Result<OutputStyle, ~str> {
|
||||||
pub fn maybe_find_pandoc(
|
pub fn maybe_find_pandoc(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
maybe_pandoc_cmd: Option<~str>,
|
maybe_pandoc_cmd: Option<~str>,
|
||||||
program_output: Process
|
process_output: Process
|
||||||
) -> Result<Option<~str>, ~str> {
|
) -> Result<Option<~str>, ~str> {
|
||||||
if config.output_format != PandocHtml {
|
if config.output_format != PandocHtml {
|
||||||
return result::Ok(maybe_pandoc_cmd);
|
return result::Ok(maybe_pandoc_cmd);
|
||||||
|
@ -228,7 +228,7 @@ pub fn maybe_find_pandoc(
|
||||||
};
|
};
|
||||||
|
|
||||||
let pandoc = do vec::find(possible_pandocs) |pandoc| {
|
let pandoc = do vec::find(possible_pandocs) |pandoc| {
|
||||||
let output = program_output(*pandoc, [~"--version"]);
|
let output = process_output(*pandoc, [~"--version"]);
|
||||||
debug!("testing pandoc cmd %s: %?", *pandoc, output);
|
debug!("testing pandoc cmd %s: %?", *pandoc, output);
|
||||||
output.status == 0
|
output.status == 0
|
||||||
};
|
};
|
||||||
|
@ -244,10 +244,10 @@ pub fn maybe_find_pandoc(
|
||||||
mod test {
|
mod test {
|
||||||
use core::prelude::*;
|
use core::prelude::*;
|
||||||
use config::*;
|
use config::*;
|
||||||
use core::run::ProgramOutput;
|
use core::run::ProcessOutput;
|
||||||
|
|
||||||
fn parse_config(args: &[~str]) -> Result<Config, ~str> {
|
fn parse_config(args: &[~str]) -> Result<Config, ~str> {
|
||||||
parse_config_(args, mock_program_output)
|
parse_config_(args, mock_process_output)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -256,10 +256,10 @@ mod test {
|
||||||
output_format: PandocHtml,
|
output_format: PandocHtml,
|
||||||
.. default_config(&Path("test"))
|
.. default_config(&Path("test"))
|
||||||
};
|
};
|
||||||
let mock_program_output: ~fn(&str, &[~str]) -> ProgramOutput = |_, _| {
|
let mock_process_output: ~fn(&str, &[~str]) -> ProcessOutput = |_, _| {
|
||||||
ProgramOutput { status: 0, out: ~"pandoc 1.8.2.1", err: ~"" }
|
ProcessOutput { status: 0, output: "pandoc 1.8.2.1".to_bytes(), error: ~[] }
|
||||||
};
|
};
|
||||||
let result = maybe_find_pandoc(&config, None, mock_program_output);
|
let result = maybe_find_pandoc(&config, None, mock_process_output);
|
||||||
assert!(result == result::Ok(Some(~"pandoc")));
|
assert!(result == result::Ok(Some(~"pandoc")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,10 +269,10 @@ mod test {
|
||||||
output_format: PandocHtml,
|
output_format: PandocHtml,
|
||||||
.. default_config(&Path("test"))
|
.. default_config(&Path("test"))
|
||||||
};
|
};
|
||||||
let mock_program_output: ~fn(&str, &[~str]) -> ProgramOutput = |_, _| {
|
let mock_process_output: ~fn(&str, &[~str]) -> ProcessOutput = |_, _| {
|
||||||
ProgramOutput { status: 1, out: ~"", err: ~"" }
|
ProcessOutput { status: 1, output: ~[], error: ~[] }
|
||||||
};
|
};
|
||||||
let result = maybe_find_pandoc(&config, None, mock_program_output);
|
let result = maybe_find_pandoc(&config, None, mock_process_output);
|
||||||
assert!(result == result::Err(~"couldn't find pandoc"));
|
assert!(result == result::Err(~"couldn't find pandoc"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ use config;
|
||||||
use doc::ItemUtils;
|
use doc::ItemUtils;
|
||||||
use doc;
|
use doc;
|
||||||
|
|
||||||
use core::libc;
|
|
||||||
use core::run;
|
use core::run;
|
||||||
use core::comm::*;
|
use core::comm::*;
|
||||||
use extra::future;
|
use extra::future;
|
||||||
|
@ -105,60 +104,20 @@ fn pandoc_writer(
|
||||||
debug!("pandoc cmd: %s", pandoc_cmd);
|
debug!("pandoc cmd: %s", pandoc_cmd);
|
||||||
debug!("pandoc args: %s", str::connect(pandoc_args, " "));
|
debug!("pandoc args: %s", str::connect(pandoc_args, " "));
|
||||||
|
|
||||||
let pipe_in = os::pipe();
|
let mut proc = run::Process::new(pandoc_cmd, pandoc_args, run::ProcessOptions::new());
|
||||||
let pipe_out = os::pipe();
|
|
||||||
let pipe_err = os::pipe();
|
|
||||||
let pid = run::spawn_process(
|
|
||||||
pandoc_cmd, pandoc_args, &None, &None,
|
|
||||||
pipe_in.in, pipe_out.out, pipe_err.out);
|
|
||||||
|
|
||||||
let writer = io::fd_writer(pipe_in.out, false);
|
proc.input().write_str(markdown);
|
||||||
writer.write_str(markdown);
|
let output = proc.finish_with_output();
|
||||||
|
|
||||||
os::close(pipe_in.in);
|
debug!("pandoc result: %i", output.status);
|
||||||
os::close(pipe_out.out);
|
if output.status != 0 {
|
||||||
os::close(pipe_err.out);
|
error!("pandoc-out: %s", str::from_bytes(output.output));
|
||||||
os::close(pipe_in.out);
|
error!("pandoc-err: %s", str::from_bytes(output.error));
|
||||||
|
|
||||||
let (stdout_po, stdout_ch) = comm::stream();
|
|
||||||
do task::spawn_sched(task::SingleThreaded) || {
|
|
||||||
stdout_ch.send(readclose(pipe_out.in));
|
|
||||||
}
|
|
||||||
|
|
||||||
let (stderr_po, stderr_ch) = comm::stream();
|
|
||||||
do task::spawn_sched(task::SingleThreaded) || {
|
|
||||||
stderr_ch.send(readclose(pipe_err.in));
|
|
||||||
}
|
|
||||||
let stdout = stdout_po.recv();
|
|
||||||
let stderr = stderr_po.recv();
|
|
||||||
|
|
||||||
let status = run::waitpid(pid);
|
|
||||||
debug!("pandoc result: %i", status);
|
|
||||||
if status != 0 {
|
|
||||||
error!("pandoc-out: %s", stdout);
|
|
||||||
error!("pandoc-err: %s", stderr);
|
|
||||||
fail!("pandoc failed");
|
fail!("pandoc failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readclose(fd: libc::c_int) -> ~str {
|
|
||||||
// Copied from run::program_output
|
|
||||||
unsafe {
|
|
||||||
let file = os::fdopen(fd);
|
|
||||||
let reader = io::FILE_reader(file, false);
|
|
||||||
let buf = io::with_bytes_writer(|writer| {
|
|
||||||
let mut bytes = [0, ..4096];
|
|
||||||
while !reader.eof() {
|
|
||||||
let nread = reader.read(bytes, bytes.len());
|
|
||||||
writer.write(bytes.slice(0, nread).to_owned());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
os::fclose(file);
|
|
||||||
str::from_bytes(buf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generic_writer(process: ~fn(markdown: ~str)) -> Writer {
|
fn generic_writer(process: ~fn(markdown: ~str)) -> Writer {
|
||||||
let (po, ch) = stream::<WriteInstr>();
|
let (po, ch) = stream::<WriteInstr>();
|
||||||
do task::spawn || {
|
do task::spawn || {
|
||||||
|
|
|
@ -131,17 +131,17 @@ impl<'self> PkgScript<'self> {
|
||||||
&exe, @copy os::args()[0],
|
&exe, @copy os::args()[0],
|
||||||
driver::cu_everything);
|
driver::cu_everything);
|
||||||
debug!("Running program: %s %s %s", exe.to_str(), root.to_str(), what);
|
debug!("Running program: %s %s %s", exe.to_str(), root.to_str(), what);
|
||||||
let status = run::run_program(exe.to_str(), [root.to_str(), what]);
|
let status = run::process_status(exe.to_str(), [root.to_str(), what]);
|
||||||
if status != 0 {
|
if status != 0 {
|
||||||
return (~[], status);
|
return (~[], status);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
debug!("Running program (configs): %s %s %s",
|
debug!("Running program (configs): %s %s %s",
|
||||||
exe.to_str(), root.to_str(), "configs");
|
exe.to_str(), root.to_str(), "configs");
|
||||||
let output = run::program_output(exe.to_str(), [root.to_str(), ~"configs"]);
|
let output = run::process_output(exe.to_str(), [root.to_str(), ~"configs"]);
|
||||||
// Run the configs() function to get the configs
|
// Run the configs() function to get the configs
|
||||||
let mut cfgs = ~[];
|
let mut cfgs = ~[];
|
||||||
for str::each_word(output.out) |w| {
|
for str::each_word(str::from_bytes(output.output)) |w| {
|
||||||
cfgs.push(w.to_owned());
|
cfgs.push(w.to_owned());
|
||||||
}
|
}
|
||||||
(cfgs, output.status)
|
(cfgs, output.status)
|
||||||
|
@ -551,7 +551,7 @@ impl PkgSrc {
|
||||||
let url = fmt!("https://%s", self.id.remote_path.to_str());
|
let url = fmt!("https://%s", self.id.remote_path.to_str());
|
||||||
util::note(fmt!("git clone %s %s", url, local.to_str()));
|
util::note(fmt!("git clone %s %s", url, local.to_str()));
|
||||||
|
|
||||||
if run::program_output("git", [~"clone", copy url, local.to_str()]).status != 0 {
|
if run::process_output("git", [~"clone", copy url, local.to_str()]).status != 0 {
|
||||||
util::note(fmt!("fetching %s failed: can't clone repository", url));
|
util::note(fmt!("fetching %s failed: can't clone repository", url));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,6 @@ pub fn main() {
|
||||||
file.write_str("pub fn wheeeee() { for [1, 2, 3].each() |_| { assert!(true); } }");
|
file.write_str("pub fn wheeeee() { for [1, 2, 3].each() |_| { assert!(true); } }");
|
||||||
|
|
||||||
// now compile the crate itself
|
// now compile the crate itself
|
||||||
run::run_program("rustc", ~[~"src/fancy-lib/fancy-lib.rs", ~"--lib",
|
run::process_status("rustc", [~"src/fancy-lib/fancy-lib.rs", ~"--lib", ~"-o",
|
||||||
~"-o", out_path.push(~"fancy_lib").to_str()]);
|
out_path.push(~"fancy_lib").to_str()]);
|
||||||
}
|
}
|
|
@ -1671,7 +1671,7 @@ mod tests {
|
||||||
fail!("%s doesn't exist", in.to_str());
|
fail!("%s doesn't exist", in.to_str());
|
||||||
}
|
}
|
||||||
assert!((rs));
|
assert!((rs));
|
||||||
let rslt = run::run_program("diff", [in.to_str(), out.to_str()]);
|
let rslt = run::process_status("diff", [in.to_str(), out.to_str()]);
|
||||||
assert_eq!(rslt, 0);
|
assert_eq!(rslt, 0);
|
||||||
assert_eq!(out.get_mode(), in_mode);
|
assert_eq!(out.get_mode(), in_mode);
|
||||||
assert!((remove_file(&in)));
|
assert!((remove_file(&in)));
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -20,13 +20,13 @@ use std::run::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_destroy_once() {
|
fn test_destroy_once() {
|
||||||
let mut p = run::start_program("echo", []);
|
let mut p = run::Process::new("echo", [], run::ProcessOptions::new());
|
||||||
p.destroy(); // this shouldn't crash (and nor should the destructor)
|
p.destroy(); // this shouldn't crash (and nor should the destructor)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_destroy_twice() {
|
fn test_destroy_twice() {
|
||||||
let mut p = run::start_program("echo", []);
|
let mut p = run::Process::new("echo", [], run::ProcessOptions::new());
|
||||||
p.destroy(); // this shouldnt crash...
|
p.destroy(); // this shouldnt crash...
|
||||||
p.destroy(); // ...and nor should this (and nor should the destructor)
|
p.destroy(); // ...and nor should this (and nor should the destructor)
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,8 @@ fn test_destroy_actually_kills(force: bool) {
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
fn process_exists(pid: libc::pid_t) -> bool {
|
fn process_exists(pid: libc::pid_t) -> bool {
|
||||||
run::program_output("ps", [~"-p", pid.to_str()]).out.contains(pid.to_str())
|
let run::ProcessOutput {output, _} = run::process_output("ps", [~"-p", pid.to_str()]);
|
||||||
|
str::from_bytes(output).contains(pid.to_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
|
@ -64,8 +65,8 @@ fn test_destroy_actually_kills(force: bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// this program will stay alive indefinitely trying to read from stdin
|
// this process will stay alive indefinitely trying to read from stdin
|
||||||
let mut p = run::start_program(BLOCK_COMMAND, []);
|
let mut p = run::Process::new(BLOCK_COMMAND, [], run::ProcessOptions::new());
|
||||||
|
|
||||||
assert!(process_exists(p.get_id()));
|
assert!(process_exists(p.get_id()));
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue