about summary refs log tree commit diff
path: root/src/librustpkg
diff options
context:
space:
mode:
authorZack Corr <zack@z0w0.me>2013-01-23 12:41:11 +1000
committerGraydon Hoare <graydon@mozilla.com>2013-02-15 18:04:10 -0800
commite34e072d1777ad2064ed9b70ccdbe29b4f100f9b (patch)
treee8180816c58150359c1034f49008901faa373612 /src/librustpkg
parent707944184304acbd81c026156a04b98570c6ef9c (diff)
downloadrust-e34e072d1777ad2064ed9b70ccdbe29b4f100f9b.tar.gz
rust-e34e072d1777ad2064ed9b70ccdbe29b4f100f9b.zip
rustpkg: Add do command and get cmd listeners working correctly
Diffstat (limited to 'src/librustpkg')
-rw-r--r--src/librustpkg/api.rs29
-rw-r--r--src/librustpkg/rustpkg.rc47
-rw-r--r--src/librustpkg/usage.rs7
-rw-r--r--src/librustpkg/util.rs61
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<PackageScript> {
         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 <cmd>
+
+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<Path>, 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<Path>, 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<Path>, 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");