auto merge of #10936 : cadencemarseille/rust/issue-10754-std-run-unwrap-on-None, r=alexcrichton
The problem was that std::run::Process::new() was unwrap()ing the result of std::io::process::Process::new(), which returns None in the case where the io_error condition is raised to signal failure to start the process. Have std::run::Process::new() similarly return an Option\<run::Process\> to reflect the fact that a subprocess might have failed to start. Update utility functions run::process_status() and run::process_output() to return Option\<ProcessExit\> and Option\<ProcessOutput\>, respectively. Various parts of librustc and librustpkg needed to be updated to reflect these API changes. closes #10754
This commit is contained in:
commit
aafed3ece5
@ -46,10 +46,10 @@ pub fn run(lib_path: &str,
|
||||
prog: &str,
|
||||
args: &[~str],
|
||||
env: ~[(~str, ~str)],
|
||||
input: Option<~str>) -> Result {
|
||||
input: Option<~str>) -> Option<Result> {
|
||||
|
||||
let env = env + target_env(lib_path, prog);
|
||||
let mut process = run::Process::new(prog, args, run::ProcessOptions {
|
||||
let mut opt_process = run::Process::new(prog, args, run::ProcessOptions {
|
||||
env: Some(env),
|
||||
dir: None,
|
||||
in_fd: None,
|
||||
@ -57,15 +57,20 @@ pub fn run(lib_path: &str,
|
||||
err_fd: None
|
||||
});
|
||||
|
||||
for input in input.iter() {
|
||||
process.input().write(input.as_bytes());
|
||||
}
|
||||
let run::ProcessOutput { status, output, error } = process.finish_with_output();
|
||||
match opt_process {
|
||||
Some(ref mut process) => {
|
||||
for input in input.iter() {
|
||||
process.input().write(input.as_bytes());
|
||||
}
|
||||
let run::ProcessOutput { status, output, error } = process.finish_with_output();
|
||||
|
||||
Result {
|
||||
status: status,
|
||||
out: str::from_utf8_owned(output),
|
||||
err: str::from_utf8_owned(error)
|
||||
Some(Result {
|
||||
status: status,
|
||||
out: str::from_utf8_owned(output),
|
||||
err: str::from_utf8_owned(error)
|
||||
})
|
||||
},
|
||||
None => None
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,10 +78,10 @@ pub fn run_background(lib_path: &str,
|
||||
prog: &str,
|
||||
args: &[~str],
|
||||
env: ~[(~str, ~str)],
|
||||
input: Option<~str>) -> run::Process {
|
||||
input: Option<~str>) -> Option<run::Process> {
|
||||
|
||||
let env = env + target_env(lib_path, prog);
|
||||
let mut process = run::Process::new(prog, args, run::ProcessOptions {
|
||||
let opt_process = run::Process::new(prog, args, run::ProcessOptions {
|
||||
env: Some(env),
|
||||
dir: None,
|
||||
in_fd: None,
|
||||
@ -84,9 +89,14 @@ pub fn run_background(lib_path: &str,
|
||||
err_fd: None
|
||||
});
|
||||
|
||||
for input in input.iter() {
|
||||
process.input().write(input.as_bytes());
|
||||
}
|
||||
match opt_process {
|
||||
Some(mut process) => {
|
||||
for input in input.iter() {
|
||||
process.input().write(input.as_bytes());
|
||||
}
|
||||
|
||||
return process;
|
||||
Some(process)
|
||||
},
|
||||
None => None
|
||||
}
|
||||
}
|
||||
|
@ -289,20 +289,23 @@ fn run_debuginfo_test(config: &config, props: &TestProps, testfile: &Path) {
|
||||
dump_output_file(config, testfile, script_str, "debugger.script");
|
||||
|
||||
|
||||
procsrv::run("", config.adb_path.clone(),
|
||||
procsrv::run("", config.adb_path,
|
||||
[~"push", exe_file.as_str().unwrap().to_owned(), config.adb_test_dir.clone()],
|
||||
~[(~"",~"")], Some(~""));
|
||||
~[(~"",~"")], Some(~""))
|
||||
.expect(format!("failed to exec `{}`", config.adb_path));
|
||||
|
||||
procsrv::run("", config.adb_path,
|
||||
[~"forward", ~"tcp:5039", ~"tcp:5039"],
|
||||
~[(~"",~"")], Some(~""));
|
||||
~[(~"",~"")], Some(~""))
|
||||
.expect(format!("failed to exec `{}`", config.adb_path));
|
||||
|
||||
let adb_arg = format!("export LD_LIBRARY_PATH={}; gdbserver :5039 {}/{}",
|
||||
config.adb_test_dir.clone(), config.adb_test_dir.clone(),
|
||||
str::from_utf8(exe_file.filename().unwrap()));
|
||||
|
||||
let mut process = procsrv::run_background("", config.adb_path.clone(),
|
||||
[~"shell",adb_arg.clone()],~[(~"",~"")], Some(~""));
|
||||
let mut process = procsrv::run_background("", config.adb_path,
|
||||
[~"shell",adb_arg.clone()],~[(~"",~"")], Some(~""))
|
||||
.expect(format!("failed to exec `{}`", config.adb_path));
|
||||
loop {
|
||||
//waiting 1 second for gdbserver start
|
||||
timer::sleep(1000);
|
||||
@ -334,10 +337,12 @@ fn run_debuginfo_test(config: &config, props: &TestProps, testfile: &Path) {
|
||||
let debugger_opts = ~[~"-quiet", ~"-batch", ~"-nx",
|
||||
"-command=" + debugger_script.as_str().unwrap().to_owned()];
|
||||
|
||||
let gdb_path = tool_path.append("/bin/arm-linux-androideabi-gdb");
|
||||
let procsrv::Result{ out, err, status }=
|
||||
procsrv::run("",
|
||||
tool_path.append("/bin/arm-linux-androideabi-gdb"),
|
||||
debugger_opts, ~[(~"",~"")], None);
|
||||
gdb_path,
|
||||
debugger_opts, ~[(~"",~"")], None)
|
||||
.expect(format!("failed to exec `{}`", gdb_path));
|
||||
let cmdline = {
|
||||
let cmdline = make_cmdline("", "arm-linux-androideabi-gdb", debugger_opts);
|
||||
logv(config, format!("executing {}", cmdline));
|
||||
@ -800,7 +805,8 @@ fn program_output(config: &config, testfile: &Path, lib_path: &str, prog: ~str,
|
||||
cmdline
|
||||
};
|
||||
let procsrv::Result{ out, err, status } =
|
||||
procsrv::run(lib_path, prog, args, env, input);
|
||||
procsrv::run(lib_path, prog, args, env, input)
|
||||
.expect(format!("failed to exec `{}`", prog));
|
||||
dump_output(config, testfile, out, err);
|
||||
return ProcRes {status: status,
|
||||
stdout: out,
|
||||
@ -908,7 +914,8 @@ fn _arm_exec_compiled_test(config: &config, props: &TestProps,
|
||||
// copy to target
|
||||
let copy_result = procsrv::run("", config.adb_path,
|
||||
[~"push", args.prog.clone(), config.adb_test_dir.clone()],
|
||||
~[(~"",~"")], Some(~""));
|
||||
~[(~"",~"")], Some(~""))
|
||||
.expect(format!("failed to exec `{}`", config.adb_path));
|
||||
|
||||
if config.verbose {
|
||||
println!("push ({}) {} {} {}",
|
||||
@ -932,7 +939,8 @@ fn _arm_exec_compiled_test(config: &config, props: &TestProps,
|
||||
for tv in args.args.iter() {
|
||||
runargs.push(tv.to_owned());
|
||||
}
|
||||
procsrv::run("", config.adb_path, runargs, ~[(~"",~"")], Some(~""));
|
||||
procsrv::run("", config.adb_path, runargs, ~[(~"",~"")], Some(~""))
|
||||
.expect(format!("failed to exec `{}`", config.adb_path));
|
||||
|
||||
// get exitcode of result
|
||||
runargs = ~[];
|
||||
@ -942,7 +950,8 @@ fn _arm_exec_compiled_test(config: &config, props: &TestProps,
|
||||
|
||||
let procsrv::Result{ out: exitcode_out, err: _, status: _ } =
|
||||
procsrv::run("", config.adb_path, runargs, ~[(~"",~"")],
|
||||
Some(~""));
|
||||
Some(~""))
|
||||
.expect(format!("failed to exec `{}`", config.adb_path));
|
||||
|
||||
let mut exitcode : int = 0;
|
||||
for c in exitcode_out.chars() {
|
||||
@ -960,7 +969,8 @@ fn _arm_exec_compiled_test(config: &config, props: &TestProps,
|
||||
runargs.push(format!("{}/{}.stdout", config.adb_test_dir, prog_short));
|
||||
|
||||
let procsrv::Result{ out: stdout_out, err: _, status: _ } =
|
||||
procsrv::run("", config.adb_path, runargs, ~[(~"",~"")], Some(~""));
|
||||
procsrv::run("", config.adb_path, runargs, ~[(~"",~"")], Some(~""))
|
||||
.expect(format!("failed to exec `{}`", config.adb_path));
|
||||
|
||||
// get stderr of result
|
||||
runargs = ~[];
|
||||
@ -969,7 +979,8 @@ fn _arm_exec_compiled_test(config: &config, props: &TestProps,
|
||||
runargs.push(format!("{}/{}.stderr", config.adb_test_dir, prog_short));
|
||||
|
||||
let procsrv::Result{ out: stderr_out, err: _, status: _ } =
|
||||
procsrv::run("", config.adb_path, runargs, ~[(~"",~"")], Some(~""));
|
||||
procsrv::run("", config.adb_path, runargs, ~[(~"",~"")], Some(~""))
|
||||
.expect(format!("failed to exec `{}`", config.adb_path));
|
||||
|
||||
dump_output(config, testfile, stdout_out, stderr_out);
|
||||
|
||||
@ -1004,7 +1015,8 @@ fn _arm_push_aux_shared_library(config: &config, testfile: &Path) {
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
let copy_result = procsrv::run("", config.adb_path,
|
||||
[~"push", file.as_str().unwrap().to_owned(), config.adb_test_dir.clone()],
|
||||
~[(~"",~"")], Some(~""));
|
||||
~[(~"",~"")], Some(~""))
|
||||
.expect(format!("failed to exec `{}`", config.adb_path));
|
||||
|
||||
if config.verbose {
|
||||
println!("push ({}) {} {} {}",
|
||||
|
@ -40,15 +40,25 @@ fn run_ar(sess: Session, args: &str, cwd: Option<&Path>,
|
||||
Some(p) => { debug!("inside {}", p.display()); }
|
||||
None => {}
|
||||
}
|
||||
let o = Process::new(ar, args.as_slice(), opts).finish_with_output();
|
||||
if !o.status.success() {
|
||||
sess.err(format!("{} {} failed with: {}", ar, args.connect(" "),
|
||||
o.status));
|
||||
sess.note(format!("stdout ---\n{}", str::from_utf8(o.output)));
|
||||
sess.note(format!("stderr ---\n{}", str::from_utf8(o.error)));
|
||||
sess.abort_if_errors();
|
||||
let mut opt_prog = Process::new(ar, args.as_slice(), opts);
|
||||
match opt_prog {
|
||||
Some(ref mut prog) => {
|
||||
let o = prog.finish_with_output();
|
||||
if !o.status.success() {
|
||||
sess.err(format!("{} {} failed with: {}", ar, args.connect(" "),
|
||||
o.status));
|
||||
sess.note(format!("stdout ---\n{}", str::from_utf8(o.output)));
|
||||
sess.note(format!("stderr ---\n{}", str::from_utf8(o.error)));
|
||||
sess.abort_if_errors();
|
||||
}
|
||||
o
|
||||
},
|
||||
None => {
|
||||
sess.err(format!("could not exec `{}`", ar));
|
||||
sess.abort_if_errors();
|
||||
fail!("rustc::back::archive::run_ar() should not reach this point");
|
||||
}
|
||||
}
|
||||
o
|
||||
}
|
||||
|
||||
impl Archive {
|
||||
|
@ -310,13 +310,19 @@ pub mod write {
|
||||
assembly.as_str().unwrap().to_owned()];
|
||||
|
||||
debug!("{} '{}'", cc, args.connect("' '"));
|
||||
let prog = run::process_output(cc, args);
|
||||
|
||||
if !prog.status.success() {
|
||||
sess.err(format!("linking with `{}` failed: {}", cc, prog.status));
|
||||
sess.note(format!("{} arguments: '{}'", cc, args.connect("' '")));
|
||||
sess.note(str::from_utf8_owned(prog.error + prog.output));
|
||||
sess.abort_if_errors();
|
||||
match run::process_output(cc, args) {
|
||||
Some(prog) => {
|
||||
if !prog.status.success() {
|
||||
sess.err(format!("linking with `{}` failed: {}", cc, prog.status));
|
||||
sess.note(format!("{} arguments: '{}'", cc, args.connect("' '")));
|
||||
sess.note(str::from_utf8_owned(prog.error + prog.output));
|
||||
sess.abort_if_errors();
|
||||
}
|
||||
},
|
||||
None => {
|
||||
sess.err(format!("could not exec `{}`", cc));
|
||||
sess.abort_if_errors();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -949,14 +955,22 @@ fn link_natively(sess: Session, dylib: bool, obj_filename: &Path,
|
||||
|
||||
// Invoke the system linker
|
||||
debug!("{} {}", cc_prog, cc_args.connect(" "));
|
||||
let prog = time(sess.time_passes(), "running linker", (), |()|
|
||||
run::process_output(cc_prog, cc_args));
|
||||
let opt_prog = time(sess.time_passes(), "running linker", (), |()|
|
||||
run::process_output(cc_prog, cc_args));
|
||||
|
||||
if !prog.status.success() {
|
||||
sess.err(format!("linking with `{}` failed: {}", cc_prog, prog.status));
|
||||
sess.note(format!("{} arguments: '{}'", cc_prog, cc_args.connect("' '")));
|
||||
sess.note(str::from_utf8_owned(prog.error + prog.output));
|
||||
sess.abort_if_errors();
|
||||
match opt_prog {
|
||||
Some(prog) => {
|
||||
if !prog.status.success() {
|
||||
sess.err(format!("linking with `{}` failed: {}", cc_prog, prog.status));
|
||||
sess.note(format!("{} arguments: '{}'", cc_prog, cc_args.connect("' '")));
|
||||
sess.note(str::from_utf8_owned(prog.error + prog.output));
|
||||
sess.abort_if_errors();
|
||||
}
|
||||
},
|
||||
None => {
|
||||
sess.err(format!("could not exec `{}`", cc_prog));
|
||||
sess.abort_if_errors();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -142,14 +142,14 @@ pub fn install_pkg(cx: &BuildContext,
|
||||
/// Builds an arbitrary library whose short name is `output`,
|
||||
/// by invoking `tool` with arguments `args` plus "-o %s", where %s
|
||||
/// is the platform-specific library name for `output`.
|
||||
/// Returns that platform-specific name.
|
||||
/// Returns that platform-specific name, or None if `tool` could not be started.
|
||||
pub fn build_library_in_workspace(exec: &mut workcache::Exec,
|
||||
context: &mut Context,
|
||||
package_name: &str,
|
||||
tool: &str,
|
||||
flags: &[~str],
|
||||
paths: &[~str],
|
||||
output: &str) -> ~str {
|
||||
output: &str) -> Option<~str> {
|
||||
use command_failed = conditions::command_failed::cond;
|
||||
|
||||
let workspace = my_workspace(context, package_name);
|
||||
@ -169,16 +169,20 @@ pub fn build_library_in_workspace(exec: &mut workcache::Exec,
|
||||
|
||||
let all_args = flags + absolute_paths + cc_args +
|
||||
~[~"-o", out_name.as_str().unwrap().to_owned()];
|
||||
let exit_process = run::process_status(tool, all_args);
|
||||
if exit_process.success() {
|
||||
let out_name_str = out_name.as_str().unwrap().to_owned();
|
||||
exec.discover_output("binary",
|
||||
out_name_str,
|
||||
digest_only_date(&out_name));
|
||||
context.add_library_path(out_name.dir_path());
|
||||
out_name_str
|
||||
} else {
|
||||
command_failed.raise((tool.to_owned(), all_args, exit_process))
|
||||
match run::process_status(tool, all_args) {
|
||||
Some(exit_process) => {
|
||||
if exit_process.success() {
|
||||
let out_name_str = out_name.as_str().unwrap().to_owned();
|
||||
exec.discover_output("binary",
|
||||
out_name_str,
|
||||
digest_only_date(&out_name));
|
||||
context.add_library_path(out_name.dir_path());
|
||||
Some(out_name_str)
|
||||
} else {
|
||||
Some(command_failed.raise((tool.to_owned(), all_args, exit_process)))
|
||||
}
|
||||
},
|
||||
None => None
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,29 +166,47 @@ impl<'a> PkgScript<'a> {
|
||||
/// Run the contents of this package script, where <what>
|
||||
/// is the command to pass to it (e.g., "build", "clean", "install")
|
||||
/// Returns a pair of an exit code and list of configs (obtained by
|
||||
/// calling the package script's configs() function if it exists
|
||||
fn run_custom(exe: &Path, sysroot: &Path) -> (~[~str], process::ProcessExit) {
|
||||
/// calling the package script's configs() function if it exists, or
|
||||
/// None if `exe` could not be started.
|
||||
fn run_custom(exe: &Path, sysroot: &Path) -> Option<(~[~str], process::ProcessExit)> {
|
||||
debug!("Running program: {} {} {}", exe.as_str().unwrap().to_owned(),
|
||||
sysroot.display(), "install");
|
||||
// FIXME #7401 should support commands besides `install`
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
let status = run::process_status(exe.as_str().unwrap(),
|
||||
[sysroot.as_str().unwrap().to_owned(), ~"install"]);
|
||||
if !status.success() {
|
||||
debug!("run_custom: first pkg command failed with {:?}", status);
|
||||
(~[], status)
|
||||
}
|
||||
else {
|
||||
debug!("Running program (configs): {} {} {}",
|
||||
exe.display(), sysroot.display(), "configs");
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
let output = run::process_output(exe.as_str().unwrap(),
|
||||
[sysroot.as_str().unwrap().to_owned(), ~"configs"]);
|
||||
debug!("run_custom: second pkg command did {:?}", output.status);
|
||||
// Run the configs() function to get the configs
|
||||
let cfgs = str::from_utf8(output.output).words()
|
||||
.map(|w| w.to_owned()).collect();
|
||||
(cfgs, output.status)
|
||||
let opt_status = run::process_status(exe.as_str().unwrap(),
|
||||
[sysroot.as_str().unwrap().to_owned(), ~"install"]);
|
||||
match opt_status {
|
||||
Some(status) => {
|
||||
if !status.success() {
|
||||
debug!("run_custom: first pkg command failed with {:?}", status);
|
||||
Some((~[], status))
|
||||
}
|
||||
else {
|
||||
debug!("Running program (configs): {} {} {}",
|
||||
exe.display(), sysroot.display(), "configs");
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
let opt_output = run::process_output(exe.as_str().unwrap(),
|
||||
[sysroot.as_str().unwrap().to_owned(),
|
||||
~"configs"]);
|
||||
match opt_output {
|
||||
Some(output) => {
|
||||
debug!("run_custom: second pkg command did {:?}", output.status);
|
||||
// Run the configs() function to get the configs
|
||||
let cfgs = str::from_utf8(output.output).words()
|
||||
.map(|w| w.to_owned()).collect();
|
||||
Some((cfgs, output.status))
|
||||
},
|
||||
None => {
|
||||
debug!("run_custom: second pkg command failed to start");
|
||||
Some((~[], status))
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
debug!("run_custom: first pkg command failed to start");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -481,14 +499,20 @@ impl CtxMethods for BuildContext {
|
||||
})
|
||||
});
|
||||
// We always *run* the package script
|
||||
let (cfgs, hook_result) = PkgScript::run_custom(&Path::new(pkg_exe), &sysroot);
|
||||
debug!("Command return code = {:?}", hook_result);
|
||||
if !hook_result.success() {
|
||||
fail!("Error running custom build command")
|
||||
match PkgScript::run_custom(&Path::new(pkg_exe), &sysroot) {
|
||||
Some((cfgs, hook_result)) => {
|
||||
debug!("Command return code = {:?}", hook_result);
|
||||
if !hook_result.success() {
|
||||
fail!("Error running custom build command")
|
||||
}
|
||||
custom = true;
|
||||
// otherwise, the package script succeeded
|
||||
cfgs
|
||||
},
|
||||
None => {
|
||||
fail!("Error starting custom build command")
|
||||
}
|
||||
}
|
||||
custom = true;
|
||||
// otherwise, the package script succeeded
|
||||
cfgs
|
||||
}
|
||||
(Some(_), Inferred) => {
|
||||
debug!("There is a package script, but we're ignoring it");
|
||||
@ -693,9 +717,14 @@ impl CtxMethods for BuildContext {
|
||||
Some(test_exec) => {
|
||||
debug!("test: test_exec = {}", test_exec.display());
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
let status = run::process_status(test_exec.as_str().unwrap(), [~"--test"]);
|
||||
if !status.success() {
|
||||
fail!("Some tests failed");
|
||||
let opt_status = run::process_status(test_exec.as_str().unwrap(), [~"--test"]);
|
||||
match opt_status {
|
||||
Some(status) => {
|
||||
if !status.success() {
|
||||
fail!("Some tests failed");
|
||||
}
|
||||
},
|
||||
None => fail!("Could not exec `{}`", test_exec.display())
|
||||
}
|
||||
}
|
||||
None => {
|
||||
|
@ -33,15 +33,16 @@ pub fn safe_git_clone(source: &Path, v: &Version, target: &Path) -> CloneResult
|
||||
if !target.exists() {
|
||||
debug!("Running: git clone {} {}", source.display(), target.display());
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
let outp = run::process_output("git", [~"clone",
|
||||
source.as_str().unwrap().to_owned(),
|
||||
target.as_str().unwrap().to_owned()]);
|
||||
let opt_outp = run::process_output("git", [~"clone",
|
||||
source.as_str().unwrap().to_owned(),
|
||||
target.as_str().unwrap().to_owned()]);
|
||||
let outp = opt_outp.expect("Failed to exec `git`");
|
||||
if !outp.status.success() {
|
||||
println(str::from_utf8_owned(outp.output.clone()));
|
||||
println(str::from_utf8_owned(outp.error));
|
||||
return DirToUse(target.clone());
|
||||
}
|
||||
else {
|
||||
else {
|
||||
match v {
|
||||
&ExactRevision(ref s) => {
|
||||
let git_dir = target.join(".git");
|
||||
@ -51,7 +52,7 @@ pub fn safe_git_clone(source: &Path, v: &Version, target: &Path) -> CloneResult
|
||||
let outp = run::process_output("git",
|
||||
[format!("--work-tree={}", target.as_str().unwrap().to_owned()),
|
||||
format!("--git-dir={}", git_dir.as_str().unwrap().to_owned()),
|
||||
~"checkout", format!("{}", *s)]);
|
||||
~"checkout", format!("{}", *s)]).expect("Failed to exec `git`");
|
||||
if !outp.status.success() {
|
||||
println(str::from_utf8_owned(outp.output.clone()));
|
||||
println(str::from_utf8_owned(outp.error));
|
||||
@ -72,7 +73,8 @@ pub fn safe_git_clone(source: &Path, v: &Version, target: &Path) -> CloneResult
|
||||
let args = [format!("--work-tree={}", target.as_str().unwrap().to_owned()),
|
||||
format!("--git-dir={}", git_dir.as_str().unwrap().to_owned()),
|
||||
~"pull", ~"--no-edit", source.as_str().unwrap().to_owned()];
|
||||
let outp = run::process_output("git", args);
|
||||
let opt_outp = run::process_output("git", args);
|
||||
let outp = opt_outp.expect("Failed to exec `git`");
|
||||
assert!(outp.status.success());
|
||||
}
|
||||
CheckedOutSources
|
||||
@ -108,8 +110,9 @@ pub fn git_clone_url(source: &str, target: &Path, v: &Version) {
|
||||
use conditions::git_checkout_failed::cond;
|
||||
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
let outp = run::process_output("git", [~"clone", source.to_owned(),
|
||||
target.as_str().unwrap().to_owned()]);
|
||||
let opt_outp = run::process_output("git", [~"clone", source.to_owned(),
|
||||
target.as_str().unwrap().to_owned()]);
|
||||
let outp = opt_outp.expect("Failed to exec `git`");
|
||||
if !outp.status.success() {
|
||||
debug!("{}", str::from_utf8_owned(outp.output.clone()));
|
||||
debug!("{}", str::from_utf8_owned(outp.error));
|
||||
@ -118,8 +121,9 @@ pub fn git_clone_url(source: &str, target: &Path, v: &Version) {
|
||||
else {
|
||||
match v {
|
||||
&ExactRevision(ref s) | &Tagged(ref s) => {
|
||||
let outp = process_output_in_cwd("git", [~"checkout", s.to_owned()],
|
||||
let opt_outp = process_output_in_cwd("git", [~"checkout", s.to_owned()],
|
||||
target);
|
||||
let outp = opt_outp.expect("Failed to exec `git`");
|
||||
if !outp.status.success() {
|
||||
debug!("{}", str::from_utf8_owned(outp.output.clone()));
|
||||
debug!("{}", str::from_utf8_owned(outp.error));
|
||||
@ -131,10 +135,13 @@ pub fn git_clone_url(source: &str, target: &Path, v: &Version) {
|
||||
}
|
||||
}
|
||||
|
||||
fn process_output_in_cwd(prog: &str, args: &[~str], cwd: &Path) -> ProcessOutput {
|
||||
let mut prog = Process::new(prog, args, ProcessOptions{ dir: Some(cwd)
|
||||
,..ProcessOptions::new()});
|
||||
prog.finish_with_output()
|
||||
fn process_output_in_cwd(prog: &str, args: &[~str], cwd: &Path) -> Option<ProcessOutput> {
|
||||
let mut opt_prog = Process::new(prog, args, ProcessOptions{ dir: Some(cwd)
|
||||
,..ProcessOptions::new()});
|
||||
match opt_prog {
|
||||
Some(ref mut prog) => Some(prog.finish_with_output()),
|
||||
None => None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_git_dir(p: &Path) -> bool {
|
||||
|
@ -148,7 +148,7 @@ fn run_git(args: &[~str], env: Option<~[(~str, ~str)]>, cwd: &Path, err_msg: &st
|
||||
in_fd: None,
|
||||
out_fd: None,
|
||||
err_fd: None
|
||||
});
|
||||
}).expect("failed to exec `git`");
|
||||
let rslt = prog.finish_with_output();
|
||||
if !rslt.status.success() {
|
||||
fail!("{} [git returned {:?}, output = {}, error = {}]", err_msg,
|
||||
@ -285,7 +285,7 @@ fn command_line_test_with_env(args: &[~str], cwd: &Path, env: Option<~[(~str, ~s
|
||||
in_fd: None,
|
||||
out_fd: None,
|
||||
err_fd: None
|
||||
});
|
||||
}).expect(format!("failed to exec `{}`", cmd));
|
||||
let output = prog.finish_with_output();
|
||||
debug!("Output from command {} with args {:?} was {} \\{{}\\}[{:?}]",
|
||||
cmd, args, str::from_utf8(output.output),
|
||||
@ -503,7 +503,8 @@ fn touch_source_file(workspace: &Path, pkgid: &PkgId) {
|
||||
// n.b. Bumps time up by 2 seconds to get around granularity issues
|
||||
if !run::process_output("touch", [~"--date",
|
||||
~"+2 seconds",
|
||||
p.as_str().unwrap().to_owned()]).status.success() {
|
||||
p.as_str().unwrap().to_owned()])
|
||||
.expect("failed to exec `touch`").status.success() {
|
||||
let _ = cond.raise((pkg_src_dir.clone(), ~"Bad path"));
|
||||
}
|
||||
}
|
||||
@ -521,7 +522,8 @@ fn touch_source_file(workspace: &Path, pkgid: &PkgId) {
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
// n.b. Bumps time up by 2 seconds to get around granularity issues
|
||||
if !run::process_output("touch", [~"-A02",
|
||||
p.as_str().unwrap().to_owned()]).status.success() {
|
||||
p.as_str().unwrap().to_owned()])
|
||||
.expect("failed to exec `touch`").status.success() {
|
||||
let _ = cond.raise((pkg_src_dir.clone(), ~"Bad path"));
|
||||
}
|
||||
}
|
||||
@ -1276,7 +1278,7 @@ fn test_extern_mod() {
|
||||
in_fd: None,
|
||||
out_fd: None,
|
||||
err_fd: None
|
||||
});
|
||||
}).expect(format!("failed to exec `{}`", rustc.as_str().unwrap()));
|
||||
let outp = prog.finish_with_output();
|
||||
if !outp.status.success() {
|
||||
fail!("output was {}, error was {}",
|
||||
@ -1331,7 +1333,7 @@ fn test_extern_mod_simpler() {
|
||||
in_fd: None,
|
||||
out_fd: None,
|
||||
err_fd: None
|
||||
});
|
||||
}).expect(format!("failed to exec `{}`", rustc.as_str().unwrap()));
|
||||
let outp = prog.finish_with_output();
|
||||
if !outp.status.success() {
|
||||
fail!("output was {}, error was {}",
|
||||
|
@ -104,8 +104,9 @@ pub fn try_getting_local_version(local_path: &Path) -> Option<Version> {
|
||||
continue;
|
||||
}
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
let outp = run::process_output("git",
|
||||
let opt_outp = run::process_output("git",
|
||||
["--git-dir=" + git_dir.as_str().unwrap(), ~"tag", ~"-l"]);
|
||||
let outp = opt_outp.expect("Failed to exec `git`");
|
||||
|
||||
debug!("git --git-dir={} tag -l ~~~> {:?}", git_dir.display(), outp.status);
|
||||
|
||||
@ -140,9 +141,10 @@ pub fn try_getting_version(remote_path: &Path) -> Option<Version> {
|
||||
remote_path.display(),
|
||||
tmp_dir.display());
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
let outp = run::process_output("git", [~"clone", format!("https://{}",
|
||||
remote_path.as_str().unwrap()),
|
||||
tmp_dir.as_str().unwrap().to_owned()]);
|
||||
let opt_outp = run::process_output("git", [~"clone", format!("https://{}",
|
||||
remote_path.as_str().unwrap()),
|
||||
tmp_dir.as_str().unwrap().to_owned()]);
|
||||
let outp = opt_outp.expect("Failed to exec `git`");
|
||||
if outp.status.success() {
|
||||
debug!("Cloned it... ( {}, {} )",
|
||||
str::from_utf8(outp.output),
|
||||
@ -152,9 +154,10 @@ pub fn try_getting_version(remote_path: &Path) -> Option<Version> {
|
||||
debug!("(getting version, now getting tags) executing \\{git --git-dir={} tag -l\\}",
|
||||
git_dir.display());
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
let outp = run::process_output("git",
|
||||
["--git-dir=" + git_dir.as_str().unwrap(),
|
||||
~"tag", ~"-l"]);
|
||||
let opt_outp = run::process_output("git",
|
||||
["--git-dir=" + git_dir.as_str().unwrap(),
|
||||
~"tag", ~"-l"]);
|
||||
let outp = opt_outp.expect("Failed to exec `git`");
|
||||
let output_text = str::from_utf8(outp.output);
|
||||
debug!("Full output: ( {} ) [{:?}]", output_text, outp.status);
|
||||
for l in output_text.lines() {
|
||||
|
@ -119,7 +119,7 @@ impl Process {
|
||||
* * options - Options to configure the environment of the process,
|
||||
* the working directory and the standard IO streams.
|
||||
*/
|
||||
pub fn new(prog: &str, args: &[~str], options: ProcessOptions) -> Process {
|
||||
pub fn new(prog: &str, args: &[~str], options: ProcessOptions) -> Option<Process> {
|
||||
let ProcessOptions { env, dir, in_fd, out_fd, err_fd } = options;
|
||||
let env = env.as_ref().map(|a| a.as_slice());
|
||||
let cwd = dir.as_ref().map(|a| a.as_str().unwrap());
|
||||
@ -138,8 +138,10 @@ impl Process {
|
||||
cwd: cwd,
|
||||
io: rtio,
|
||||
};
|
||||
let inner = process::Process::new(rtconfig).unwrap();
|
||||
Process { inner: inner }
|
||||
match process::Process::new(rtconfig) {
|
||||
Some(inner) => Some(Process { inner: inner }),
|
||||
None => None
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the unique id of the process
|
||||
@ -290,17 +292,20 @@ impl Process {
|
||||
*
|
||||
* # Return value
|
||||
*
|
||||
* The process's exit code
|
||||
* The process's exit code, or None if the child process could not be started
|
||||
*/
|
||||
pub fn process_status(prog: &str, args: &[~str]) -> ProcessExit {
|
||||
let mut prog = Process::new(prog, args, ProcessOptions {
|
||||
pub fn process_status(prog: &str, args: &[~str]) -> Option<ProcessExit> {
|
||||
let mut opt_prog = Process::new(prog, args, ProcessOptions {
|
||||
env: None,
|
||||
dir: None,
|
||||
in_fd: Some(unsafe { libc::dup(libc::STDIN_FILENO) }),
|
||||
out_fd: Some(unsafe { libc::dup(libc::STDOUT_FILENO) }),
|
||||
err_fd: Some(unsafe { libc::dup(libc::STDERR_FILENO) })
|
||||
});
|
||||
prog.finish()
|
||||
match opt_prog {
|
||||
Some(ref mut prog) => Some(prog.finish()),
|
||||
None => None
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -313,11 +318,15 @@ pub fn process_status(prog: &str, args: &[~str]) -> ProcessExit {
|
||||
*
|
||||
* # Return value
|
||||
*
|
||||
* The process's stdout/stderr output and exit code.
|
||||
* The process's stdout/stderr output and exit code, or None if the child process could not be
|
||||
* started.
|
||||
*/
|
||||
pub fn process_output(prog: &str, args: &[~str]) -> ProcessOutput {
|
||||
let mut prog = Process::new(prog, args, ProcessOptions::new());
|
||||
prog.finish_with_output()
|
||||
pub fn process_output(prog: &str, args: &[~str]) -> Option<ProcessOutput> {
|
||||
let mut opt_prog = Process::new(prog, args, ProcessOptions::new());
|
||||
match opt_prog {
|
||||
Some(ref mut prog) => Some(prog.finish_with_output()),
|
||||
None => None
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -331,24 +340,36 @@ mod tests {
|
||||
use task::spawn;
|
||||
use unstable::running_on_valgrind;
|
||||
use io::native::file;
|
||||
use io::{Writer, Reader};
|
||||
use io::{Writer, Reader, io_error};
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_os="android"))] // FIXME(#10380)
|
||||
fn test_process_status() {
|
||||
let mut status = run::process_status("false", []);
|
||||
let mut status = run::process_status("false", []).expect("failed to exec `false`");
|
||||
assert!(status.matches_exit_status(1));
|
||||
|
||||
status = run::process_status("true", []);
|
||||
status = run::process_status("true", []).expect("failed to exec `true`");
|
||||
assert!(status.success());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_process_output_fail_to_start() {
|
||||
let mut trapped_io_error = false;
|
||||
let opt_outp = io_error::cond.trap(|_| {
|
||||
trapped_io_error = true;
|
||||
}).inside(|| -> Option<run::ProcessOutput> {
|
||||
run::process_output("no-binary-by-this-name-should-exist", [])
|
||||
});
|
||||
assert!(trapped_io_error);
|
||||
assert!(opt_outp.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_os="android"))] // FIXME(#10380)
|
||||
fn test_process_output_output() {
|
||||
|
||||
let run::ProcessOutput {status, output, error}
|
||||
= run::process_output("echo", [~"hello"]);
|
||||
= run::process_output("echo", [~"hello"]).expect("failed to exec `echo`");
|
||||
let output_str = str::from_utf8_owned(output);
|
||||
|
||||
assert!(status.success());
|
||||
@ -364,7 +385,7 @@ mod tests {
|
||||
fn test_process_output_error() {
|
||||
|
||||
let run::ProcessOutput {status, output, error}
|
||||
= run::process_output("mkdir", [~"."]);
|
||||
= run::process_output("mkdir", [~"."]).expect("failed to exec `mkdir`");
|
||||
|
||||
assert!(status.matches_exit_status(1));
|
||||
assert_eq!(output, ~[]);
|
||||
@ -385,7 +406,7 @@ mod tests {
|
||||
in_fd: Some(pipe_in.input),
|
||||
out_fd: Some(pipe_out.out),
|
||||
err_fd: Some(pipe_err.out)
|
||||
});
|
||||
}).expect("failed to exec `cat`");
|
||||
|
||||
os::close(pipe_in.input);
|
||||
os::close(pipe_out.out);
|
||||
@ -422,14 +443,16 @@ mod tests {
|
||||
#[test]
|
||||
#[cfg(not(target_os="android"))] // FIXME(#10380)
|
||||
fn test_finish_once() {
|
||||
let mut prog = run::Process::new("false", [], run::ProcessOptions::new());
|
||||
let mut prog = run::Process::new("false", [], run::ProcessOptions::new())
|
||||
.expect("failed to exec `false`");
|
||||
assert!(prog.finish().matches_exit_status(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_os="android"))] // FIXME(#10380)
|
||||
fn test_finish_twice() {
|
||||
let mut prog = run::Process::new("false", [], run::ProcessOptions::new());
|
||||
let mut prog = run::Process::new("false", [], run::ProcessOptions::new())
|
||||
.expect("failed to exec `false`");
|
||||
assert!(prog.finish().matches_exit_status(1));
|
||||
assert!(prog.finish().matches_exit_status(1));
|
||||
}
|
||||
@ -438,7 +461,8 @@ mod tests {
|
||||
#[cfg(not(target_os="android"))] // FIXME(#10380)
|
||||
fn test_finish_with_output_once() {
|
||||
|
||||
let mut prog = run::Process::new("echo", [~"hello"], run::ProcessOptions::new());
|
||||
let mut prog = run::Process::new("echo", [~"hello"], run::ProcessOptions::new())
|
||||
.expect("failed to exec `echo`");
|
||||
let run::ProcessOutput {status, output, error}
|
||||
= prog.finish_with_output();
|
||||
let output_str = str::from_utf8_owned(output);
|
||||
@ -455,7 +479,8 @@ mod tests {
|
||||
#[cfg(not(target_os="android"))] // FIXME(#10380)
|
||||
fn test_finish_with_output_twice() {
|
||||
|
||||
let mut prog = run::Process::new("echo", [~"hello"], run::ProcessOptions::new());
|
||||
let mut prog = run::Process::new("echo", [~"hello"], run::ProcessOptions::new())
|
||||
.expect("failed to exec `echo`");
|
||||
let run::ProcessOutput {status, output, error}
|
||||
= prog.finish_with_output();
|
||||
|
||||
@ -484,14 +509,14 @@ mod tests {
|
||||
run::Process::new("pwd", [], run::ProcessOptions {
|
||||
dir: dir,
|
||||
.. run::ProcessOptions::new()
|
||||
})
|
||||
}).expect("failed to exec `pwd`")
|
||||
}
|
||||
#[cfg(unix,target_os="android")]
|
||||
fn run_pwd(dir: Option<&Path>) -> run::Process {
|
||||
run::Process::new("/system/bin/sh", [~"-c",~"pwd"], run::ProcessOptions {
|
||||
dir: dir,
|
||||
.. run::ProcessOptions::new()
|
||||
})
|
||||
}).expect("failed to exec `/system/bin/sh`")
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
@ -499,7 +524,7 @@ mod tests {
|
||||
run::Process::new("cmd", [~"/c", ~"cd"], run::ProcessOptions {
|
||||
dir: dir,
|
||||
.. run::ProcessOptions::new()
|
||||
})
|
||||
}).expect("failed to run `cmd`")
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -539,14 +564,14 @@ mod tests {
|
||||
run::Process::new("env", [], run::ProcessOptions {
|
||||
env: env,
|
||||
.. run::ProcessOptions::new()
|
||||
})
|
||||
}).expect("failed to exec `env`")
|
||||
}
|
||||
#[cfg(unix,target_os="android")]
|
||||
fn run_env(env: Option<~[(~str, ~str)]>) -> run::Process {
|
||||
run::Process::new("/system/bin/sh", [~"-c",~"set"], run::ProcessOptions {
|
||||
env: env,
|
||||
.. run::ProcessOptions::new()
|
||||
})
|
||||
}).expect("failed to exec `/system/bin/sh`")
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
@ -554,7 +579,7 @@ mod tests {
|
||||
run::Process::new("cmd", [~"/c", ~"set"], run::ProcessOptions {
|
||||
env: env,
|
||||
.. run::ProcessOptions::new()
|
||||
})
|
||||
}).expect("failed to run `cmd`")
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -27,7 +27,8 @@ fn test_destroy_once() {
|
||||
#[cfg(target_os="android")]
|
||||
static PROG: &'static str = "ls"; // android don't have echo binary
|
||||
|
||||
let mut p = run::Process::new(PROG, [], run::ProcessOptions::new());
|
||||
let mut p = run::Process::new(PROG, [], run::ProcessOptions::new())
|
||||
.expect(format!("failed to exec `{}`", PROG));
|
||||
p.destroy(); // this shouldn't crash (and nor should the destructor)
|
||||
}
|
||||
|
||||
@ -38,7 +39,8 @@ fn test_destroy_twice() {
|
||||
#[cfg(target_os="android")]
|
||||
static PROG: &'static str = "ls"; // android don't have echo binary
|
||||
|
||||
let mut p = run::Process::new(PROG, [], run::ProcessOptions::new());
|
||||
let mut p = run::Process::new(PROG, [], run::ProcessOptions::new())
|
||||
.expect(format!("failed to exec `{}`", PROG));
|
||||
p.destroy(); // this shouldnt crash...
|
||||
io::io_error::cond.trap(|_| {}).inside(|| {
|
||||
p.destroy(); // ...and nor should this (and nor should the destructor)
|
||||
@ -58,13 +60,15 @@ fn test_destroy_actually_kills(force: bool) {
|
||||
|
||||
#[cfg(unix,not(target_os="android"))]
|
||||
fn process_exists(pid: libc::pid_t) -> bool {
|
||||
let run::ProcessOutput {output, ..} = run::process_output("ps", [~"-p", pid.to_str()]);
|
||||
let run::ProcessOutput {output, ..} = run::process_output("ps", [~"-p", pid.to_str()])
|
||||
.expect("failed to exec `ps`");
|
||||
str::from_utf8_owned(output).contains(pid.to_str())
|
||||
}
|
||||
|
||||
#[cfg(unix,target_os="android")]
|
||||
fn process_exists(pid: libc::pid_t) -> bool {
|
||||
let run::ProcessOutput {output, ..} = run::process_output("/system/bin/ps", [pid.to_str()]);
|
||||
let run::ProcessOutput {output, ..} = run::process_output("/system/bin/ps", [pid.to_str()])
|
||||
.expect("failed to exec `/system/bin/ps`");
|
||||
str::from_utf8_owned(output).contains(~"root")
|
||||
}
|
||||
|
||||
@ -88,7 +92,8 @@ fn test_destroy_actually_kills(force: bool) {
|
||||
}
|
||||
|
||||
// this process will stay alive indefinitely trying to read from stdin
|
||||
let mut p = run::Process::new(BLOCK_COMMAND, [], run::ProcessOptions::new());
|
||||
let mut p = run::Process::new(BLOCK_COMMAND, [], run::ProcessOptions::new())
|
||||
.expect(format!("failed to exec `{}`", BLOCK_COMMAND));
|
||||
|
||||
assert!(process_exists(p.get_id()));
|
||||
|
||||
|
@ -19,7 +19,8 @@ fn main() {
|
||||
// Raise a segfault.
|
||||
unsafe { *(0 as *mut int) = 0; }
|
||||
} else {
|
||||
let status = run::process_status(args[0], [~"signal"]);
|
||||
let status = run::process_status(args[0], [~"signal"])
|
||||
.expect("failed to exec `signal`");
|
||||
// Windows does not have signal, so we get exit status 0xC0000028 (STATUS_BAD_STACK).
|
||||
match status {
|
||||
process::ExitSignal(_) if cfg!(unix) => {},
|
||||
|
Loading…
Reference in New Issue
Block a user