*/
-use cmp::Eq;
+use cmp::{Eq,Ord};
use kinds::Copy;
use option;
use ptr;
Some(T),
}
+pub impl<T:Ord> Ord for Option<T> {
+ pure fn lt(&self, other: &Option<T>) -> bool {
+ match (self, other) {
+ (&None, &None) => false,
+ (&None, &Some(_)) => true,
+ (&Some(_), &None) => false,
+ (&Some(ref a), &Some(ref b)) => *a < *b
+ }
+ }
+
+ pure fn le(&self, other: &Option<T>) -> bool {
+ match (self, other) {
+ (&None, &None) => true,
+ (&None, &Some(_)) => true,
+ (&Some(_), &None) => false,
+ (&Some(ref a), &Some(ref b)) => *a <= *b
+ }
+ }
+
+ pure fn ge(&self, other: &Option<T>) -> bool {
+ ! (self < other)
+ }
+
+ pure fn gt(&self, other: &Option<T>) -> bool {
+ ! (self <= other)
+ }
+}
+
#[inline(always)]
pub pure fn get<T: Copy>(opt: Option<T>) -> T {
/*!
#[allow(vecs_implicitly_copyable,
non_implicitly_copyable_typarams)];
+#[legacy_records];
+
extern mod core(vers = "0.6");
extern mod std(vers = "0.6");
extern mod rustc(vers = "0.6");
use io::{ReaderUtil, WriterUtil};
use std::{json, semver, getopts};
use std::net::url;
-use send_map::linear::LinearMap;
+use hashmap::linear::LinearMap;
use rustc::metadata::filesearch;
use rustc::driver::{driver, session};
use syntax::{ast, attr, codemap, diagnostic, parse, visit};
+use syntax::codemap::spanned;
mod usage;
mod util;
for mis.each |a| {
match a.node {
- ast::meta_name_value(v, ast::spanned {
+ ast::meta_name_value(v, spanned {
node: ast::lit_str(s),
span: _}) => {
match v {
for mis.each |a| {
match a.node {
- ast::meta_name_value(v, ast::spanned {
+ ast::meta_name_value(v, spanned {
node: ast::lit_str(s),
span: _}) => {
match v {
for mis.each |a| {
match a.node {
- ast::meta_name_value(v, ast::spanned {
+ ast::meta_name_value(v, spanned {
node: ast::lit_str(s),
span: _}) => {
match v {
let (u, t) = load_pkg_dep_attr(mis);
if u.is_none() {
- fail ~"pkg_dep attr without a url value";
+ fail!(~"pkg_dep attr without a url value");
}
deps.push((u.get(), t));
let f = load_pkg_crate_attr(mis);
if f.is_none() {
- fail ~"pkg_file attr without a file value";
+ fail!(~"pkg_file attr without a file value");
}
crates.push(f.get());
// Build the bootstrap and run a command
// FIXME (#4432): Use workcache to only compile the script when changed
- fn run(cmd: ~str, test: bool) -> int {
+ fn run(&self, cmd: ~str, test: bool) -> int {
let work_dir = self.work_dir();
let input = self.input;
let sess = self.sess;
run::run_program(exe.to_str(), ~[root.to_str(), cmd, test.to_str()])
}
- fn hash() -> ~str {
+ fn hash(&self) -> ~str {
fmt!("%s-%s-%s", self.name, util::hash(self.id + self.vers.to_str()),
self.vers.to_str())
}
- fn work_dir() -> Path {
+ fn work_dir(&self) -> Path {
util::root().push(~"work").push(self.hash())
}
}
}
impl Ctx {
- fn run(cmd: ~str, args: ~[~str]) {
+ fn run(&self, cmd: ~str, args: ~[~str]) {
let root = util::root();
util::need_dir(&root);
self.unprefer(name.get(), vers);
}
- _ => fail ~"reached an unhandled command"
+ _ => fail!(~"reached an unhandled command")
}
}
- fn do_cmd(cmd: ~str) -> bool {
+ fn do_cmd(&self, cmd: ~str) -> bool {
match cmd {
~"build" | ~"test" => {
util::error(~"that command cannot be manually called");
status == 0
}
- fn build(dir: &Path, verbose: bool, opt: bool,
+ fn build(&self, dir: &Path, verbose: bool, opt: bool,
test: bool) -> Option<PackageScript> {
let cwd = &os::getcwd();
let script = match PackageScript::parse(dir) {
Some(script)
}
- fn compile(crate: &Path, dir: &Path, flags: ~[~str],
+ fn compile(&self, crate: &Path, dir: &Path, flags: ~[~str],
cfgs: ~[~str], opt: bool, test: bool) -> bool {
util::compile_crate(None, crate, dir, flags, cfgs, opt, test)
}
- fn clean() -> bool {
+ fn clean(&self) -> bool {
let script = match PackageScript::parse(&os::getcwd()) {
result::Ok(script) => script,
result::Err(err) => {
true
}
- fn info() {
+ fn info(&self) {
if self.json {
match PackageScript::parse(&os::getcwd()) {
result::Ok(script) => {
- let mut map = ~LinearMap();
+ let mut map = ~LinearMap::new();
map.insert(~"id", json::String(script.id));
map.insert(~"name", json::String(script.name));
map.insert(~"vers", json::String(script.vers.to_str()));
map.insert(~"deps", json::List(do script.deps.map |&dep| {
let (url, target) = dep;
- let mut inner = ~LinearMap();
+ let mut inner = ~LinearMap::new();
inner.insert(~"url", json::String(url));
if !target.is_none() {
- inner.insert(~"target", json::String(target.get()));
+ inner.insert(~"target",
+ json::String(target.get()));
}
json::Object(inner)
util::note(fmt!("id: %s", script.id));
util::note(fmt!("name: %s", script.name));
util::note(fmt!("vers: %s", script.vers.to_str()));
- util::note(fmt!("deps: %s", if script.deps.len() > 0 { ~"" } else { ~"none" }));
+ util::note(fmt!("deps: %s",
+ if script.deps.len() > 0 {
+ ~""
+ } else {
+ ~"none"
+ }));
for script.deps.each |&dep| {
let (url, target) = dep;
}
}
- fn install(url: Option<~str>, target: Option<~str>, cache: bool) -> bool {
+ fn install(&self, url: Option<~str>,
+ target: Option<~str>, cache: bool) -> bool {
let mut success;
let mut dir;
true
}
- fn fetch(dir: &Path, url: ~str, target: Option<~str>) -> bool {
+ fn fetch(&self, dir: &Path, url: ~str, target: Option<~str>) -> bool {
let url = if str::find_str(url, "://").is_none() {
~"http://" + url }
else { url };
}
}
- fn fetch_curl(dir: &Path, url: ~str) -> bool {
+ fn fetch_curl(&self, dir: &Path, url: ~str) -> bool {
util::note(fmt!("fetching from %s using curl", url));
let tar = dir.dir_path().push(&dir.file_path().to_str() + ~".tar");
true
}
- fn fetch_git(dir: &Path, url: ~str, target: Option<~str>) -> bool {
+ fn fetch_git(&self, dir: &Path, url: ~str, target: Option<~str>) -> bool {
util::note(fmt!("fetching from %s using git", url));
// Git can't clone into a non-empty directory
true
}
- fn prefer(id: ~str, vers: Option<~str>) -> bool {
+ fn prefer(&self, id: ~str, vers: Option<~str>) -> bool {
let package = match util::get_pkg(id, vers) {
result::Ok(package) => package,
result::Err(err) => {
true
}
- fn test() -> bool {
+ fn test(&self) -> bool {
let script = match self.build(&os::getcwd(), false, false, true) {
Some(script) => script,
None => {
true
}
- fn uninstall(id: ~str, vers: Option<~str>) -> bool {
+ fn uninstall(&self, id: ~str, vers: Option<~str>) -> bool {
let package = match util::get_pkg(id, vers) {
result::Ok(package) => package,
result::Err(err) => {
true
}
- fn unprefer(id: ~str, vers: Option<~str>) -> bool {
+ fn unprefer(&self, id: ~str, vers: Option<~str>) -> bool {
let package = match util::get_pkg(id, vers) {
result::Ok(package) => package,
result::Err(err) => {
Ctx {
cfgs: cfgs,
json: json,
- mut dep_cache: LinearMap()
+ mut dep_cache: LinearMap::new()
}.run(cmd, args);
}
}
pub impl Crate {
- pub fn flag(flag: ~str) -> Crate {
+ pub fn flag(&self, flag: ~str) -> Crate {
Crate {
flags: vec::append(copy self.flags, ~[flag]),
- .. copy self
+ .. copy *self
}
}
- pub fn flags(flags: ~[~str]) -> Crate {
+ pub fn flags(&self, flags: ~[~str]) -> Crate {
Crate {
flags: vec::append(copy self.flags, flags),
- .. copy self
+ .. copy *self
}
}
- pub fn cfg(cfg: ~str) -> Crate {
+ pub fn cfg(&self, cfg: ~str) -> Crate {
Crate {
cfgs: vec::append(copy self.cfgs, ~[cfg]),
- .. copy self
+ .. copy *self
}
}
- pub fn cfgs(cfgs: ~[~str]) -> Crate {
+ pub fn cfgs(&self, cfgs: ~[~str]) -> Crate {
Crate {
cfgs: vec::append(copy self.cfgs, cfgs),
- .. copy self
+ .. copy *self
}
}
}
// except according to those terms.
use core::*;
-use send_map::linear::LinearMap;
+use hashmap::linear::LinearMap;
use rustc::metadata::filesearch;
use rustc::driver::{driver, session};
use syntax::ast_util::*;
use syntax::{ast, attr, codemap, diagnostic, fold, parse, visit};
-use codemap::span;
+use codemap::{span, dummy_sp, spanned};
use std::semver;
use std::{json, term, sort, getopts};
use getopts::groups::getopts;
use Listener;
+use syntax::ext::base::{mk_ctxt, ext_ctxt};
+use syntax::ext::build;
+
pub struct Package {
id: ~str,
vers: semver::Version,
pub fn root() -> Path {
match filesearch::get_rustpkg_root() {
result::Ok(path) => path,
- result::Err(err) => fail err
+ result::Err(err) => fail!(err)
}
}
result::Ok(parts.last())
}
-fn mk_rustpkg_use(ctx: @ReadyCtx) -> @ast::view_item {
- let vers = ast::lit_str(@~"0.6");
- let vers = no_span(vers);
- let mi = ast::meta_name_value(~"vers", vers);
- let mi = no_span(mi);
- let vi = ast::view_item_use(ctx.sess.ident_of(~"rustpkg"),
- ~[@mi],
- ctx.sess.next_node_id());
-
- @ast::view_item {
- node: vi,
- attrs: ~[],
- vis: ast::private,
- span: dummy_sp()
- }
-}
-
struct ListenerFn {
cmds: ~[~str],
span: codemap::span,
struct ReadyCtx {
sess: session::Session,
crate: @ast::crate,
+ ext_cx: ext_ctxt,
mut path: ~[ast::ident],
mut fns: ~[ListenerFn]
}
-fn fold_mod(ctx: @ReadyCtx, m: ast::_mod,
+fn fold_mod(_ctx: @ReadyCtx, m: ast::_mod,
fold: fold::ast_fold) -> ast::_mod {
fn strip_main(item: @ast::item) -> @ast::item {
@ast::item {
}
fold::noop_fold_mod(ast::_mod {
- view_items: vec::append_one(m.view_items, mk_rustpkg_use(ctx)),
items: do vec::map(m.items) |item| {
strip_main(*item)
- }
+ },
+ .. m
}, fold)
}
-fn fold_crate(ctx: @ReadyCtx, crate: ast::crate_,
- fold: fold::ast_fold) -> ast::crate_ {
- let folded = fold::noop_fold_crate(crate, fold);
-
- ast::crate_ {
- module: add_pkg_module(ctx, /*bad*/copy folded.module),
- .. folded
- }
-}
-
fn fold_item(ctx: @ReadyCtx, item: @ast::item,
fold: fold::ast_fold) -> Option<@ast::item> {
res
}
-fn mk_rustpkg_import(ctx: @ReadyCtx) -> @ast::view_item {
- let path = @ast::path {
- span: dummy_sp(),
- global: false,
- idents: ~[ctx.sess.ident_of(~"rustpkg")],
- rp: None,
- types: ~[]
- };
- let vp = @no_span(ast::view_path_simple(ctx.sess.ident_of(~"rustpkg"),
- path, ast::type_value_ns,
- ctx.sess.next_node_id()));
-
- @ast::view_item {
- node: ast::view_item_import(~[vp]),
- attrs: ~[],
- vis: ast::private,
- span: dummy_sp()
- }
-}
-
fn add_pkg_module(ctx: @ReadyCtx, m: ast::_mod) -> ast::_mod {
- let listeners = mk_listeners(ctx);
- let main = mk_main(ctx);
- let pkg_mod = @ast::_mod {
- view_items: ~[mk_rustpkg_import(ctx)],
- items: ~[main, listeners]
- };
- let resolve_unexported_attr =
- attr::mk_attr(attr::mk_word_item(~"!resolve_unexported"));
- let item_ = ast::item_mod(*pkg_mod);
- let item = @ast::item {
- ident: ctx.sess.ident_of(~"__pkg"),
- attrs: ~[resolve_unexported_attr],
- id: ctx.sess.next_node_id(),
- node: item_,
- vis: ast::public,
- span: dummy_sp(),
- };
-
+ let listeners = mk_listener_vec(ctx);
+ let ext_cx = ctx.ext_cx;
+ let item = quote_item! (
+ mod __pkg {
+ extern mod rustpkg (vers="0.6");
+ const listeners : &[rustpkg::Listener] = $listeners;
+ #[main]
+ fn main() {
+ rustpkg::run(listeners);
+ }
+ }
+ );
ast::_mod {
- items: vec::append_one(/*bad*/copy m.items, item),
+ items: vec::append_one(/*bad*/copy m.items, item.get()),
.. m
}
}
-fn no_span<T: Copy>(t: T) -> ast::spanned<T> {
- ast::spanned {
- node: t,
- span: dummy_sp()
- }
-}
-
-fn path_node(ids: ~[ast::ident]) -> @ast::path {
- @ast::path {
- span: dummy_sp(),
- global: false,
- idents: ids,
- rp: None,
- types: ~[]
- }
-}
-
-fn path_node_global(ids: ~[ast::ident]) -> @ast::path {
- @ast::path {
- span: dummy_sp(),
- global: true,
- idents: ids,
- rp: None,
- types: ~[]
- }
-}
-
-fn mk_listeners(ctx: @ReadyCtx) -> @ast::item {
- let ret_ty = mk_listener_vec_ty(ctx);
- let decl = ast::fn_decl {
- inputs: ~[],
- output: ret_ty,
- cf: ast::return_val
- };
- let listeners = mk_listener_vec(ctx);
- let body_ = default_block(~[], option::Some(listeners),
- ctx.sess.next_node_id());
- let body = no_span(body_);
- let item_ = ast::item_fn(decl, ast::impure_fn, ~[], body);
-
- @ast::item {
- ident: ctx.sess.ident_of(~"listeners"),
- attrs: ~[],
- id: ctx.sess.next_node_id(),
- node: item_,
- vis: ast::public,
- span: dummy_sp(),
- }
-}
-
-fn mk_path(ctx: @ReadyCtx, path: ~[ast::ident]) -> @ast::path {
- path_node(~[ctx.sess.ident_of(~"rustpkg")] + path)
-}
-
-fn mk_listener_vec_ty(ctx: @ReadyCtx) -> @ast::Ty {
- let listener_ty_path = mk_path(ctx, ~[ctx.sess.ident_of(~"Listener")]);
- let listener_ty = ast::Ty {
- id: ctx.sess.next_node_id(),
- node: ast::ty_path(listener_ty_path,
- ctx.sess.next_node_id()),
- span: dummy_sp()
- };
- let vec_mt = ast::mt {
- ty: @listener_ty,
- mutbl: ast::m_imm
- };
- let inner_ty = @ast::Ty {
- id: ctx.sess.next_node_id(),
- node: ast::ty_vec(vec_mt),
- span: dummy_sp()
- };
-
- @ast::Ty {
- id: ctx.sess.next_node_id(),
- node: ast::ty_uniq(ast::mt {
- ty: inner_ty,
- mutbl: ast::m_imm
- }),
- span: dummy_sp()
- }
-}
-
fn mk_listener_vec(ctx: @ReadyCtx) -> @ast::expr {
let fns = ctx.fns;
-
let descs = do fns.map |listener| {
mk_listener_rec(ctx, *listener)
};
- let inner_expr = @ast::expr {
- id: ctx.sess.next_node_id(),
- callee_id: ctx.sess.next_node_id(),
- node: ast::expr_vec(descs, ast::m_imm),
- span: dummy_sp()
- };
-
- @ast::expr {
- id: ctx.sess.next_node_id(),
- callee_id: ctx.sess.next_node_id(),
- node: ast::expr_vstore(inner_expr, ast::expr_vstore_uniq),
- span: dummy_sp()
- }
+ build::mk_slice_vec_e(ctx.ext_cx, dummy_sp(), descs)
}
fn mk_listener_rec(ctx: @ReadyCtx, listener: ListenerFn) -> @ast::expr {
+
let span = listener.span;
- let path = /*bad*/copy listener.path;
- let descs = do listener.cmds.map |&cmd| {
- let inner = @ast::expr {
- 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
- };
-
- @ast::expr {
- 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 = @ast::expr {
- id: ctx.sess.next_node_id(),
- callee_id: ctx.sess.next_node_id(),
- node: ast::expr_vec(descs, ast::m_imm),
- span: dummy_sp()
- };
- let cmd_expr = ast::expr {
- id: ctx.sess.next_node_id(),
- callee_id: ctx.sess.next_node_id(),
- node: ast::expr_vstore(cmd_expr_inner, ast::expr_vstore_uniq),
- span: dummy_sp()
- };
- let cmd_field = no_span(ast::field_ {
- mutbl: ast::m_imm,
- ident: ctx.sess.ident_of(~"cmds"),
- expr: @cmd_expr,
- });
-
- let cb_path = path_node_global(path);
- let cb_expr = ast::expr {
- id: ctx.sess.next_node_id(),
- callee_id: ctx.sess.next_node_id(),
- node: ast::expr_path(cb_path),
- span: span
+ let cmds = do listener.cmds.map |&cmd| {
+ build::mk_base_str(ctx.ext_cx, span, cmd)
};
- let cb_wrapper_expr = mk_fn_wrapper(ctx, cb_expr, span);
- let cb_field = no_span(ast::field_ {
- mutbl: ast::m_imm,
- ident: ctx.sess.ident_of(~"cb"),
- expr: cb_wrapper_expr
- });
-
- let listener_path = mk_path(ctx, ~[ctx.sess.ident_of(~"Listener")]);
- let listener_rec_ = ast::expr_struct(listener_path,
- ~[cmd_field, cb_field],
- option::None);
- @ast::expr {
- id: ctx.sess.next_node_id(),
- callee_id: ctx.sess.next_node_id(),
- node: listener_rec_,
- span: span
- }
-}
-fn mk_fn_wrapper(ctx: @ReadyCtx, fn_path_expr: ast::expr,
- span: span) -> @ast::expr {
- let call_expr = ast::expr {
- id: ctx.sess.next_node_id(),
- callee_id: ctx.sess.next_node_id(),
- node: ast::expr_call(@fn_path_expr, ~[], false),
- span: span
- };
- let call_stmt = no_span(ast::stmt_semi(@call_expr,
- ctx.sess.next_node_id()));
- let wrapper_decl = ast::fn_decl {
- inputs: ~[],
- output: @ast::Ty {
- id: ctx.sess.next_node_id(),
- node: ast::ty_nil, span: span
- },
- cf: ast::return_val
- };
- let wrapper_body = no_span(ast::blk_ {
- view_items: ~[],
- stmts: ~[@call_stmt],
- expr: option::None,
- id: ctx.sess.next_node_id(),
- rules: ast::default_blk
- });
-
- @ast::expr {
- id: ctx.sess.next_node_id(),
- callee_id: ctx.sess.next_node_id(),
- node: ast::expr_fn(ast::ProtoBare, wrapper_decl,
- wrapper_body, @~[]),
- span: span
- }
-}
+ let cmds_expr = build::mk_slice_vec_e(ctx.ext_cx, span, cmds);
+ let cb_expr = build::mk_path(ctx.ext_cx, span, copy listener.path);
+ let ext_cx = ctx.ext_cx;
-fn mk_main(ctx: @ReadyCtx) -> @ast::item {
- let ret_ty = ast::Ty {
- id: ctx.sess.next_node_id(),
- node: ast::ty_nil,
- span: dummy_sp()
- };
- let decl = ast::fn_decl {
- inputs: ~[],
- output: @ret_ty,
- cf: ast::return_val
- };
- let run_call_expr = mk_run_call(ctx);
- let body_ = default_block(~[], option::Some(run_call_expr),
- ctx.sess.next_node_id());
- let body = ast::spanned {
- node: body_,
- span: dummy_sp()
- };
- let item_ = ast::item_fn(decl, ast::impure_fn, ~[], body);
-
- @ast::item {
- ident: ctx.sess.ident_of(~"main"),
- attrs: ~[attr::mk_attr(attr::mk_word_item(~"main"))],
- id: ctx.sess.next_node_id(),
- node: item_,
- vis: ast::public,
- span: dummy_sp(),
- }
-}
-
-fn mk_run_call(ctx: @ReadyCtx) -> @ast::expr {
- let listener_path = path_node(~[ctx.sess.ident_of(~"listeners")]);
- let listener_path_expr_ = ast::expr_path(listener_path);
- let listener_path_expr = ast::expr {
- id: ctx.sess.next_node_id(),
- callee_id: ctx.sess.next_node_id(),
- node: listener_path_expr_,
- span: dummy_sp()
- };
- let listener_call_expr_ = ast::expr_call(@listener_path_expr, ~[], false);
- let listener_call_expr = ast::expr {
- id: ctx.sess.next_node_id(),
- callee_id: ctx.sess.next_node_id(),
- node: listener_call_expr_,
- span: dummy_sp()
- };
- let rustpkg_run_path = mk_path(ctx, ~[ctx.sess.ident_of(~"run")]);
-
- let rustpkg_run_path_expr_ = ast::expr_path(rustpkg_run_path);
- let rustpkg_run_path_expr = ast::expr {
- id: ctx.sess.next_node_id(),
- callee_id: ctx.sess.next_node_id(),
- node: rustpkg_run_path_expr_,
- span: dummy_sp()
- };
- let rustpkg_run_call_expr_ = ast::expr_call(@rustpkg_run_path_expr,
- ~[@listener_call_expr],
- false);
- @ast::expr {
- id: ctx.sess.next_node_id(),
- callee_id: ctx.sess.next_node_id(),
- node: rustpkg_run_call_expr_,
- span: dummy_sp()
- }
+ quote_expr!(
+ Listener {
+ cmds: $cmds_expr,
+ cb: $cb_expr
+ }
+ )
}
/// Generate/filter main function, add the list of commands, etc.
let ctx = @ReadyCtx {
sess: sess,
crate: crate,
+ ext_cx: mk_ctxt(sess.parse_sess, copy sess.opts.cfg),
mut path: ~[],
mut fns: ~[]
};
let precursor = @fold::AstFoldFns {
- fold_crate: fold::wrap(|a, b| fold_crate(ctx, a, b)),
+ // fold_crate: fold::wrap(|a, b| fold_crate(ctx, a, b)),
fold_item: |a, b| fold_item(ctx, a, b),
fold_mod: |a, b| fold_mod(ctx, a, b),
.. *fold::default_ast_fold()
pub fn need_dir(s: &Path) {
if !os::path_is_dir(s) && !os::make_dir(s, 493_i32) {
- fail fmt!("can't create dir: %s", s.to_str());
+ fail!(fmt!("can't create dir: %s", s.to_str()));
}
}
out.write_str(~"note: ");
term::reset(out);
out.write_line(msg);
- } else { out.write_line(~"note: " + msg); }
+ } else {
+ out.write_line(~"note: " + msg);
+ }
}
pub fn warn(msg: ~str) {
out.write_str(~"warning: ");
term::reset(out);
out.write_line(msg);
- }else { out.write_line(~"warning: " + msg); }
+ } else {
+ out.write_line(~"warning: " + msg);
+ }
}
pub fn error(msg: ~str) {
out.write_str(~"error: ");
term::reset(out);
out.write_line(msg);
+ } else {
+ out.write_line(~"error: " + msg);
}
- else { out.write_line(~"error: " + msg); }
}
pub fn hash(data: ~str) -> ~str {
fn _add_pkg(packages: ~[json::Json], pkg: &Package) -> ~[json::Json] {
for packages.each |&package| {
- match package {
- json::Object(map) => {
+ match &package {
+ &json::Object(ref map) => {
let mut has_id = false;
match map.get(&~"id") {
- json::String(str) => {
- if pkg.id == str {
+ &json::String(ref str) => {
+ if pkg.id == *str {
has_id = true;
}
}
}
match map.get(&~"vers") {
- json::String(str) => {
- if has_id && pkg.vers.to_str() == str {
- return packages;
+ &json::String(ref str) => {
+ if has_id && pkg.vers.to_str() == *str {
+ return copy packages;
}
}
_ => {}
}
}
- let mut map = ~LinearMap();
+ let mut map = ~LinearMap::new();
map.insert(~"id", json::String(pkg.id));
map.insert(~"vers", json::String(pkg.vers.to_str()));
}
fn _rm_pkg(packages: ~[json::Json], pkg: &Package) -> ~[json::Json] {
- do packages.filter_map |&package| {
- match package {
- json::Object(map) => {
+ do packages.filter_mapped |&package| {
+ match &package {
+ &json::Object(ref map) => {
let mut has_id = false;
match map.get(&~"id") {
- json::String(str) => {
+ &json::String(str) => {
if pkg.id == str {
has_id = true;
}
}
match map.get(&~"vers") {
- json::String(str) => {
- if has_id && pkg.vers.to_str() == str { None }
- else { Some(package) }
+ &json::String(ref str) => {
+ if has_id && pkg.vers.to_str() == *str {
+ None
+ } else {
+ Some(copy package)
+ }
}
- _ => { Some(package) }
+ _ => { Some(copy package) }
}
}
- _ => { Some(package) }
+ _ => { Some(copy package) }
}
}
}
match package {
json::Object(map) => {
let pid = match map.get(&~"id") {
- json::String(str) => str,
+ &json::String(str) => str,
_ => loop
};
let pname = match parse_name(pid) {
}
};
let pvers = match map.get(&~"vers") {
- json::String(str) => str,
+ &json::String(str) => str,
_ => loop
};
if pid == id || pname == name {
let bins = match map.get(&~"bins") {
- json::List(list) => {
+ &json::List(ref list) => {
do list.map |&bin| {
match bin {
json::String(str) => str,
_ => ~[]
};
let libs = match map.get(&~"libs") {
- json::List(list) => {
+ &json::List(ref list) => {
do list.map |&lib| {
match lib {
json::String(str) => str,
for mis.each |a| {
match a.node {
- ast::meta_name_value(v, ast::spanned {node: ast::lit_str(s),
+ ast::meta_name_value(v, spanned {node: ast::lit_str(s),
span: _}) => {
match v {
~"name" => name = Some(*s),
for crate.node.attrs.each |a| {
match a.node.value.node {
- ast::meta_name_value(v, ast::spanned {node: ast::lit_str(s),
+ ast::meta_name_value(v, spanned {node: ast::lit_str(s),
span: _}) => {
match v {
~"crate_type" => crate_type = Some(*s),
#[cfg(target_os = "android")]
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "macos")]
-pub fn link_exe(src: &Path, dest: &Path) -> bool unsafe {
- do str::as_c_str(src.to_str()) |src_buf| {
- do str::as_c_str(dest.to_str()) |dest_buf| {
- libc::link(src_buf, dest_buf) == 0 as libc::c_int &&
- libc::chmod(dest_buf, 755) == 0 as libc::c_int
+pub fn link_exe(src: &Path, dest: &Path) -> bool {
+ unsafe {
+ do str::as_c_str(src.to_str()) |src_buf| {
+ do str::as_c_str(dest.to_str()) |dest_buf| {
+ libc::link(src_buf, dest_buf) == 0 as libc::c_int &&
+ libc::chmod(dest_buf, 755) == 0 as libc::c_int
+ }
}
}
}
use char;
use core::cmp;
+#[deriving_eq]
+pub enum Identifier {
+ Numeric(uint),
+ AlphaNumeric(~str)
+}
+
+impl cmp::Ord for Identifier {
+ #[inline(always)]
+ pure fn lt(&self, other: &Identifier) -> bool {
+ match (self, other) {
+ (&Numeric(a), &Numeric(b)) => a < b,
+ (&Numeric(_), _) => true,
+ (&AlphaNumeric(ref a), &AlphaNumeric(ref b)) => *a < *b,
+ (&AlphaNumeric(_), _) => false
+ }
+ }
+ #[inline(always)]
+ pure fn le(&self, other: &Identifier) -> bool {
+ ! (other < self)
+ }
+ #[inline(always)]
+ pure fn gt(&self, other: &Identifier) -> bool {
+ other < self
+ }
+ #[inline(always)]
+ pure fn ge(&self, other: &Identifier) -> bool {
+ ! (self < other)
+ }
+}
+
+impl ToStr for Identifier {
+ #[inline(always)]
+ pure fn to_str(&self) -> ~str {
+ match self {
+ &Numeric(n) => n.to_str(),
+ &AlphaNumeric(ref s) => s.to_str()
+ }
+ }
+}
+
+
+#[deriving_eq]
pub struct Version {
major: uint,
minor: uint,
patch: uint,
- tag: Option<~str>,
+ pre: ~[Identifier],
+ build: ~[Identifier],
}
-impl Version: ToStr {
+impl ToStr for Version {
#[inline(always)]
- pure fn to_str() -> ~str {
- let suffix = match copy self.tag {
- Some(tag) => ~"-" + tag,
- None => ~""
+ pure fn to_str(&self) -> ~str {
+ let s = fmt!("%u.%u.%u", self.major, self.minor, self.patch);
+ let s = if self.pre.is_empty() {
+ s
+ } else {
+ s + "-" + str::connect(self.pre.map(|i| i.to_str()), ".")
};
-
- fmt!("%u.%u.%u%s", self.major, self.minor, self.patch, suffix)
+ if self.build.is_empty() {
+ s
+ } else {
+ s + "+" + str::connect(self.build.map(|i| i.to_str()), ".")
+ }
}
}
-impl Version: cmp::Ord {
+impl cmp::Ord for Version {
#[inline(always)]
pure fn lt(&self, other: &Version) -> bool {
+
self.major < other.major ||
- self.minor < other.minor ||
- self.patch < other.patch ||
- (match self.tag {
- Some(stag) => match other.tag {
- Some(otag) => stag < otag,
- None => true
- },
- None => false
- })
+
+ (self.major == other.major &&
+ self.minor < other.minor) ||
+
+ (self.major == other.major &&
+ self.minor == other.minor &&
+ self.patch < other.patch) ||
+
+ (self.major == other.major &&
+ self.minor == other.minor &&
+ self.patch == other.patch &&
+ // NB: semver spec says 0.0.0-pre < 0.0.0
+ // but the version of ord defined for vec
+ // says that [] < [pre], so we alter it
+ // here.
+ (match (self.pre.len(), other.pre.len()) {
+ (0, 0) => false,
+ (0, _) => false,
+ (_, 0) => true,
+ (_, _) => self.pre < other.pre
+ })) ||
+
+ (self.major == other.major &&
+ self.minor == other.minor &&
+ self.patch == other.patch &&
+ self.pre == other.pre &&
+ self.build < other.build)
}
+
#[inline(always)]
pure fn le(&self, other: &Version) -> bool {
- self.major <= other.major ||
- self.minor <= other.minor ||
- self.patch <= other.patch ||
- (match self.tag {
- Some(stag) => match other.tag {
- Some(otag) => stag <= otag,
- None => true
- },
- None => false
- })
+ ! (other < self)
}
#[inline(always)]
pure fn gt(&self, other: &Version) -> bool {
- self.major > other.major ||
- self.minor > other.minor ||
- self.patch > other.patch ||
- (match self.tag {
- Some(stag) => match other.tag {
- Some(otag) => stag > otag,
- None => false
- },
- None => true
- })
+ other < self
}
#[inline(always)]
pure fn ge(&self, other: &Version) -> bool {
- self.major >= other.major ||
- self.minor >= other.minor ||
- self.patch >= other.patch ||
- (match self.tag {
- Some(stag) => match other.tag {
- Some(otag) => stag >= otag,
- None => false
- },
- None => true
- })
+ ! (self < other)
}
}
-fn read_whitespace(rdr: io::Reader, ch: char) -> char {
- let mut nch = ch;
+condition! {
+ bad_parse: () -> ();
+}
- while char::is_whitespace(nch) {
- nch = rdr.read_char();
+fn take_nonempty_prefix(rdr: io::Reader,
+ ch: char,
+ pred: fn(char) -> bool) -> (~str, char) {
+ let mut buf = ~"";
+ let mut ch = ch;
+ while pred(ch) {
+ str::push_char(&mut buf, ch);
+ ch = rdr.read_char();
}
-
- nch
+ if buf.is_empty() {
+ bad_parse::cond.raise(())
+ }
+ debug!("extracted nonempty prefix: %s", buf);
+ (buf, ch)
}
-fn parse_reader(rdr: io::Reader) -> Option<(Version, char)> {
- fn read_digits(rdr: io::Reader, ch: char) -> Option<(uint, char)> {
- let mut buf = ~"";
- let mut nch = ch;
-
- while nch != -1 as char {
- match nch {
- '0' .. '9' => buf += str::from_char(nch),
- _ => break
- }
+fn take_num(rdr: io::Reader, ch: char) -> (uint, char) {
+ let (s, ch) = take_nonempty_prefix(rdr, ch, char::is_digit);
+ match uint::from_str(s) {
+ None => { bad_parse::cond.raise(()); (0, ch) },
+ Some(i) => (i, ch)
+ }
+}
- nch = rdr.read_char();
+fn take_ident(rdr: io::Reader, ch: char) -> (Identifier, char) {
+ let (s,ch) = take_nonempty_prefix(rdr, ch, char::is_alphanumeric);
+ if s.all(char::is_digit) {
+ match uint::from_str(s) {
+ None => { bad_parse::cond.raise(()); (Numeric(0), ch) },
+ Some(i) => (Numeric(i), ch)
}
+ } else {
+ (AlphaNumeric(s), ch)
+ }
+}
- do uint::from_str(buf).chain_ref |&i| {
- Some((i, nch))
- }
+fn expect(ch: char, c: char) {
+ if ch != c {
+ bad_parse::cond.raise(())
}
+}
- fn read_tag(rdr: io::Reader) -> Option<(~str, char)> {
- let mut ch = rdr.read_char();
- let mut buf = ~"";
+fn parse_reader(rdr: io::Reader) -> Version {
- while ch != -1 as char {
- match ch {
- '0' .. '9' | 'A' .. 'Z' | 'a' .. 'z' | '-' => {
- buf += str::from_char(ch);
- }
- _ => break
- }
+ let (major, ch) = take_num(rdr, rdr.read_char());
+ expect(ch, '.');
+ let (minor, ch) = take_num(rdr, rdr.read_char());
+ expect(ch, '.');
+ let (patch, ch) = take_num(rdr, rdr.read_char());
- ch = rdr.read_char();
- }
+ let mut pre = ~[];
+ let mut build = ~[];
- if buf == ~"" { return None; }
- else { Some((buf, ch)) }
+ let mut ch = ch;
+ if ch == '-' {
+ loop {
+ let (id, c) = take_ident(rdr, rdr.read_char());
+ pre.push(id);
+ ch = c;
+ if ch != '.' { break; }
+ }
}
- let ch = read_whitespace(rdr, rdr.read_char());
- let (major, ch) = match read_digits(rdr, ch) {
- None => return None,
- Some(item) => item
- };
-
- if ch != '.' { return None; }
-
- let (minor, ch) = match read_digits(rdr, rdr.read_char()) {
- None => return None,
- Some(item) => item
- };
-
- if ch != '.' { return None; }
-
- let (patch, ch) = match read_digits(rdr, rdr.read_char()) {
- None => return None,
- Some(item) => item
- };
- let (tag, ch) = if ch == '-' {
- match read_tag(rdr) {
- None => return None,
- Some((tag, ch)) => (Some(tag), ch)
+ if ch == '+' {
+ loop {
+ let (id, c) = take_ident(rdr, rdr.read_char());
+ build.push(id);
+ ch = c;
+ if ch != '.' { break; }
}
- } else {
- (None, ch)
- };
+ }
- Some((Version { major: major, minor: minor, patch: patch, tag: tag },
- ch))
+ Version {
+ major: major,
+ minor: minor,
+ patch: patch,
+ pre: pre,
+ build: build,
+ }
}
-pub fn parse(s: &str) -> Option<Version> {
- do io::with_str_reader(s) |rdr| {
- do parse_reader(rdr).chain_ref |&item| {
- let (version, ch) = item;
- if read_whitespace(rdr, ch) != -1 as char {
+pub fn parse(s: &str) -> Option<Version> {
+ if ! str::is_ascii(s) {
+ return None;
+ }
+ let s = s.trim();
+ let mut bad = false;
+ do bad_parse::cond.trap(|_| { debug!("bad"); bad = true }).in {
+ do io::with_str_reader(s) |rdr| {
+ let v = parse_reader(rdr);
+ if bad || v.to_str() != s {
None
} else {
- Some(version)
+ Some(v)
}
}
}
major: 1u,
minor: 2u,
patch: 3u,
- tag: None,
+ pre: ~[],
+ build: ~[],
});
assert parse(" 1.2.3 ") == Some(Version {
major: 1u,
minor: 2u,
patch: 3u,
- tag: None,
+ pre: ~[],
+ build: ~[],
});
assert parse("1.2.3-alpha1") == Some(Version {
major: 1u,
minor: 2u,
patch: 3u,
- tag: Some("alpha1")
+ pre: ~[AlphaNumeric(~"alpha1")],
+ build: ~[]
});
assert parse(" 1.2.3-alpha1 ") == Some(Version {
major: 1u,
minor: 2u,
patch: 3u,
- tag: Some("alpha1")
+ pre: ~[AlphaNumeric(~"alpha1")],
+ build: ~[]
});
+ assert parse("1.2.3+build5") == Some(Version {
+ major: 1u,
+ minor: 2u,
+ patch: 3u,
+ pre: ~[],
+ build: ~[AlphaNumeric(~"build5")]
+ });
+ assert parse(" 1.2.3+build5 ") == Some(Version {
+ major: 1u,
+ minor: 2u,
+ patch: 3u,
+ pre: ~[],
+ build: ~[AlphaNumeric(~"build5")]
+ });
+ assert parse("1.2.3-alpha1+build5") == Some(Version {
+ major: 1u,
+ minor: 2u,
+ patch: 3u,
+ pre: ~[AlphaNumeric(~"alpha1")],
+ build: ~[AlphaNumeric(~"build5")]
+ });
+ assert parse(" 1.2.3-alpha1+build5 ") == Some(Version {
+ major: 1u,
+ minor: 2u,
+ patch: 3u,
+ pre: ~[AlphaNumeric(~"alpha1")],
+ build: ~[AlphaNumeric(~"build5")]
+ });
+ assert parse("1.2.3-1.alpha1.9+build5.7.3aedf ") == Some(Version {
+ major: 1u,
+ minor: 2u,
+ patch: 3u,
+ pre: ~[Numeric(1),AlphaNumeric(~"alpha1"),Numeric(9)],
+ build: ~[AlphaNumeric(~"build5"),
+ Numeric(7),
+ AlphaNumeric(~"3aedf")]
+ });
+
}
#[test]
assert parse("0.0.0") < parse("1.2.3-alpha2");
assert parse("1.0.0") < parse("1.2.3-alpha2");
assert parse("1.2.0") < parse("1.2.3-alpha2");
- assert parse("1.2.3") < parse("1.2.3-alpha2");
+ assert parse("1.2.3-alpha1") < parse("1.2.3");
assert parse("1.2.3-alpha1") < parse("1.2.3-alpha2");
-
assert !(parse("1.2.3-alpha2") < parse("1.2.3-alpha2"));
}
assert parse("0.0.0") <= parse("1.2.3-alpha2");
assert parse("1.0.0") <= parse("1.2.3-alpha2");
assert parse("1.2.0") <= parse("1.2.3-alpha2");
- assert parse("1.2.3") <= parse("1.2.3-alpha2");
assert parse("1.2.3-alpha1") <= parse("1.2.3-alpha2");
assert parse("1.2.3-alpha2") <= parse("1.2.3-alpha2");
}
assert parse("1.2.3-alpha2") > parse("0.0.0");
assert parse("1.2.3-alpha2") > parse("1.0.0");
assert parse("1.2.3-alpha2") > parse("1.2.0");
- assert parse("1.2.3-alpha2") > parse("1.2.3");
assert parse("1.2.3-alpha2") > parse("1.2.3-alpha1");
-
+ assert parse("1.2.3") > parse("1.2.3-alpha2");
assert !(parse("1.2.3-alpha2") > parse("1.2.3-alpha2"));
}
assert parse("1.2.3-alpha2") >= parse("0.0.0");
assert parse("1.2.3-alpha2") >= parse("1.0.0");
assert parse("1.2.3-alpha2") >= parse("1.2.0");
- assert parse("1.2.3-alpha2") >= parse("1.2.3");
assert parse("1.2.3-alpha2") >= parse("1.2.3-alpha1");
assert parse("1.2.3-alpha2") >= parse("1.2.3-alpha2");
}
+
+#[test]
+fn test_spec_order() {
+
+ let vs = ["1.0.0-alpha",
+ "1.0.0-alpha.1",
+ "1.0.0-beta.2",
+ "1.0.0-beta.11",
+ "1.0.0-rc.1",
+ "1.0.0-rc.1+build.1",
+ "1.0.0",
+ "1.0.0+0.3.7",
+ "1.3.7+build",
+ "1.3.7+build.2.b8f12d7",
+ "1.3.7+build.11.e0f985a"];
+ let mut i = 1;
+ while i < vs.len() {
+ let a = parse(vs[i-1]).get();
+ let b = parse(vs[i]).get();
+ assert a < b;
+ i += 1;
+ }
+}
\ No newline at end of file