From e34e072d1777ad2064ed9b70ccdbe29b4f100f9b Mon Sep 17 00:00:00 2001 From: Zack Corr Date: Wed, 23 Jan 2013 12:41:11 +1000 Subject: [PATCH] rustpkg: Add do command and get cmd listeners working correctly --- src/librustpkg/api.rs | 29 +++++++++++++------ src/librustpkg/rustpkg.rc | 47 ++++++++++++++++++++++++++++-- src/librustpkg/usage.rs | 7 +++++ src/librustpkg/util.rs | 61 ++++++++++++++++++++++++++++++--------- 4 files changed, 119 insertions(+), 25 deletions(-) diff --git a/src/librustpkg/api.rs b/src/librustpkg/api.rs index d431db27e68..349bbd0f408 100644 --- a/src/librustpkg/api.rs +++ b/src/librustpkg/api.rs @@ -19,21 +19,29 @@ pub struct Crate { } pub struct Listener { - cmd: ~str, + cmds: ~[~str], cb: fn~() } pub fn run(listeners: ~[Listener]) { - io::println(src_dir().to_str()); - io::println(work_dir().to_str()); - - let cmd = os::args()[1]; + let rcmd = os::args()[2]; + let mut found = false; for listeners.each |listener| { - if listener.cmd == cmd { - (listener.cb)(); + for listener.cmds.each |&cmd| { + if cmd == rcmd { + (listener.cb)(); + + found = true; + + break; + } } } + + if !found { + os::set_exit_status(1); + } } pub impl Crate { @@ -108,19 +116,22 @@ pub fn build(crates: ~[Crate]) -> bool { let dir = src_dir(); let work_dir = work_dir(); let mut success = true; + let sysroot = Path(os::args()[1]); for crates.each |&crate| { let path = &dir.push_rel(&Path(crate.file)).normalize(); note(fmt!("compiling %s", path.to_str())); - success = compile_crate(path, &work_dir, crate.flags, crate.cfgs, + success = compile_crate(Some(sysroot), path, &work_dir, crate.flags, crate.cfgs, false, false); if !success { break; } } - os::set_exit_status(101); + if !success { + os::set_exit_status(2); + } success } diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index 9d29bf76d6c..76e6b587942 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -30,6 +30,7 @@ use io::{ReaderUtil, WriterUtil}; use std::getopts; use std::net::url; use send_map::linear::LinearMap; +use rustc::metadata::filesearch; use rustc::driver::{driver, session}; use syntax::{ast, attr, codemap, diagnostic, parse, visit}; use semver::Version; @@ -184,7 +185,11 @@ impl PackageScript { // the build API. for crate.node.module.items.each |i| { match i.node { - ast::item_fn(_, _, _, _) => custom = true, + ast::item_fn(_, _, _, _) => { + custom = true; + + break; + } _ => {} } } @@ -228,10 +233,11 @@ impl PackageScript { let outputs = driver::build_output_filenames(input, &Some(work_dir), &None, sess); let exe = work_dir.push(~"package" + util::exe_suffix()); + let root = filesearch::get_rustpkg_sysroot().get().pop().pop(); driver::compile_rest(sess, cfg, driver::cu_parse, Some(outputs), Some(crate)); - run::run_program(exe.to_str(), ~[cmd]) + run::run_program(exe.to_str(), ~[root.to_str(), cmd]) } fn hash() -> ~str { @@ -282,6 +288,13 @@ impl Ctx { ~"clean" => { self.clean(); } + ~"do" => { + if args.len() < 1 { + return usage::do_cmd(); + } + + self.do_cmd(args[0]); + } ~"install" => { self.install(if args.len() >= 1 { Some(args[0]) } else { None }, @@ -322,6 +335,33 @@ impl Ctx { } } + fn do_cmd(cmd: ~str) -> bool { + if cmd == ~"build" { + util::error(~"the build cmd is reserved"); + + return false; + } + + let cwd = &os::getcwd(); + let script = match PackageScript::parse(cwd) { + result::Ok(script) => script, + result::Err(err) => { + util::error(err); + + return false; + } + }; + let status = script.run(cmd); + + if status == 1 { + util::error(~"no fns are listening for that cmd"); + + return false; + } + + status == 0 + } + fn build(dir: &Path, verbose: bool, opt: bool, test: bool) -> Option { let cwd = &os::getcwd(); @@ -399,7 +439,7 @@ impl Ctx { fn compile(crate: &Path, dir: &Path, flags: ~[~str], cfgs: ~[~str], opt: bool, test: bool) -> bool { - util::compile_crate(crate, dir, flags, cfgs, opt, test) + util::compile_crate(None, crate, dir, flags, cfgs, opt, test) } fn clean() -> bool { @@ -759,6 +799,7 @@ pub fn main() { return match cmd { ~"build" => usage::build(), ~"clean" => usage::clean(), + ~"do" => usage::do_cmd(), ~"install" => usage::install(), ~"prefer" => usage::prefer(), ~"test" => usage::test(), diff --git a/src/librustpkg/usage.rs b/src/librustpkg/usage.rs index cad5aa650db..18afcd38bae 100644 --- a/src/librustpkg/usage.rs +++ b/src/librustpkg/usage.rs @@ -39,6 +39,13 @@ Remove all build files in the work cache for the package in the current directory."); } +pub fn do_cmd() { + io::println(~"rustpkg do + +Runs a command in the package script. You can listen to a command +by tagging a function with the attribute `#[pkg_do(cmd)]`."); +} + pub fn install() { io::println(~"rustpkg [options..] install [url] [target] diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index b7d6ad17f05..317a9331675 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -34,8 +34,8 @@ pub fn root() -> Path { } pub fn is_cmd(cmd: ~str) -> bool { - let cmds = &[~"build", ~"clean", ~"install", ~"prefer", ~"test", - ~"uninstall", ~"unprefer"]; + let cmds = &[~"build", ~"clean", ~"do", ~"install", ~"prefer", + ~"test", ~"uninstall", ~"unprefer"]; vec::contains(cmds, &cmd) } @@ -74,6 +74,7 @@ fn mk_rustpkg_use(ctx: @ReadyCtx) -> @ast::view_item { } struct ListenerFn { + cmds: ~[~str], span: codemap::span, path: ~[ast::ident] } @@ -119,8 +120,27 @@ fn fold_item(ctx: @ReadyCtx, &&item: @ast::item, ctx.path.push(item.ident); - if attr::find_attrs_by_name(item.attrs, ~"pkg_do").is_not_empty() { + let attrs = attr::find_attrs_by_name(item.attrs, ~"pkg_do"); + + if attrs.len() > 0 { + let mut cmds = ~[]; + + for attrs.each |attr| { + match attr.node.value.node { + ast::meta_list(_, mis) => { + for mis.each |mi| { + match mi.node { + ast::meta_word(cmd) => cmds.push(cmd), + _ => {} + }; + } + } + _ => cmds.push(~"build") + }; + } + ctx.fns.push(ListenerFn { + cmds: cmds, span: item.span, path: /*bad*/copy ctx.path }); @@ -284,13 +304,26 @@ fn mk_listener_vec(ctx: @ReadyCtx) -> @ast::expr { fn mk_listener_rec(ctx: @ReadyCtx, listener: ListenerFn) -> @ast::expr { let span = listener.span; let path = /*bad*/copy listener.path; - let cmd_lit = no_span(ast::lit_str(@path_name_i(path, - ctx.sess.parse_sess.interner))); + let descs = do listener.cmds.map |&cmd| { + let inner = @{ + id: ctx.sess.next_node_id(), + callee_id: ctx.sess.next_node_id(), + node: ast::expr_lit(@no_span(ast::lit_str(@cmd))), + span: span + }; + + @{ + id: ctx.sess.next_node_id(), + callee_id: ctx.sess.next_node_id(), + node: ast::expr_vstore(inner, ast::expr_vstore_uniq), + span: dummy_sp() + } + }; let cmd_expr_inner = @{ id: ctx.sess.next_node_id(), callee_id: ctx.sess.next_node_id(), - node: ast::expr_lit(@cmd_lit), - span: span + node: ast::expr_vec(descs, ast::m_imm), + span: dummy_sp() }; let cmd_expr = { id: ctx.sess.next_node_id(), @@ -300,7 +333,7 @@ fn mk_listener_rec(ctx: @ReadyCtx, listener: ListenerFn) -> @ast::expr { }; let cmd_field = no_span(ast::field_ { mutbl: ast::m_imm, - ident: ctx.sess.ident_of(~"cmd"), + ident: ctx.sess.ident_of(~"cmds"), expr: @cmd_expr, }); @@ -827,7 +860,7 @@ pub fn remove_pkg(pkg: &Package) -> bool { true } -pub fn compile_input(input: driver::input, dir: &Path, +pub fn compile_input(sysroot: Option, input: driver::input, dir: &Path, flags: ~[~str], cfgs: ~[~str], opt: bool, test: bool) -> bool { let lib_dir = dir.push(~"lib"); let bin_dir = dir.push(~"bin"); @@ -838,6 +871,7 @@ pub fn compile_input(input: driver::input, dir: &Path, crate_type: session::unknown_crate, optimize: if opt { session::Aggressive } else { session::No }, test: test, + maybe_sysroot: sysroot, .. *session::basic_options() }; let sess = driver::build_session(options, diagnostic::emit); @@ -966,14 +1000,14 @@ pub fn exe_suffix() -> ~str { ~".exe" } #[cfg(target_os = "macos")] pub fn exe_suffix() -> ~str { ~"" } -pub fn compile_crate(crate: &Path, dir: &Path, flags: ~[~str], +pub fn compile_crate(sysroot: Option, crate: &Path, dir: &Path, flags: ~[~str], cfgs: ~[~str], opt: bool, test: bool) -> bool { - compile_input(driver::file_input(*crate), dir, flags, cfgs, opt, test) + compile_input(sysroot, driver::file_input(*crate), dir, flags, cfgs, opt, test) } -pub fn compile_str(code: ~str, dir: &Path, flags: ~[~str], +pub fn compile_str(sysroot: Option, code: ~str, dir: &Path, flags: ~[~str], cfgs: ~[~str], opt: bool, test: bool) -> bool { - compile_input(driver::str_input(code), dir, flags, cfgs, opt, test) + compile_input(sysroot, driver::str_input(code), dir, flags, cfgs, opt, test) } #[cfg(windows)] @@ -1002,6 +1036,7 @@ pub fn link_exe(src: &Path, dest: &Path) -> bool unsafe { fn test_is_cmd() { assert is_cmd(~"build"); assert is_cmd(~"clean"); + assert is_cmd(~"do"); assert is_cmd(~"install"); assert is_cmd(~"prefer"); assert is_cmd(~"test");