summary refs log tree commit diff
path: root/src/librustpkg
diff options
context:
space:
mode:
authorZack Corr <zack@z0w0.me>2013-01-16 21:59:37 +1000
committerGraydon Hoare <graydon@mozilla.com>2013-02-15 18:04:10 -0800
commit226b61ba5f30e0ecb0799626a010161f3ce0b72d (patch)
treeed15c6860e9e94096eb2078df4d692f4d88f6b12 /src/librustpkg
parent71d34a8872491f37011aa14c866a95165fc45f99 (diff)
downloadrust-226b61ba5f30e0ecb0799626a010161f3ce0b72d.tar.gz
rust-226b61ba5f30e0ecb0799626a010161f3ce0b72d.zip
rustpkg: Add package script parsing
Diffstat (limited to 'src/librustpkg')
-rw-r--r--src/librustpkg/api.rs6
-rw-r--r--src/librustpkg/rustpkg.rc170
-rw-r--r--src/librustpkg/util.rs52
3 files changed, 218 insertions, 10 deletions
diff --git a/src/librustpkg/api.rs b/src/librustpkg/api.rs
index 10868c23636..6dd238b3d5c 100644
--- a/src/librustpkg/api.rs
+++ b/src/librustpkg/api.rs
@@ -9,7 +9,7 @@ pub struct Crate {
 pub impl Crate {
     fn flag(flag: ~str) -> Crate {
         Crate {
-            flags: vec::append(self.flags, flag),
+            flags: vec::append(copy self.flags, ~[flag]),
             .. copy self
         }
     }
@@ -18,3 +18,7 @@ pub impl Crate {
 pub fn build(_targets: ~[Crate]) {
     // TODO: magic
 }
+
+pub mod util {
+    
+}
diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc
index a21bd2dc9ec..e847a8935f6 100644
--- a/src/librustpkg/rustpkg.rc
+++ b/src/librustpkg/rustpkg.rc
@@ -17,6 +17,8 @@
 
 #[crate_type = "lib"];
 #[no_core];
+#[allow(vecs_implicitly_copyable,
+        non_implicitly_copyable_typarams)];
 
 extern mod core(vers = "0.6");
 extern mod std(vers = "0.6");
@@ -24,26 +26,171 @@ extern mod rustc(vers = "0.6");
 extern mod syntax(vers = "0.6");
 
 use core::*;
+use io::{ReaderUtil, WriterUtil};
 use std::getopts;
-use getopts::{optflag, optopt, opt_present};
 use rustc::metadata::{filesearch};
+use syntax::{ast, codemap, parse, visit, attr};
+use semver::Version;
 
 mod api;
 mod usage;
 mod util;
 
-use util::*;
+struct PackageScript {
+    id: ~str,
+    name: ~str,
+    vers: Version
+}
+
+impl PackageScript {
+    static fn parse(parent: Path) -> PackageScript {
+        let script = parent.push(~"package.rs");
+
+        if !os::path_exists(&script) {
+            fail ~"no package.rs file";
+        }
+
+        let sess = parse::new_parse_sess(None);
+        let crate = parse::parse_crate_from_file(&script, ~[], sess);
+        let mut id = None;
+        let mut vers = None;
+
+        fn load_pkg_attr(mis: ~[@ast::meta_item]) -> (Option<~str>,
+                                                      Option<~str>) {
+            let mut id = None;
+            let mut vers = None;
+
+            for mis.each |a| {
+                match a.node {
+                    ast::meta_name_value(v, ast::spanned {
+                                                node: ast::lit_str(s),
+                                                span: _}) => {
+                        match v {
+                            ~"id" => id = Some(*s),
+                            ~"vers" => vers = Some(*s),
+                            _ => ()
+                        }
+                    }
+                    _ => {}
+                }
+            }
+
+            (id, vers)
+        }
+
+        for crate.node.attrs.each |a| {
+            match a.node.value.node {
+                ast::meta_list(v, mis) => {
+                    match v {
+                        ~"pkg" => {
+                            let (i, v) = load_pkg_attr(mis);
+
+                            id = i;
+                            vers = v;
+                        }
+                        _ => {}
+                    }
+                }
+                _ => {}
+            }
+        }
+
+        if id.is_none() || vers.is_none() {
+            fail ~"id or vers isn't defined in a pkg attribute in package.rs";
+        }
+
+        let id = id.get();
+        let vers = vers.get();
+
+        PackageScript {
+            id: id,
+            name: util::parse_id(id),
+            vers: util::parse_vers(vers)
+        }
+    }
+
+    fn hash() -> ~str {
+        let hasher = hash::default_state();
+
+        hasher.write_str(self.id + self.vers.to_str());
+
+        self.name + hasher.result_str() + self.vers.to_str()
+    }
+
+    fn work_dir() -> Path {
+        util::root().push(self.hash())
+    }
+}
+
+struct Ctx {
+    cmd: ~str,
+    args: ~[~str],
+    cfgs: ~[~str],
+    prefer: bool
+}
+
+impl Ctx {
+    fn run() {
+        match self.cmd {
+            ~"build" => self.build(),
+            ~"clean" => self.clean(),
+            ~"install" => self.install(),
+            ~"prefer" => self.prefer(),
+            ~"test" => self.test(),
+            ~"uninstall" => self.uninstall(),
+            ~"unprefer" => self.unprefer(),
+            _ => fail ~"reached an unhandled command"
+        }
+    }
+
+    fn build() {
+        let script = PackageScript::parse(os::getcwd());
+
+        io::println(fmt!("build: %s (v%s)", script.id, script.vers.to_str()));
+    }
+
+    fn clean() {
+
+    }
+
+    fn install() {
+
+    }
+
+    fn prefer() {
+
+    }
+
+    fn test() {
+
+    }
+
+    fn uninstall() {
+
+    }
+
+    fn unprefer() {
+
+    }
+}
 
 pub fn main() {
     let args = os::args();
-    let opts = ~[optflag(~"h"), optflag(~"help")];
+    let opts = ~[getopts::optflag(~"h"), getopts::optflag(~"help"),
+                 getopts::optmulti(~"c"), getopts::optmulti(~"cfg"),
+                 getopts::optmulti(~"p"), getopts::optmulti(~"prefer")];
     let matches = &match getopts::getopts(args, opts) {
         result::Ok(m) => m,
         result::Err(f) => {
             fail fmt!("%s", getopts::fail_str(f));
         }
     };
-    let help = opt_present(matches, ~"h") || opt_present(matches, ~"help");
+    let help = getopts::opt_present(matches, ~"h") ||
+               getopts::opt_present(matches, ~"help");
+    let cfgs = vec::append(getopts::opt_strs(matches, ~"cfg"),
+                           getopts::opt_strs(matches, ~"c"));
+    let prefer = getopts::opt_present(matches, ~"p") ||
+                 getopts::opt_present(matches, ~"prefer");
     let mut args = copy matches.free;
 
     args.shift();
@@ -52,12 +199,12 @@ pub fn main() {
         return usage::general();
     }
 
-    let cmd = copy args[0];
+    let cmd = args.shift();
 
-    if !is_cmd(cmd) {
+    if !util::is_cmd(cmd) {
         return usage::general();
     } else if help {
-        match cmd {
+        return match cmd {
             ~"build" => usage::build(),
             ~"clean" => usage::clean(),
             ~"install" => usage::install(),
@@ -66,10 +213,15 @@ pub fn main() {
             ~"uninstall" => usage::uninstall(),
             ~"unprefer" => usage::unprefer(),
             _ => usage::general()
-        }
+        };
     }
 
-    Ctx { cmd: cmd, args: args }
+    Ctx {
+        cmd: cmd,
+        args: args,
+        cfgs: cfgs,
+        prefer: prefer
+    }.run();
 }
 
 pub use Crate = api::Crate;
diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs
index 304c4864d4c..0f2aea5a33b 100644
--- a/src/librustpkg/util.rs
+++ b/src/librustpkg/util.rs
@@ -1,6 +1,58 @@
+use core::*;
+use rustc::metadata::filesearch;
+use semver::Version;
+use std::net::url;
+
+pub fn root() -> Path {
+    match filesearch::get_rustpkg_root() {
+        result::Ok(path) => path,
+        result::Err(err) => fail err
+    }
+}
+
 pub fn is_cmd(cmd: ~str) -> bool {
     let cmds = &[~"build", ~"clean", ~"install", ~"prefer", ~"test",
                  ~"uninstall", ~"unprefer"];
 
     vec::contains(cmds, &cmd)
 }
+
+pub fn parse_id(id: ~str) -> ~str {
+    let parts = str::split_char(id, '.');
+
+    for parts.each |&part| {
+        for str::chars(part).each |&char| {
+            if char::is_whitespace(char) {
+                fail ~"could not parse id: contains whitespace";
+            } else if char::is_uppercase(char) {
+                fail ~"could not parse id: should be all lowercase";
+            }
+        }
+    }
+
+    parts.last()
+}
+
+pub fn parse_vers(vers: ~str) -> Version {
+    match semver::parse(vers) {
+        Some(vers) => vers,
+        None => fail ~"could not parse version: invalid"
+    }
+}
+
+#[test]
+fn test_is_cmd() {
+    assert is_cmd(~"build");
+    assert is_cmd(~"clean");
+    assert is_cmd(~"install");
+    assert is_cmd(~"prefer");
+    assert is_cmd(~"test");
+    assert is_cmd(~"uninstall");
+    assert is_cmd(~"unprefer");
+}
+
+#[test]
+fn test_parse_id() {
+    assert parse_id(~"org.mozilla.servo").get() == ~"servo";
+    assert parse_id(~"org. mozilla.servo 2131").is_err();
+}