Start using core::path2::Path in a lot of places.

This commit is contained in:
Graydon Hoare 2012-08-24 15:28:43 -07:00
parent a8f1bee457
commit c284b8b1dc
43 changed files with 1139 additions and 1115 deletions

View file

@ -43,12 +43,12 @@ type source = @{
type cargo = { type cargo = {
pgp: bool, pgp: bool,
root: ~str, root: Path,
installdir: ~str, installdir: Path,
bindir: ~str, bindir: Path,
libdir: ~str, libdir: Path,
workdir: ~str, workdir: Path,
sourcedir: ~str, sourcedir: Path,
sources: map::hashmap<~str, source>, sources: map::hashmap<~str, source>,
mut current_install: ~str, mut current_install: ~str,
dep_cache: map::hashmap<~str, bool>, dep_cache: map::hashmap<~str, bool>,
@ -185,7 +185,7 @@ fn has_archive_extension(p: ~str) -> bool {
} }
fn is_archive_path(u: ~str) -> bool { fn is_archive_path(u: ~str) -> bool {
has_archive_extension(u) && os::path_exists(u) has_archive_extension(u) && os::path_exists(&Path(u))
} }
fn is_archive_url(u: ~str) -> bool { fn is_archive_url(u: ~str) -> bool {
@ -209,7 +209,7 @@ fn assume_source_method(url: ~str) -> ~str {
if is_git_url(url) { if is_git_url(url) {
return ~"git"; return ~"git";
} }
if str::starts_with(url, ~"file://") || os::path_exists(url) { if str::starts_with(url, ~"file://") || os::path_exists(&Path(url)) {
return ~"file"; return ~"file";
} }
@ -238,7 +238,7 @@ fn load_link(mis: ~[@ast::meta_item]) -> (option<~str>,
(name, vers, uuid) (name, vers, uuid)
} }
fn load_crate(filename: ~str) -> option<crate> { fn load_crate(filename: &Path) -> option<crate> {
let sess = parse::new_parse_sess(none); let sess = parse::new_parse_sess(none);
let c = parse::parse_crate_from_crate_file(filename, ~[], sess); let c = parse::parse_crate_from_crate_file(filename, ~[], sess);
@ -368,10 +368,10 @@ fn rest(s: ~str, start: uint) -> ~str {
} }
} }
fn need_dir(s: ~str) { fn need_dir(s: &Path) {
if os::path_is_dir(s) { return; } if os::path_is_dir(s) { return; }
if !os::make_dir(s, 493_i32 /* oct: 755 */) { if !os::make_dir(s, 493_i32 /* oct: 755 */) {
fail fmt!("can't make_dir %s", s); fail fmt!("can't make_dir %s", s.to_str());
} }
} }
@ -411,7 +411,7 @@ fn parse_source(name: ~str, j: json::json) -> source {
_ => none _ => none
}; };
if method == ~"file" { if method == ~"file" {
url = os::make_absolute(url); url = os::make_absolute(&Path(url)).to_str();
} }
return @{ return @{
name: name, name: name,
@ -425,7 +425,7 @@ fn parse_source(name: ~str, j: json::json) -> source {
}; };
} }
fn try_parse_sources(filename: ~str, sources: map::hashmap<~str, source>) { fn try_parse_sources(filename: &Path, sources: map::hashmap<~str, source>) {
if !os::path_exists(filename) { return; } if !os::path_exists(filename) { return; }
let c = io::read_whole_file_str(filename); let c = io::read_whole_file_str(filename);
match json::from_str(result::get(c)) { match json::from_str(result::get(c)) {
@ -436,7 +436,7 @@ fn try_parse_sources(filename: ~str, sources: map::hashmap<~str, source>) {
} }
} }
ok(_) => fail ~"malformed sources.json", ok(_) => fail ~"malformed sources.json",
err(e) => fail fmt!("%s:%s", filename, e.to_str()) err(e) => fail fmt!("%s:%s", filename.to_str(), e.to_str())
} }
} }
@ -543,10 +543,10 @@ fn load_one_source_package(src: source, p: map::hashmap<~str, json::json>) {
} }
fn load_source_info(c: cargo, src: source) { fn load_source_info(c: cargo, src: source) {
let dir = path::connect(c.sourcedir, src.name); let dir = c.sourcedir.push(src.name);
let srcfile = path::connect(dir, ~"source.json"); let srcfile = dir.push("source.json");
if !os::path_exists(srcfile) { return; } if !os::path_exists(&srcfile) { return; }
let srcstr = io::read_whole_file_str(srcfile); let srcstr = io::read_whole_file_str(&srcfile);
match json::from_str(result::get(srcstr)) { match json::from_str(result::get(srcstr)) {
ok(json::dict(s)) => { ok(json::dict(s)) => {
let o = parse_source(src.name, json::dict(s)); let o = parse_source(src.name, json::dict(s));
@ -565,10 +565,10 @@ fn load_source_info(c: cargo, src: source) {
} }
fn load_source_packages(c: cargo, src: source) { fn load_source_packages(c: cargo, src: source) {
log(debug, ~"loading source: " + src.name); log(debug, ~"loading source: " + src.name);
let dir = path::connect(c.sourcedir, src.name); let dir = c.sourcedir.push(src.name);
let pkgfile = path::connect(dir, ~"packages.json"); let pkgfile = dir.push("packages.json");
if !os::path_exists(pkgfile) { return; } if !os::path_exists(&pkgfile) { return; }
let pkgstr = io::read_whole_file_str(pkgfile); let pkgstr = io::read_whole_file_str(&pkgfile);
match json::from_str(result::get(pkgstr)) { match json::from_str(result::get(pkgstr)) {
ok(json::list(js)) => { ok(json::list(js)) => {
for (*js).each |j| { for (*js).each |j| {
@ -639,8 +639,8 @@ fn configure(opts: options) -> cargo {
let p = result::get(get_cargo_dir()); let p = result::get(get_cargo_dir());
let sources = map::str_hash(); let sources = map::str_hash();
try_parse_sources(path::connect(home, ~"sources.json"), sources); try_parse_sources(&home.push("sources.json"), sources);
try_parse_sources(path::connect(home, ~"local-sources.json"), sources); try_parse_sources(&home.push("local-sources.json"), sources);
let dep_cache = map::str_hash(); let dep_cache = map::str_hash();
@ -648,22 +648,22 @@ fn configure(opts: options) -> cargo {
pgp: pgp::supported(), pgp: pgp::supported(),
root: home, root: home,
installdir: p, installdir: p,
bindir: path::connect(p, ~"bin"), bindir: p.push("bin"),
libdir: path::connect(p, ~"lib"), libdir: p.push("lib"),
workdir: path::connect(p, ~"work"), workdir: p.push("work"),
sourcedir: path::connect(home, ~"sources"), sourcedir: home.push("sources"),
sources: sources, sources: sources,
mut current_install: ~"", mut current_install: ~"",
dep_cache: dep_cache, dep_cache: dep_cache,
opts: opts opts: opts
}; };
need_dir(c.root); need_dir(&c.root);
need_dir(c.installdir); need_dir(&c.installdir);
need_dir(c.sourcedir); need_dir(&c.sourcedir);
need_dir(c.workdir); need_dir(&c.workdir);
need_dir(c.libdir); need_dir(&c.libdir);
need_dir(c.bindir); need_dir(&c.bindir);
for sources.each_key |k| { for sources.each_key |k| {
let mut s = sources.get(k); let mut s = sources.get(k);
@ -672,7 +672,7 @@ fn configure(opts: options) -> cargo {
} }
if c.pgp { if c.pgp {
pgp::init(c.root); pgp::init(&c.root);
} else { } else {
warn(~"command `gpg` was not found"); warn(~"command `gpg` was not found");
warn(~"you have to install gpg from source " + warn(~"you have to install gpg from source " +
@ -694,22 +694,24 @@ fn for_each_package(c: cargo, b: fn(source, package)) {
} }
// Runs all programs in directory <buildpath> // Runs all programs in directory <buildpath>
fn run_programs(buildpath: ~str) { fn run_programs(buildpath: &Path) {
let newv = os::list_dir_path(buildpath); let newv = os::list_dir_path(buildpath);
for newv.each |ct| { for newv.each |ct| {
run::run_program(ct, ~[]); run::run_program(ct.to_str(), ~[]);
} }
} }
// Runs rustc in <path + subdir> with the given flags // Runs rustc in <path + subdir> with the given flags
// and returns <path + subdir> // and returns <patho + subdir>
fn run_in_buildpath(what: ~str, path: ~str, subdir: ~str, cf: ~str, fn run_in_buildpath(what: &str, path: &Path, subdir: &Path, cf: &Path,
extra_flags: ~[~str]) -> option<~str> { extra_flags: ~[~str]) -> option<Path> {
let buildpath = path::connect(path, subdir); let buildpath = path.push_rel(subdir);
need_dir(buildpath); need_dir(&buildpath);
debug!("%s: %s -> %s", what, cf, buildpath); debug!("%s: %s -> %s", what, cf.to_str(), buildpath.to_str());
let p = run::program_output(rustc_sysroot(), let p = run::program_output(rustc_sysroot(),
~[~"--out-dir", buildpath, cf] + extra_flags); ~[~"--out-dir",
buildpath.to_str(),
cf.to_str()] + extra_flags);
if p.status != 0 { if p.status != 0 {
error(fmt!("rustc failed: %d\n%s\n%s", p.status, p.err, p.out)); error(fmt!("rustc failed: %d\n%s\n%s", p.status, p.err, p.out));
return none; return none;
@ -717,37 +719,42 @@ fn run_in_buildpath(what: ~str, path: ~str, subdir: ~str, cf: ~str,
some(buildpath) some(buildpath)
} }
fn test_one_crate(_c: cargo, path: ~str, cf: ~str) { fn test_one_crate(_c: cargo, path: &Path, cf: &Path) {
let buildpath = match run_in_buildpath(~"testing", path, ~"/test", cf, let buildpath = match run_in_buildpath(~"testing", path,
~[ ~"--test"]) { &Path("test"),
cf,
~[ ~"--test"]) {
none => return, none => return,
some(bp) => bp some(bp) => bp
}; };
run_programs(buildpath); run_programs(&buildpath);
} }
fn install_one_crate(c: cargo, path: ~str, cf: ~str) { fn install_one_crate(c: cargo, path: &Path, cf: &Path) {
let buildpath = match run_in_buildpath(~"installing", path, let buildpath = match run_in_buildpath(~"installing", path,
~"/build", cf, ~[]) { &Path("build"),
cf, ~[]) {
none => return, none => return,
some(bp) => bp some(bp) => bp
}; };
let newv = os::list_dir_path(buildpath); let newv = os::list_dir_path(&buildpath);
let exec_suffix = os::exe_suffix(); let exec_suffix = os::exe_suffix();
for newv.each |ct| { for newv.each |ct| {
if (exec_suffix != ~"" && str::ends_with(ct, exec_suffix)) || if (exec_suffix != ~"" && str::ends_with(ct.to_str(),
(exec_suffix == ~"" && !str::starts_with(path::basename(ct), exec_suffix)) ||
~"lib")) { (exec_suffix == ~"" &&
debug!(" bin: %s", ct); !str::starts_with(option::get(ct.filename()),
install_to_dir(ct, c.bindir); ~"lib")) {
debug!(" bin: %s", ct.to_str());
install_to_dir(ct, &c.bindir);
if c.opts.mode == system_mode { if c.opts.mode == system_mode {
// FIXME (#2662): Put this file in PATH / symlink it so it can // FIXME (#2662): Put this file in PATH / symlink it so it can
// be used as a generic executable // be used as a generic executable
// `cargo install -G rustray` and `rustray file.obj` // `cargo install -G rustray` and `rustray file.obj`
} }
} else { } else {
debug!(" lib: %s", ct); debug!(" lib: %s", ct.to_str());
install_to_dir(ct, c.libdir); install_to_dir(ct, &c.libdir);
} }
} }
} }
@ -756,23 +763,22 @@ fn install_one_crate(c: cargo, path: ~str, cf: ~str) {
fn rustc_sysroot() -> ~str { fn rustc_sysroot() -> ~str {
match os::self_exe_path() { match os::self_exe_path() {
some(path) => { some(path) => {
let path = ~[path, ~"..", ~"bin", ~"rustc"]; let rustc = path.push_many([~"..", ~"bin", ~"rustc"]);
let rustc = path::normalize(path::connect_many(path)); debug!(" rustc: %s", rustc.to_str());
debug!(" rustc: %s", rustc); rustc.to_str()
rustc
} }
none => ~"rustc" none => ~"rustc"
} }
} }
fn install_source(c: cargo, path: ~str) { fn install_source(c: cargo, path: &Path) {
debug!("source: %s", path); debug!("source: %s", path.to_str());
os::change_dir(path); os::change_dir(path);
let mut cratefiles = ~[]; let mut cratefiles = ~[];
for os::walk_dir(~".") |p| { for os::walk_dir(&Path(".")) |p| {
if str::ends_with(p, ~".rc") { if p.filetype() == some(~"rc") {
vec::push(cratefiles, p); vec::push(cratefiles, *p);
} }
} }
@ -781,7 +787,7 @@ fn install_source(c: cargo, path: ~str) {
} }
for cratefiles.each |cf| { for cratefiles.each |cf| {
match load_crate(cf) { match load_crate(&cf) {
none => again, none => again,
some(crate) => { some(crate) => {
for crate.deps.each |query| { for crate.deps.each |query| {
@ -789,28 +795,23 @@ fn install_source(c: cargo, path: ~str) {
// (n.b. #1356 says "Cyclic dependency is an error // (n.b. #1356 says "Cyclic dependency is an error
// condition") // condition")
let wd_base = c.workdir + path::path_sep(); let wd = get_temp_workdir(c);
let wd = match tempfile::mkdtemp(wd_base, ~"") { install_query(c, &wd, query);
some(wd) => wd,
none => fail fmt!("needed temp dir: %s", wd_base)
};
install_query(c, wd, query);
} }
os::change_dir(path); os::change_dir(path);
if c.opts.test { if c.opts.test {
test_one_crate(c, path, cf); test_one_crate(c, path, &cf);
} }
install_one_crate(c, path, cf); install_one_crate(c, path, &cf);
} }
} }
} }
} }
fn install_git(c: cargo, wd: ~str, url: ~str, reference: option<~str>) { fn install_git(c: cargo, wd: &Path, url: ~str, reference: option<~str>) {
run::program_output(~"git", ~[~"clone", url, wd]); run::program_output(~"git", ~[~"clone", url, wd.to_str()]);
if option::is_some(reference) { if option::is_some(reference) {
let r = option::get(reference); let r = option::get(reference);
os::change_dir(wd); os::change_dir(wd);
@ -820,25 +821,27 @@ fn install_git(c: cargo, wd: ~str, url: ~str, reference: option<~str>) {
install_source(c, wd); install_source(c, wd);
} }
fn install_curl(c: cargo, wd: ~str, url: ~str) { fn install_curl(c: cargo, wd: &Path, url: ~str) {
let tarpath = path::connect(wd, ~"pkg.tar"); let tarpath = wd.push("pkg.tar");
let p = run::program_output(~"curl", ~[~"-f", ~"-s", ~"-o", let p = run::program_output(~"curl", ~[~"-f", ~"-s", ~"-o",
tarpath, url]); tarpath.to_str(), url]);
if p.status != 0 { if p.status != 0 {
fail fmt!("fetch of %s failed: %s", url, p.err); fail fmt!("fetch of %s failed: %s", url, p.err);
} }
run::run_program(~"tar", ~[~"-x", ~"--strip-components=1", run::run_program(~"tar", ~[~"-x", ~"--strip-components=1",
~"-C", wd, ~"-f", tarpath]); ~"-C", wd.to_str(),
~"-f", tarpath.to_str()]);
install_source(c, wd); install_source(c, wd);
} }
fn install_file(c: cargo, wd: ~str, path: ~str) { fn install_file(c: cargo, wd: &Path, path: &Path) {
run::program_output(~"tar", ~[~"-x", ~"--strip-components=1", run::program_output(~"tar", ~[~"-x", ~"--strip-components=1",
~"-C", wd, ~"-f", path]); ~"-C", wd.to_str(),
~"-f", path.to_str()]);
install_source(c, wd); install_source(c, wd);
} }
fn install_package(c: cargo, src: ~str, wd: ~str, pkg: package) { fn install_package(c: cargo, src: ~str, wd: &Path, pkg: package) {
let url = copy pkg.url; let url = copy pkg.url;
let method = match pkg.method { let method = match pkg.method {
~"git" => ~"git", ~"git" => ~"git",
@ -850,7 +853,7 @@ fn install_package(c: cargo, src: ~str, wd: ~str, pkg: package) {
match method { match method {
~"git" => install_git(c, wd, url, copy pkg.reference), ~"git" => install_git(c, wd, url, copy pkg.reference),
~"file" => install_file(c, wd, url), ~"file" => install_file(c, wd, &Path(url)),
~"curl" => install_curl(c, wd, copy url), ~"curl" => install_curl(c, wd, copy url),
_ => () _ => ()
} }
@ -866,7 +869,7 @@ fn cargo_suggestion(c: cargo, fallback: fn())
fallback(); fallback();
} }
fn install_uuid(c: cargo, wd: ~str, uuid: ~str) { fn install_uuid(c: cargo, wd: &Path, uuid: ~str) {
let mut ps = ~[]; let mut ps = ~[];
for_each_package(c, |s, p| { for_each_package(c, |s, p| {
if p.uuid == uuid { if p.uuid == uuid {
@ -890,7 +893,7 @@ fn install_uuid(c: cargo, wd: ~str, uuid: ~str) {
} }
} }
fn install_named(c: cargo, wd: ~str, name: ~str) { fn install_named(c: cargo, wd: &Path, name: ~str) {
let mut ps = ~[]; let mut ps = ~[];
for_each_package(c, |s, p| { for_each_package(c, |s, p| {
if p.name == name { if p.name == name {
@ -914,7 +917,7 @@ fn install_named(c: cargo, wd: ~str, name: ~str) {
} }
} }
fn install_uuid_specific(c: cargo, wd: ~str, src: ~str, uuid: ~str) { fn install_uuid_specific(c: cargo, wd: &Path, src: ~str, uuid: ~str) {
match c.sources.find(src) { match c.sources.find(src) {
some(s) => { some(s) => {
let packages = copy s.packages; let packages = copy s.packages;
@ -930,7 +933,7 @@ fn install_uuid_specific(c: cargo, wd: ~str, src: ~str, uuid: ~str) {
error(~"can't find package: " + src + ~"/" + uuid); error(~"can't find package: " + src + ~"/" + uuid);
} }
fn install_named_specific(c: cargo, wd: ~str, src: ~str, name: ~str) { fn install_named_specific(c: cargo, wd: &Path, src: ~str, name: ~str) {
match c.sources.find(src) { match c.sources.find(src) {
some(s) => { some(s) => {
let packages = copy s.packages; let packages = copy s.packages;
@ -952,59 +955,45 @@ fn cmd_uninstall(c: cargo) {
return; return;
} }
let lib = c.libdir; let lib = &c.libdir;
let bin = c.bindir; let bin = &c.bindir;
let target = c.opts.free[2u]; let target = c.opts.free[2u];
// FIXME (#2662): needs stronger pattern matching // FIXME (#2662): needs stronger pattern matching
// FIXME (#2662): needs to uninstall from a specified location in a // FIXME (#2662): needs to uninstall from a specified location in a
// cache instead of looking for it (binaries can be uninstalled by // cache instead of looking for it (binaries can be uninstalled by
// name only) // name only)
fn try_uninstall(p: &Path) -> bool {
if os::remove_file(p) {
info(~"uninstalled: '" + p.to_str() + ~"'");
true
} else {
error(~"could not uninstall: '" +
p.to_str() + ~"'");
false
}
}
if is_uuid(target) { if is_uuid(target) {
for os::list_dir(lib).each |file| { for os::list_dir(lib).each |file| {
match str::find_str(file, ~"-" + target + ~"-") { match str::find_str(file, ~"-" + target + ~"-") {
some(idx) => { some(_) => if !try_uninstall(&lib.push(file)) { return },
let full = path::normalize(path::connect(lib, file)); none => ()
if os::remove_file(full) {
info(~"uninstalled: '" + full + ~"'");
} else {
error(~"could not uninstall: '" + full + ~"'");
}
return;
}
none => again
} }
} }
error(~"can't find package with uuid: " + target); error(~"can't find package with uuid: " + target);
} else { } else {
for os::list_dir(lib).each |file| { for os::list_dir(lib).each |file| {
match str::find_str(file, ~"lib" + target + ~"-") { match str::find_str(file, ~"lib" + target + ~"-") {
some(idx) => { some(_) => if !try_uninstall(&lib.push(file)) { return },
let full = path::normalize(path::connect(lib, none => ()
file));
if os::remove_file(full) {
info(~"uninstalled: '" + full + ~"'");
} else {
error(~"could not uninstall: '" + full + ~"'");
}
return;
}
none => again
} }
} }
for os::list_dir(bin).each |file| { for os::list_dir(bin).each |file| {
match str::find_str(file, target) { match str::find_str(file, target) {
some(idx) => { some(_) => if !try_uninstall(&lib.push(file)) { return },
let full = path::normalize(path::connect(bin, file)); none => ()
if os::remove_file(full) {
info(~"uninstalled: '" + full + ~"'");
} else {
error(~"could not uninstall: '" + full + ~"'");
}
return;
}
none => again
} }
} }
@ -1012,7 +1001,7 @@ fn cmd_uninstall(c: cargo) {
} }
} }
fn install_query(c: cargo, wd: ~str, target: ~str) { fn install_query(c: cargo, wd: &Path, target: ~str) {
match c.dep_cache.find(target) { match c.dep_cache.find(target) {
some(inst) => { some(inst) => {
if inst { if inst {
@ -1025,7 +1014,7 @@ fn install_query(c: cargo, wd: ~str, target: ~str) {
c.dep_cache.insert(target, true); c.dep_cache.insert(target, true);
if is_archive_path(target) { if is_archive_path(target) {
install_file(c, wd, target); install_file(c, wd, &Path(target));
return; return;
} else if is_git_url(target) { } else if is_git_url(target) {
let reference = if c.opts.free.len() >= 4u { let reference = if c.opts.free.len() >= 4u {
@ -1072,31 +1061,36 @@ fn install_query(c: cargo, wd: ~str, target: ~str) {
} }
} }
fn get_temp_workdir(c: cargo) -> Path {
match tempfile::mkdtemp(&c.workdir, "cargo") {
some(wd) => wd,
none => fail fmt!("needed temp dir: %s",
c.workdir.to_str())
}
}
fn cmd_install(c: cargo) unsafe { fn cmd_install(c: cargo) unsafe {
let wd_base = c.workdir + path::path_sep(); let wd = get_temp_workdir(c);
let wd = match tempfile::mkdtemp(wd_base, ~"") {
some(wd) => wd,
none => fail fmt!("needed temp dir: %s", wd_base)
};
if vec::len(c.opts.free) == 2u { if vec::len(c.opts.free) == 2u {
let cwd = os::getcwd(); let cwd = os::getcwd();
let status = run::run_program(~"cp", ~[~"-R", cwd, wd]); let status = run::run_program(~"cp", ~[~"-R", cwd.to_str(),
wd.to_str()]);
if status != 0 { if status != 0 {
fail fmt!("could not copy directory: %s", cwd); fail fmt!("could not copy directory: %s", cwd.to_str());
} }
install_source(c, wd); install_source(c, &wd);
return; return;
} }
sync(c); sync(c);
let query = c.opts.free[2]; let query = c.opts.free[2];
c.current_install = copy query; c.current_install = query.to_str();
install_query(c, wd, copy query); install_query(c, &wd, query);
} }
fn sync(c: cargo) { fn sync(c: cargo) {
@ -1107,45 +1101,47 @@ fn sync(c: cargo) {
} }
} }
fn sync_one_file(c: cargo, dir: ~str, src: source) -> bool { fn sync_one_file(c: cargo, dir: &Path, src: source) -> bool {
let name = src.name; let name = src.name;
let srcfile = path::connect(dir, ~"source.json.new"); let srcfile = dir.push("source.json.new");
let destsrcfile = path::connect(dir, ~"source.json"); let destsrcfile = dir.push("source.json");
let pkgfile = path::connect(dir, ~"packages.json.new"); let pkgfile = dir.push("packages.json.new");
let destpkgfile = path::connect(dir, ~"packages.json"); let destpkgfile = dir.push("packages.json");
let keyfile = path::connect(dir, ~"key.gpg"); let keyfile = dir.push("key.gpg");
let srcsigfile = path::connect(dir, ~"source.json.sig"); let srcsigfile = dir.push("source.json.sig");
let sigfile = path::connect(dir, ~"packages.json.sig"); let sigfile = dir.push("packages.json.sig");
let url = src.url; let url = Path(src.url);
let mut has_src_file = false; let mut has_src_file = false;
if !os::copy_file(path::connect(url, ~"packages.json"), pkgfile) { if !os::copy_file(&url.push("packages.json"), &pkgfile) {
error(fmt!("fetch for source %s (url %s) failed", name, url)); error(fmt!("fetch for source %s (url %s) failed",
name, url.to_str()));
return false; return false;
} }
if os::copy_file(path::connect(url, ~"source.json"), srcfile) { if os::copy_file(&url.push("source.json"), &srcfile) {
has_src_file = false; has_src_file = false;
} }
os::copy_file(path::connect(url, ~"source.json.sig"), srcsigfile); os::copy_file(&url.push("source.json.sig"), &srcsigfile);
os::copy_file(path::connect(url, ~"packages.json.sig"), sigfile); os::copy_file(&url.push("packages.json.sig"), &sigfile);
match copy src.key { match copy src.key {
some(u) => { some(u) => {
let p = run::program_output(~"curl", let p = run::program_output(~"curl",
~[~"-f", ~"-s", ~"-o", keyfile, u]); ~[~"-f", ~"-s",
~"-o", keyfile.to_str(), u]);
if p.status != 0 { if p.status != 0 {
error(fmt!("fetch for source %s (key %s) failed", name, u)); error(fmt!("fetch for source %s (key %s) failed", name, u));
return false; return false;
} }
pgp::add(c.root, keyfile); pgp::add(&c.root, &keyfile);
} }
_ => () _ => ()
} }
match (src.key, src.keyfp) { match (src.key, src.keyfp) {
(some(_), some(f)) => { (some(_), some(f)) => {
let r = pgp::verify(c.root, pkgfile, sigfile, f); let r = pgp::verify(&c.root, &pkgfile, &sigfile, f);
if !r { if !r {
error(fmt!("signature verification failed for source %s", error(fmt!("signature verification failed for source %s",
@ -1154,7 +1150,7 @@ fn sync_one_file(c: cargo, dir: ~str, src: source) -> bool {
} }
if has_src_file { if has_src_file {
let e = pgp::verify(c.root, srcfile, srcsigfile, f); let e = pgp::verify(&c.root, &srcfile, &srcsigfile, f);
if !e { if !e {
error(fmt!("signature verification failed for source %s", error(fmt!("signature verification failed for source %s",
@ -1166,33 +1162,33 @@ fn sync_one_file(c: cargo, dir: ~str, src: source) -> bool {
_ => () _ => ()
} }
copy_warn(pkgfile, destpkgfile); copy_warn(&pkgfile, &destpkgfile);
if has_src_file { if has_src_file {
copy_warn(srcfile, destsrcfile); copy_warn(&srcfile, &destsrcfile);
} }
os::remove_file(keyfile); os::remove_file(&keyfile);
os::remove_file(srcfile); os::remove_file(&srcfile);
os::remove_file(srcsigfile); os::remove_file(&srcsigfile);
os::remove_file(pkgfile); os::remove_file(&pkgfile);
os::remove_file(sigfile); os::remove_file(&sigfile);
info(fmt!("synced source: %s", name)); info(fmt!("synced source: %s", name));
return true; return true;
} }
fn sync_one_git(c: cargo, dir: ~str, src: source) -> bool { fn sync_one_git(c: cargo, dir: &Path, src: source) -> bool {
let name = src.name; let name = src.name;
let srcfile = path::connect(dir, ~"source.json"); let srcfile = dir.push("source.json");
let pkgfile = path::connect(dir, ~"packages.json"); let pkgfile = dir.push("packages.json");
let keyfile = path::connect(dir, ~"key.gpg"); let keyfile = dir.push("key.gpg");
let srcsigfile = path::connect(dir, ~"source.json.sig"); let srcsigfile = dir.push("source.json.sig");
let sigfile = path::connect(dir, ~"packages.json.sig"); let sigfile = dir.push("packages.json.sig");
let url = src.url; let url = src.url;
fn rollback(name: ~str, dir: ~str, insecure: bool) { fn rollback(name: ~str, dir: &Path, insecure: bool) {
fn msg(name: ~str, insecure: bool) { fn msg(name: ~str, insecure: bool) {
error(fmt!("could not rollback source: %s", name)); error(fmt!("could not rollback source: %s", name));
@ -1216,8 +1212,8 @@ fn sync_one_git(c: cargo, dir: ~str, src: source) -> bool {
} }
} }
if !os::path_exists(path::connect(dir, ~".git")) { if !os::path_exists(&dir.push(".git")) {
let p = run::program_output(~"git", ~[~"clone", url, dir]); let p = run::program_output(~"git", ~[~"clone", url, dir.to_str()]);
if p.status != 0 { if p.status != 0 {
error(fmt!("fetch for source %s (url %s) failed", name, url)); error(fmt!("fetch for source %s (url %s) failed", name, url));
@ -1238,24 +1234,25 @@ fn sync_one_git(c: cargo, dir: ~str, src: source) -> bool {
} }
} }
let has_src_file = os::path_exists(srcfile); let has_src_file = os::path_exists(&srcfile);
match copy src.key { match copy src.key {
some(u) => { some(u) => {
let p = run::program_output(~"curl", let p = run::program_output(~"curl",
~[~"-f", ~"-s", ~"-o", keyfile, u]); ~[~"-f", ~"-s",
~"-o", keyfile.to_str(), u]);
if p.status != 0 { if p.status != 0 {
error(fmt!("fetch for source %s (key %s) failed", name, u)); error(fmt!("fetch for source %s (key %s) failed", name, u));
rollback(name, dir, false); rollback(name, dir, false);
return false; return false;
} }
pgp::add(c.root, keyfile); pgp::add(&c.root, &keyfile);
} }
_ => () _ => ()
} }
match (src.key, src.keyfp) { match (src.key, src.keyfp) {
(some(_), some(f)) => { (some(_), some(f)) => {
let r = pgp::verify(c.root, pkgfile, sigfile, f); let r = pgp::verify(&c.root, &pkgfile, &sigfile, f);
if !r { if !r {
error(fmt!("signature verification failed for source %s", error(fmt!("signature verification failed for source %s",
@ -1265,7 +1262,7 @@ fn sync_one_git(c: cargo, dir: ~str, src: source) -> bool {
} }
if has_src_file { if has_src_file {
let e = pgp::verify(c.root, srcfile, srcsigfile, f); let e = pgp::verify(&c.root, &srcfile, &srcsigfile, f);
if !e { if !e {
error(fmt!("signature verification failed for source %s", error(fmt!("signature verification failed for source %s",
@ -1278,22 +1275,22 @@ fn sync_one_git(c: cargo, dir: ~str, src: source) -> bool {
_ => () _ => ()
} }
os::remove_file(keyfile); os::remove_file(&keyfile);
info(fmt!("synced source: %s", name)); info(fmt!("synced source: %s", name));
return true; return true;
} }
fn sync_one_curl(c: cargo, dir: ~str, src: source) -> bool { fn sync_one_curl(c: cargo, dir: &Path, src: source) -> bool {
let name = src.name; let name = src.name;
let srcfile = path::connect(dir, ~"source.json.new"); let srcfile = dir.push("source.json.new");
let destsrcfile = path::connect(dir, ~"source.json"); let destsrcfile = dir.push("source.json");
let pkgfile = path::connect(dir, ~"packages.json.new"); let pkgfile = dir.push("packages.json.new");
let destpkgfile = path::connect(dir, ~"packages.json"); let destpkgfile = dir.push("packages.json");
let keyfile = path::connect(dir, ~"key.gpg"); let keyfile = dir.push("key.gpg");
let srcsigfile = path::connect(dir, ~"source.json.sig"); let srcsigfile = dir.push("source.json.sig");
let sigfile = path::connect(dir, ~"packages.json.sig"); let sigfile = dir.push("packages.json.sig");
let mut url = src.url; let mut url = src.url;
let smart = !str::ends_with(src.url, ~"packages.json"); let smart = !str::ends_with(src.url, ~"packages.json");
let mut has_src_file = false; let mut has_src_file = false;
@ -1303,7 +1300,8 @@ fn sync_one_curl(c: cargo, dir: ~str, src: source) -> bool {
} }
let p = run::program_output(~"curl", let p = run::program_output(~"curl",
~[~"-f", ~"-s", ~"-o", pkgfile, url]); ~[~"-f", ~"-s",
~"-o", pkgfile.to_str(), url]);
if p.status != 0 { if p.status != 0 {
error(fmt!("fetch for source %s (url %s) failed", name, url)); error(fmt!("fetch for source %s (url %s) failed", name, url));
@ -1313,7 +1311,8 @@ fn sync_one_curl(c: cargo, dir: ~str, src: source) -> bool {
url = src.url + ~"/source.json"; url = src.url + ~"/source.json";
let p = let p =
run::program_output(~"curl", run::program_output(~"curl",
~[~"-f", ~"-s", ~"-o", srcfile, url]); ~[~"-f", ~"-s",
~"-o", srcfile.to_str(), url]);
if p.status == 0 { if p.status == 0 {
has_src_file = true; has_src_file = true;
@ -1323,12 +1322,13 @@ fn sync_one_curl(c: cargo, dir: ~str, src: source) -> bool {
match copy src.key { match copy src.key {
some(u) => { some(u) => {
let p = run::program_output(~"curl", let p = run::program_output(~"curl",
~[~"-f", ~"-s", ~"-o", keyfile, u]); ~[~"-f", ~"-s",
~"-o", keyfile.to_str(), u]);
if p.status != 0 { if p.status != 0 {
error(fmt!("fetch for source %s (key %s) failed", name, u)); error(fmt!("fetch for source %s (key %s) failed", name, u));
return false; return false;
} }
pgp::add(c.root, keyfile); pgp::add(&c.root, &keyfile);
} }
_ => () _ => ()
} }
@ -1341,14 +1341,15 @@ fn sync_one_curl(c: cargo, dir: ~str, src: source) -> bool {
url = src.url + ~".sig"; url = src.url + ~".sig";
} }
let mut p = run::program_output(~"curl", ~[~"-f", ~"-s", ~"-o", let mut p = run::program_output(~"curl",
sigfile, url]); ~[~"-f", ~"-s", ~"-o",
sigfile.to_str(), url]);
if p.status != 0 { if p.status != 0 {
error(fmt!("fetch for source %s (sig %s) failed", name, url)); error(fmt!("fetch for source %s (sig %s) failed", name, url));
return false; return false;
} }
let r = pgp::verify(c.root, pkgfile, sigfile, f); let r = pgp::verify(&c.root, &pkgfile, &sigfile, f);
if !r { if !r {
error(fmt!("signature verification failed for source %s", error(fmt!("signature verification failed for source %s",
@ -1361,14 +1362,14 @@ fn sync_one_curl(c: cargo, dir: ~str, src: source) -> bool {
p = run::program_output(~"curl", p = run::program_output(~"curl",
~[~"-f", ~"-s", ~"-o", ~[~"-f", ~"-s", ~"-o",
srcsigfile, url]); srcsigfile.to_str(), url]);
if p.status != 0 { if p.status != 0 {
error(fmt!("fetch for source %s (sig %s) failed", error(fmt!("fetch for source %s (sig %s) failed",
name, url)); name, url));
return false; return false;
} }
let e = pgp::verify(c.root, srcfile, srcsigfile, f); let e = pgp::verify(&c.root, &srcfile, &srcsigfile, f);
if !e { if !e {
error(~"signature verification failed for " + error(~"signature verification failed for " +
@ -1380,17 +1381,17 @@ fn sync_one_curl(c: cargo, dir: ~str, src: source) -> bool {
_ => () _ => ()
} }
copy_warn(pkgfile, destpkgfile); copy_warn(&pkgfile, &destpkgfile);
if smart && has_src_file { if smart && has_src_file {
copy_warn(srcfile, destsrcfile); copy_warn(&srcfile, &destsrcfile);
} }
os::remove_file(keyfile); os::remove_file(&keyfile);
os::remove_file(srcfile); os::remove_file(&srcfile);
os::remove_file(srcsigfile); os::remove_file(&srcsigfile);
os::remove_file(pkgfile); os::remove_file(&pkgfile);
os::remove_file(sigfile); os::remove_file(&sigfile);
info(fmt!("synced source: %s", name)); info(fmt!("synced source: %s", name));
@ -1399,16 +1400,16 @@ fn sync_one_curl(c: cargo, dir: ~str, src: source) -> bool {
fn sync_one(c: cargo, src: source) { fn sync_one(c: cargo, src: source) {
let name = src.name; let name = src.name;
let dir = path::connect(c.sourcedir, name); let dir = c.sourcedir.push(name);
info(fmt!("syncing source: %s...", name)); info(fmt!("syncing source: %s...", name));
need_dir(dir); need_dir(&dir);
let result = match src.method { let result = match src.method {
~"git" => sync_one_git(c, dir, src), ~"git" => sync_one_git(c, &dir, src),
~"file" => sync_one_file(c, dir, src), ~"file" => sync_one_file(c, &dir, src),
_ => sync_one_curl(c, dir, src) _ => sync_one_curl(c, &dir, src)
}; };
if result { if result {
@ -1421,35 +1422,39 @@ fn cmd_init(c: cargo) {
let srcurl = ~"http://www.rust-lang.org/cargo/sources.json"; let srcurl = ~"http://www.rust-lang.org/cargo/sources.json";
let sigurl = ~"http://www.rust-lang.org/cargo/sources.json.sig"; let sigurl = ~"http://www.rust-lang.org/cargo/sources.json.sig";
let srcfile = path::connect(c.root, ~"sources.json.new"); let srcfile = c.root.push("sources.json.new");
let sigfile = path::connect(c.root, ~"sources.json.sig"); let sigfile = c.root.push("sources.json.sig");
let destsrcfile = path::connect(c.root, ~"sources.json"); let destsrcfile = c.root.push("sources.json");
let p = let p =
run::program_output(~"curl", ~[~"-f", ~"-s", ~"-o", srcfile, srcurl]); run::program_output(~"curl", ~[~"-f", ~"-s",
~"-o", srcfile.to_str(), srcurl]);
if p.status != 0 { if p.status != 0 {
error(fmt!("fetch of sources.json failed: %s", p.out)); error(fmt!("fetch of sources.json failed: %s", p.out));
return; return;
} }
let p = let p =
run::program_output(~"curl", ~[~"-f", ~"-s", ~"-o", sigfile, sigurl]); run::program_output(~"curl", ~[~"-f", ~"-s",
~"-o", sigfile.to_str(), sigurl]);
if p.status != 0 { if p.status != 0 {
error(fmt!("fetch of sources.json.sig failed: %s", p.out)); error(fmt!("fetch of sources.json.sig failed: %s", p.out));
return; return;
} }
let r = pgp::verify(c.root, srcfile, sigfile, pgp::signing_key_fp()); let r = pgp::verify(&c.root, &srcfile, &sigfile,
pgp::signing_key_fp());
if !r { if !r {
error(fmt!("signature verification failed for '%s'", srcfile)); error(fmt!("signature verification failed for '%s'",
srcfile.to_str()));
return; return;
} }
copy_warn(srcfile, destsrcfile); copy_warn(&srcfile, &destsrcfile);
os::remove_file(srcfile); os::remove_file(&srcfile);
os::remove_file(sigfile); os::remove_file(&sigfile);
info(fmt!("initialized .cargo in %s", c.root)); info(fmt!("initialized .cargo in %s", c.root.to_str()));
} }
fn print_pkg(s: source, p: package) { fn print_pkg(s: source, p: package) {
@ -1530,25 +1535,26 @@ fn cmd_search(c: cargo) {
info(fmt!("found %d packages", n)); info(fmt!("found %d packages", n));
} }
fn install_to_dir(srcfile: ~str, destdir: ~str) { fn install_to_dir(srcfile: &Path, destdir: &Path) {
let newfile = path::connect(destdir, path::basename(srcfile)); let newfile = destdir.push(option::get(srcfile.filename()));
let status = run::run_program(~"cp", ~[~"-r", srcfile, newfile]); let status = run::run_program(~"cp", ~[~"-r", srcfile.to_str(),
newfile.to_str()]);
if status == 0 { if status == 0 {
info(fmt!("installed: '%s'", newfile)); info(fmt!("installed: '%s'", newfile.to_str()));
} else { } else {
error(fmt!("could not install: '%s'", newfile)); error(fmt!("could not install: '%s'", newfile.to_str()));
} }
} }
fn dump_cache(c: cargo) { fn dump_cache(c: cargo) {
need_dir(c.root); need_dir(&c.root);
let out = path::connect(c.root, ~"cache.json"); let out = c.root.push("cache.json");
let _root = json::dict(map::str_hash()); let _root = json::dict(map::str_hash());
if os::path_exists(out) { if os::path_exists(&out) {
copy_warn(out, path::connect(c.root, ~"cache.json.old")); copy_warn(&out, &c.root.push("cache.json.old"));
} }
} }
fn dump_sources(c: cargo) { fn dump_sources(c: cargo) {
@ -1556,15 +1562,15 @@ fn dump_sources(c: cargo) {
return; return;
} }
need_dir(c.root); need_dir(&c.root);
let out = path::connect(c.root, ~"sources.json"); let out = c.root.push("sources.json");
if os::path_exists(out) { if os::path_exists(&out) {
copy_warn(out, path::connect(c.root, ~"sources.json.old")); copy_warn(&out, &c.root.push("sources.json.old"));
} }
match io::buffered_file_writer(out) { match io::buffered_file_writer(&out) {
result::ok(writer) => { result::ok(writer) => {
let hash = map::str_hash(); let hash = map::str_hash();
let root = json::dict(hash); let root = json::dict(hash);
@ -1600,9 +1606,10 @@ fn dump_sources(c: cargo) {
} }
} }
fn copy_warn(srcfile: ~str, destfile: ~str) { fn copy_warn(srcfile: &Path, destfile: &Path) {
if !os::copy_file(srcfile, destfile) { if !os::copy_file(srcfile, destfile) {
warn(fmt!("copying %s to %s failed", srcfile, destfile)); warn(fmt!("copying %s to %s failed",
srcfile.to_str(), destfile.to_str()));
} }
} }
@ -1894,7 +1901,7 @@ fn main(argv: ~[~str]) {
let mut c = configure(o); let mut c = configure(o);
let home = c.root; let home = c.root;
let first_time = os::path_exists(path::connect(home, ~"sources.json")); let first_time = os::path_exists(&home.push("sources.json"));
if !first_time && o.free[1] != ~"init" { if !first_time && o.free[1] != ~"init" {
cmd_init(c); cmd_init(c);

View file

@ -63,11 +63,13 @@ fn supported() -> bool {
r.status == 0 r.status == 0
} }
fn init(root: ~str) { fn init(root: &Path) {
let p = path::connect(root, ~"gpg"); let p = root.push("gpg");
if !os::path_is_dir(p) { if !os::path_is_dir(&p) {
os::make_dir(p, 0x1c0i32); os::make_dir(&p, 0x1c0i32);
let p = run::start_program(~"gpg", ~[~"--homedir", p, ~"--import"]); let p = run::start_program(~"gpg", ~[~"--homedir",
p.to_str(),
~"--import"]);
p.input().write_str(signing_key()); p.input().write_str(signing_key());
let s = p.finish(); let s = p.finish();
if s != 0 { if s != 0 {
@ -76,19 +78,22 @@ fn init(root: ~str) {
} }
} }
fn add(root: ~str, key: ~str) { fn add(root: &Path, key: &Path) {
let path = path::connect(root, ~"gpg"); let path = root.push("gpg");
let p = let p =
run::program_output(~"gpg", ~[~"--homedir", path, ~"--import", key]); run::program_output(~"gpg", ~[~"--homedir", path.to_str(),
~"--import", key.to_str()]);
if p.status != 0 { if p.status != 0 {
fail ~"pgp add failed: " + p.out; fail ~"pgp add failed: " + p.out;
} }
} }
fn verify(root: ~str, data: ~str, sig: ~str, keyfp: ~str) -> bool { fn verify(root: &Path, data: &Path, sig: &Path, keyfp: ~str) -> bool {
let path = path::connect(root, ~"gpg"); let path = root.push("gpg");
let p = gpg(~[~"--homedir", path, ~"--with-fingerprint", ~"--verify", sig, let p = gpg(~[~"--homedir", path.to_str(),
data]); ~"--with-fingerprint",
~"--verify", sig.to_str(),
data.to_str()]);
let res = ~"Primary key fingerprint: " + keyfp; let res = ~"Primary key fingerprint: " + keyfp;
for str::split_char(p.err, '\n').each |line| { for str::split_char(p.err, '\n').each |line| {
if line == res { return true; } if line == res { return true; }

View file

@ -10,16 +10,16 @@ type config = {
run_lib_path: ~str, run_lib_path: ~str,
// The rustc executable // The rustc executable
rustc_path: ~str, rustc_path: Path,
// The directory containing the tests to run // The directory containing the tests to run
src_base: ~str, src_base: Path,
// The directory where programs should be built // The directory where programs should be built
build_base: ~str, build_base: Path,
// Directory for auxiliary libraries // Directory for auxiliary libraries
aux_base: ~str, aux_base: Path,
// The name of the stage being built (stage1, etc) // The name of the stage being built (stage1, etc)
stage_id: ~str, stage_id: ~str,
@ -34,7 +34,7 @@ type config = {
filter: option<~str>, filter: option<~str>,
// Write out a parseable log of tests that were run // Write out a parseable log of tests that were run
logfile: option<~str>, logfile: option<Path>,
// A command line to prefix program execution with, // A command line to prefix program execution with,
// for running under valgrind // for running under valgrind

View file

@ -42,12 +42,16 @@ fn parse_config(args: ~[~str]) -> config {
err(f) => fail getopts::fail_str(f) err(f) => fail getopts::fail_str(f)
}; };
fn opt_path(m: getopts::matches, nm: ~str) -> Path {
Path(getopts::opt_str(m, nm))
}
return {compile_lib_path: getopts::opt_str(matches, ~"compile-lib-path"), return {compile_lib_path: getopts::opt_str(matches, ~"compile-lib-path"),
run_lib_path: getopts::opt_str(matches, ~"run-lib-path"), run_lib_path: getopts::opt_str(matches, ~"run-lib-path"),
rustc_path: getopts::opt_str(matches, ~"rustc-path"), rustc_path: opt_path(matches, ~"rustc-path"),
src_base: getopts::opt_str(matches, ~"src-base"), src_base: opt_path(matches, ~"src-base"),
build_base: getopts::opt_str(matches, ~"build-base"), build_base: opt_path(matches, ~"build-base"),
aux_base: getopts::opt_str(matches, ~"aux-base"), aux_base: opt_path(matches, ~"aux-base"),
stage_id: getopts::opt_str(matches, ~"stage-id"), stage_id: getopts::opt_str(matches, ~"stage-id"),
mode: str_mode(getopts::opt_str(matches, ~"mode")), mode: str_mode(getopts::opt_str(matches, ~"mode")),
run_ignored: getopts::opt_present(matches, ~"ignored"), run_ignored: getopts::opt_present(matches, ~"ignored"),
@ -55,7 +59,9 @@ fn parse_config(args: ~[~str]) -> config {
if vec::len(matches.free) > 0u { if vec::len(matches.free) > 0u {
option::some(matches.free[0]) option::some(matches.free[0])
} else { option::none }, } else { option::none },
logfile: getopts::opt_maybe_str(matches, ~"logfile"), logfile: option::map(getopts::opt_maybe_str(matches,
~"logfile"),
|s| Path(s)),
runtool: getopts::opt_maybe_str(matches, ~"runtool"), runtool: getopts::opt_maybe_str(matches, ~"runtool"),
rustcflags: getopts::opt_maybe_str(matches, ~"rustcflags"), rustcflags: getopts::opt_maybe_str(matches, ~"rustcflags"),
verbose: getopts::opt_present(matches, ~"verbose")}; verbose: getopts::opt_present(matches, ~"verbose")};
@ -66,9 +72,9 @@ fn log_config(config: config) {
logv(c, fmt!("configuration:")); logv(c, fmt!("configuration:"));
logv(c, fmt!("compile_lib_path: %s", config.compile_lib_path)); logv(c, fmt!("compile_lib_path: %s", config.compile_lib_path));
logv(c, fmt!("run_lib_path: %s", config.run_lib_path)); logv(c, fmt!("run_lib_path: %s", config.run_lib_path));
logv(c, fmt!("rustc_path: %s", config.rustc_path)); logv(c, fmt!("rustc_path: %s", config.rustc_path.to_str()));
logv(c, fmt!("src_base: %s", config.src_base)); logv(c, fmt!("src_base: %s", config.src_base.to_str()));
logv(c, fmt!("build_base: %s", config.build_base)); logv(c, fmt!("build_base: %s", config.build_base.to_str()));
logv(c, fmt!("stage_id: %s", config.stage_id)); logv(c, fmt!("stage_id: %s", config.stage_id));
logv(c, fmt!("mode: %s", mode_str(config.mode))); logv(c, fmt!("mode: %s", mode_str(config.mode)));
logv(c, fmt!("run_ignored: %b", config.run_ignored)); logv(c, fmt!("run_ignored: %b", config.run_ignored));
@ -122,18 +128,19 @@ fn test_opts(config: config) -> test::test_opts {
run_ignored: config.run_ignored, run_ignored: config.run_ignored,
logfile: logfile:
match config.logfile { match config.logfile {
option::some(s) => option::some(s), option::some(s) => option::some(s.to_str()),
option::none => option::none option::none => option::none
} }
} }
} }
fn make_tests(config: config) -> ~[test::test_desc] { fn make_tests(config: config) -> ~[test::test_desc] {
debug!("making tests from %s", config.src_base); debug!("making tests from %s",
config.src_base.to_str());
let mut tests = ~[]; let mut tests = ~[];
for os::list_dir_path(config.src_base).each |file| { for os::list_dir_path(&config.src_base).each |file| {
let file = file; let file = copy file;
debug!("inspecting file %s", file); debug!("inspecting file %s", file.to_str());
if is_test(config, file) { if is_test(config, file) {
vec::push(tests, make_test(config, file)) vec::push(tests, make_test(config, file))
} }
@ -141,7 +148,7 @@ fn make_tests(config: config) -> ~[test::test_desc] {
return tests; return tests;
} }
fn is_test(config: config, testfile: ~str) -> bool { fn is_test(config: config, testfile: &Path) -> bool {
// Pretty-printer does not work with .rc files yet // Pretty-printer does not work with .rc files yet
let valid_extensions = let valid_extensions =
match config.mode { match config.mode {
@ -149,7 +156,7 @@ fn is_test(config: config, testfile: ~str) -> bool {
_ => ~[~".rc", ~".rs"] _ => ~[~".rc", ~".rs"]
}; };
let invalid_prefixes = ~[~".", ~"#", ~"~"]; let invalid_prefixes = ~[~".", ~"#", ~"~"];
let name = path::basename(testfile); let name = option::get(testfile.filename());
let mut valid = false; let mut valid = false;
@ -164,7 +171,7 @@ fn is_test(config: config, testfile: ~str) -> bool {
return valid; return valid;
} }
fn make_test(config: config, testfile: ~str) -> fn make_test(config: config, testfile: &Path) ->
test::test_desc { test::test_desc {
{ {
name: make_test_name(config, testfile), name: make_test_name(config, testfile),
@ -174,12 +181,13 @@ fn make_test(config: config, testfile: ~str) ->
} }
} }
fn make_test_name(config: config, testfile: ~str) -> ~str { fn make_test_name(config: config, testfile: &Path) -> ~str {
fmt!("[%s] %s", mode_str(config.mode), testfile) fmt!("[%s] %s", mode_str(config.mode), testfile.to_str())
} }
fn make_test_closure(config: config, testfile: ~str) -> test::test_fn { fn make_test_closure(config: config, testfile: &Path) -> test::test_fn {
fn~() { runtest::run(config, copy testfile) } let testfile = testfile.to_str();
fn~() { runtest::run(config, testfile) }
} }
// Local Variables: // Local Variables:

View file

@ -6,7 +6,7 @@ export expected_error;
type expected_error = { line: uint, kind: ~str, msg: ~str }; type expected_error = { line: uint, kind: ~str, msg: ~str };
// Load any test directives embedded in the file // Load any test directives embedded in the file
fn load_errors(testfile: ~str) -> ~[expected_error] { fn load_errors(testfile: &Path) -> ~[expected_error] {
let mut error_patterns = ~[]; let mut error_patterns = ~[];
let rdr = result::get(io::file_reader(testfile)); let rdr = result::get(io::file_reader(testfile));
let mut line_num = 1u; let mut line_num = 1u;

View file

@ -14,7 +14,7 @@ type test_props = {
compile_flags: option<~str>, compile_flags: option<~str>,
// If present, the name of a file that this test should match when // If present, the name of a file that this test should match when
// pretty-printed // pretty-printed
pp_exact: option<~str>, pp_exact: option<Path>,
// Modules from aux directory that should be compiled // Modules from aux directory that should be compiled
aux_builds: ~[~str], aux_builds: ~[~str],
// Environment settings to use during execution // Environment settings to use during execution
@ -22,7 +22,7 @@ type test_props = {
}; };
// Load any test directives embedded in the file // Load any test directives embedded in the file
fn load_props(testfile: ~str) -> test_props { fn load_props(testfile: &Path) -> test_props {
let mut error_patterns = ~[]; let mut error_patterns = ~[];
let mut aux_builds = ~[]; let mut aux_builds = ~[];
let mut exec_env = ~[]; let mut exec_env = ~[];
@ -59,7 +59,7 @@ fn load_props(testfile: ~str) -> test_props {
}; };
} }
fn is_test_ignored(config: config, testfile: ~str) -> bool { fn is_test_ignored(config: config, testfile: &Path) -> bool {
let mut found = false; let mut found = false;
for iter_header(testfile) |ln| { for iter_header(testfile) |ln| {
if parse_name_directive(ln, ~"xfail-test") { return true; } if parse_name_directive(ln, ~"xfail-test") { return true; }
@ -74,7 +74,7 @@ fn is_test_ignored(config: config, testfile: ~str) -> bool {
} }
} }
fn iter_header(testfile: ~str, it: fn(~str) -> bool) -> bool { fn iter_header(testfile: &Path, it: fn(~str) -> bool) -> bool {
let rdr = result::get(io::file_reader(testfile)); let rdr = result::get(io::file_reader(testfile));
while !rdr.eof() { while !rdr.eof() {
let ln = rdr.read_line(); let ln = rdr.read_line();
@ -114,12 +114,12 @@ fn parse_exec_env(line: ~str) -> option<(~str, ~str)> {
} }
} }
fn parse_pp_exact(line: ~str, testfile: ~str) -> option<~str> { fn parse_pp_exact(line: ~str, testfile: &Path) -> option<Path> {
match parse_name_value_directive(line, ~"pp-exact") { match parse_name_value_directive(line, ~"pp-exact") {
option::some(s) => option::some(s), option::some(s) => option::some(Path(s)),
option::none => { option::none => {
if parse_name_directive(line, ~"pp-exact") { if parse_name_directive(line, ~"pp-exact") {
option::some(path::basename(testfile)) option::some(testfile.file_path())
} else { } else {
option::none option::none
} }

View file

@ -16,17 +16,18 @@ fn run(config: config, testfile: ~str) {
// We're going to be dumping a lot of info. Start on a new line. // We're going to be dumping a lot of info. Start on a new line.
io::stdout().write_str(~"\n\n"); io::stdout().write_str(~"\n\n");
} }
debug!("running %s", testfile); let testfile = Path(testfile);
let props = load_props(testfile); debug!("running %s", testfile.to_str());
let props = load_props(&testfile);
match config.mode { match config.mode {
mode_compile_fail => run_cfail_test(config, props, testfile), mode_compile_fail => run_cfail_test(config, props, &testfile),
mode_run_fail => run_rfail_test(config, props, testfile), mode_run_fail => run_rfail_test(config, props, &testfile),
mode_run_pass => run_rpass_test(config, props, testfile), mode_run_pass => run_rpass_test(config, props, &testfile),
mode_pretty => run_pretty_test(config, props, testfile) mode_pretty => run_pretty_test(config, props, &testfile)
} }
} }
fn run_cfail_test(config: config, props: test_props, testfile: ~str) { fn run_cfail_test(config: config, props: test_props, testfile: &Path) {
let procres = compile_test(config, props, testfile); let procres = compile_test(config, props, testfile);
if procres.status == 0 { if procres.status == 0 {
@ -46,7 +47,7 @@ fn run_cfail_test(config: config, props: test_props, testfile: ~str) {
} }
} }
fn run_rfail_test(config: config, props: test_props, testfile: ~str) { fn run_rfail_test(config: config, props: test_props, testfile: &Path) {
let mut procres = compile_test(config, props, testfile); let mut procres = compile_test(config, props, testfile);
if procres.status != 0 { fatal_procres(~"compilation failed!", procres); } if procres.status != 0 { fatal_procres(~"compilation failed!", procres); }
@ -74,7 +75,7 @@ fn check_correct_failure_status(procres: procres) {
} }
} }
fn run_rpass_test(config: config, props: test_props, testfile: ~str) { fn run_rpass_test(config: config, props: test_props, testfile: &Path) {
let mut procres = compile_test(config, props, testfile); let mut procres = compile_test(config, props, testfile);
if procres.status != 0 { fatal_procres(~"compilation failed!", procres); } if procres.status != 0 { fatal_procres(~"compilation failed!", procres); }
@ -84,7 +85,7 @@ fn run_rpass_test(config: config, props: test_props, testfile: ~str) {
if procres.status != 0 { fatal_procres(~"test run failed!", procres); } if procres.status != 0 { fatal_procres(~"test run failed!", procres); }
} }
fn run_pretty_test(config: config, props: test_props, testfile: ~str) { fn run_pretty_test(config: config, props: test_props, testfile: &Path) {
if option::is_some(props.pp_exact) { if option::is_some(props.pp_exact) {
logv(config, ~"testing for exact pretty-printing"); logv(config, ~"testing for exact pretty-printing");
} else { logv(config, ~"testing for converging pretty-printing"); } } else { logv(config, ~"testing for converging pretty-printing"); }
@ -111,8 +112,8 @@ fn run_pretty_test(config: config, props: test_props, testfile: ~str) {
let mut expected = let mut expected =
match props.pp_exact { match props.pp_exact {
option::some(file) => { option::some(file) => {
let filepath = path::connect(path::dirname(testfile), file); let filepath = testfile.dir_path().push_rel(&file);
result::get(io::read_whole_file_str(filepath)) result::get(io::read_whole_file_str(&filepath))
} }
option::none => { srcs[vec::len(srcs) - 2u] } option::none => { srcs[vec::len(srcs) - 2u] }
}; };
@ -136,15 +137,15 @@ fn run_pretty_test(config: config, props: test_props, testfile: ~str) {
return; return;
fn print_source(config: config, testfile: ~str, src: ~str) -> procres { fn print_source(config: config, testfile: &Path, src: ~str) -> procres {
compose_and_run(config, testfile, make_pp_args(config, testfile), compose_and_run(config, testfile, make_pp_args(config, testfile),
~[], config.compile_lib_path, option::some(src)) ~[], config.compile_lib_path, option::some(src))
} }
fn make_pp_args(config: config, _testfile: ~str) -> procargs { fn make_pp_args(config: config, _testfile: &Path) -> procargs {
let prog = config.rustc_path; let prog = config.rustc_path;
let args = ~[~"-", ~"--pretty", ~"normal"]; let args = ~[~"-", ~"--pretty", ~"normal"];
return {prog: prog, args: args}; return {prog: prog.to_str(), args: args};
} }
fn compare_source(expected: ~str, actual: ~str) { fn compare_source(expected: ~str, actual: ~str) {
@ -168,28 +169,30 @@ actual:\n\
} }
fn typecheck_source(config: config, props: test_props, fn typecheck_source(config: config, props: test_props,
testfile: ~str, src: ~str) -> procres { testfile: &Path, src: ~str) -> procres {
compose_and_run_compiler( compose_and_run_compiler(
config, props, testfile, config, props, testfile,
make_typecheck_args(config, testfile), make_typecheck_args(config, testfile),
option::some(src)) option::some(src))
} }
fn make_typecheck_args(config: config, testfile: ~str) -> procargs { fn make_typecheck_args(config: config, testfile: &Path) -> procargs {
let prog = config.rustc_path; let prog = config.rustc_path;
let mut args = ~[~"-", let mut args = ~[~"-",
~"--no-trans", ~"--lib", ~"-L", config.build_base, ~"--no-trans", ~"--lib",
~"-L", aux_output_dir_name(config, testfile)]; ~"-L", config.build_base.to_str(),
~"-L",
aux_output_dir_name(config, testfile).to_str()];
args += split_maybe_args(config.rustcflags); args += split_maybe_args(config.rustcflags);
return {prog: prog, args: args}; return {prog: prog.to_str(), args: args};
} }
} }
fn check_error_patterns(props: test_props, fn check_error_patterns(props: test_props,
testfile: ~str, testfile: &Path,
procres: procres) { procres: procres) {
if vec::is_empty(props.error_patterns) { if vec::is_empty(props.error_patterns) {
fatal(~"no error pattern specified in " + testfile); fatal(~"no error pattern specified in " + testfile.to_str());
} }
if procres.status == 0 { if procres.status == 0 {
@ -228,7 +231,7 @@ fn check_error_patterns(props: test_props,
} }
fn check_expected_errors(expected_errors: ~[errors::expected_error], fn check_expected_errors(expected_errors: ~[errors::expected_error],
testfile: ~str, testfile: &Path,
procres: procres) { procres: procres) {
// true if we found the error in question // true if we found the error in question
@ -240,7 +243,7 @@ fn check_expected_errors(expected_errors: ~[errors::expected_error],
} }
let prefixes = vec::map(expected_errors, |ee| { let prefixes = vec::map(expected_errors, |ee| {
fmt!("%s:%u:", testfile, ee.line) fmt!("%s:%u:", testfile.to_str(), ee.line)
}); });
// Scan and extract our error/warning messages, // Scan and extract our error/warning messages,
@ -291,8 +294,8 @@ type procargs = {prog: ~str, args: ~[~str]};
type procres = {status: int, stdout: ~str, stderr: ~str, cmdline: ~str}; type procres = {status: int, stdout: ~str, stderr: ~str, cmdline: ~str};
fn compile_test(config: config, props: test_props, fn compile_test(config: config, props: test_props,
testfile: ~str) -> procres { testfile: &Path) -> procres {
let link_args = ~[~"-L", aux_output_dir_name(config, testfile)]; let link_args = ~[~"-L", aux_output_dir_name(config, testfile).to_str()];
compose_and_run_compiler( compose_and_run_compiler(
config, props, testfile, config, props, testfile,
make_compile_args(config, props, link_args, make_compile_args(config, props, link_args,
@ -301,7 +304,7 @@ fn compile_test(config: config, props: test_props,
} }
fn exec_compiled_test(config: config, props: test_props, fn exec_compiled_test(config: config, props: test_props,
testfile: ~str) -> procres { testfile: &Path) -> procres {
compose_and_run(config, testfile, compose_and_run(config, testfile,
make_run_args(config, props, testfile), make_run_args(config, props, testfile),
props.exec_env, props.exec_env,
@ -311,26 +314,28 @@ fn exec_compiled_test(config: config, props: test_props,
fn compose_and_run_compiler( fn compose_and_run_compiler(
config: config, config: config,
props: test_props, props: test_props,
testfile: ~str, testfile: &Path,
args: procargs, args: procargs,
input: option<~str>) -> procres { input: option<~str>) -> procres {
if props.aux_builds.is_not_empty() { if props.aux_builds.is_not_empty() {
ensure_dir(aux_output_dir_name(config, testfile)); ensure_dir(&aux_output_dir_name(config, testfile));
} }
let extra_link_args = ~[~"-L", aux_output_dir_name(config, testfile)]; let extra_link_args = ~[~"-L",
aux_output_dir_name(config, testfile).to_str()];
do vec::iter(props.aux_builds) |rel_ab| { do vec::iter(props.aux_builds) |rel_ab| {
let abs_ab = path::connect(config.aux_base, rel_ab); let abs_ab = config.aux_base.push_rel(&Path(rel_ab));
let aux_args = let aux_args =
make_compile_args(config, props, ~[~"--lib"] + extra_link_args, make_compile_args(config, props, ~[~"--lib"] + extra_link_args,
|a,b| make_lib_name(a, b, testfile), abs_ab); |a,b| make_lib_name(a, b, testfile), &abs_ab);
let auxres = compose_and_run(config, abs_ab, aux_args, ~[], let auxres = compose_and_run(config, &abs_ab, aux_args, ~[],
config.compile_lib_path, option::none); config.compile_lib_path, option::none);
if auxres.status != 0 { if auxres.status != 0 {
fatal_procres( fatal_procres(
fmt!("auxiliary build of %s failed to compile: ", abs_ab), fmt!("auxiliary build of %s failed to compile: ",
abs_ab.to_str()),
auxres); auxres);
} }
} }
@ -339,14 +344,14 @@ fn compose_and_run_compiler(
config.compile_lib_path, input) config.compile_lib_path, input)
} }
fn ensure_dir(path: Path) { fn ensure_dir(path: &Path) {
if os::path_is_dir(path) { return; } if os::path_is_dir(path) { return; }
if !os::make_dir(path, 0x1c0i32) { if !os::make_dir(path, 0x1c0i32) {
fail fmt!("can't make dir %s", path); fail fmt!("can't make dir %s", path.to_str());
} }
} }
fn compose_and_run(config: config, testfile: ~str, fn compose_and_run(config: config, testfile: &Path,
procargs: procargs, procargs: procargs,
procenv: ~[(~str, ~str)], procenv: ~[(~str, ~str)],
lib_path: ~str, lib_path: ~str,
@ -356,28 +361,30 @@ fn compose_and_run(config: config, testfile: ~str,
} }
fn make_compile_args(config: config, props: test_props, extras: ~[~str], fn make_compile_args(config: config, props: test_props, extras: ~[~str],
xform: fn(config, ~str) -> ~str, testfile: ~str) -> xform: fn(config, (&Path)) -> Path,
procargs { testfile: &Path) -> procargs {
let prog = config.rustc_path; let prog = config.rustc_path;
let mut args = ~[testfile, ~"-o", xform(config, testfile), let mut args = ~[testfile.to_str(),
~"-L", config.build_base] + extras; ~"-o", xform(config, testfile).to_str(),
~"-L", config.build_base.to_str()]
+ extras;
args += split_maybe_args(config.rustcflags); args += split_maybe_args(config.rustcflags);
args += split_maybe_args(props.compile_flags); args += split_maybe_args(props.compile_flags);
return {prog: prog, args: args}; return {prog: prog.to_str(), args: args};
} }
fn make_lib_name(config: config, auxfile: ~str, testfile: ~str) -> ~str { fn make_lib_name(config: config, auxfile: &Path, testfile: &Path) -> Path {
// what we return here is not particularly important, as it // what we return here is not particularly important, as it
// happens; rustc ignores everything except for the directory. // happens; rustc ignores everything except for the directory.
let auxname = output_testname(auxfile); let auxname = output_testname(auxfile);
path::connect(aux_output_dir_name(config, testfile), auxname) aux_output_dir_name(config, testfile).push_rel(&auxname)
} }
fn make_exe_name(config: config, testfile: ~str) -> ~str { fn make_exe_name(config: config, testfile: &Path) -> Path {
output_base_name(config, testfile) + os::exe_suffix() Path(output_base_name(config, testfile).to_str() + os::exe_suffix())
} }
fn make_run_args(config: config, _props: test_props, testfile: ~str) -> fn make_run_args(config: config, _props: test_props, testfile: &Path) ->
procargs { procargs {
let toolargs = { let toolargs = {
// If we've got another tool to run under (valgrind), // If we've got another tool to run under (valgrind),
@ -390,7 +397,7 @@ fn make_run_args(config: config, _props: test_props, testfile: ~str) ->
split_maybe_args(runtool) split_maybe_args(runtool)
}; };
let args = toolargs + ~[make_exe_name(config, testfile)]; let args = toolargs + ~[make_exe_name(config, testfile).to_str()];
return {prog: args[0], args: vec::slice(args, 1u, vec::len(args))}; return {prog: args[0], args: vec::slice(args, 1u, vec::len(args))};
} }
@ -408,7 +415,7 @@ fn split_maybe_args(argstr: option<~str>) -> ~[~str] {
} }
} }
fn program_output(config: config, testfile: ~str, lib_path: ~str, prog: ~str, fn program_output(config: config, testfile: &Path, lib_path: ~str, prog: ~str,
args: ~[~str], env: ~[(~str, ~str)], args: ~[~str], env: ~[(~str, ~str)],
input: option<~str>) -> procres { input: option<~str>) -> procres {
let cmdline = let cmdline =
@ -445,37 +452,36 @@ fn lib_path_cmd_prefix(path: ~str) -> ~str {
fmt!("%s=\"%s\"", util::lib_path_env_var(), util::make_new_path(path)) fmt!("%s=\"%s\"", util::lib_path_env_var(), util::make_new_path(path))
} }
fn dump_output(config: config, testfile: ~str, out: ~str, err: ~str) { fn dump_output(config: config, testfile: &Path, out: ~str, err: ~str) {
dump_output_file(config, testfile, out, ~"out"); dump_output_file(config, testfile, out, ~"out");
dump_output_file(config, testfile, err, ~"err"); dump_output_file(config, testfile, err, ~"err");
maybe_dump_to_stdout(config, out, err); maybe_dump_to_stdout(config, out, err);
} }
fn dump_output_file(config: config, testfile: ~str, fn dump_output_file(config: config, testfile: &Path,
out: ~str, extension: ~str) { out: ~str, extension: ~str) {
let outfile = make_out_name(config, testfile, extension); let outfile = make_out_name(config, testfile, extension);
let writer = result::get( let writer = result::get(
io::file_writer(outfile, ~[io::Create, io::Truncate])); io::file_writer(&outfile, ~[io::Create, io::Truncate]));
writer.write_str(out); writer.write_str(out);
} }
fn make_out_name(config: config, testfile: ~str, extension: ~str) -> ~str { fn make_out_name(config: config, testfile: &Path, extension: ~str) -> Path {
output_base_name(config, testfile) + ~"." + extension output_base_name(config, testfile).with_filetype(extension)
} }
fn aux_output_dir_name(config: config, testfile: ~str) -> ~str { fn aux_output_dir_name(config: config, testfile: &Path) -> Path {
output_base_name(config, testfile) + ~".libaux" output_base_name(config, testfile).with_filetype("libaux")
} }
fn output_testname(testfile: ~str) -> ~str { fn output_testname(testfile: &Path) -> Path {
let parts = str::split_char(path::basename(testfile), '.'); Path(option::get(testfile.filestem()))
str::connect(vec::slice(parts, 0u, vec::len(parts) - 1u), ~".")
} }
fn output_base_name(config: config, testfile: ~str) -> ~str { fn output_base_name(config: config, testfile: &Path) -> Path {
let base = config.build_base; config.build_base
let filename = output_testname(testfile); .push_rel(&output_testname(testfile))
fmt!("%s%s.%s", base, filename, config.stage_id) .with_filetype(config.stage_id)
} }
fn maybe_dump_to_stdout(config: config, out: ~str, err: ~str) { fn maybe_dump_to_stdout(config: config, out: ~str, err: ~str) {

View file

@ -8,7 +8,7 @@ import syntax::diagnostic;
enum test_mode { tm_converge, tm_run, } enum test_mode { tm_converge, tm_run, }
type context = { mode: test_mode }; // + rng type context = { mode: test_mode }; // + rng
fn write_file(filename: ~str, content: ~str) { fn write_file(filename: &Path, content: ~str) {
result::get( result::get(
io::file_writer(filename, ~[io::Create, io::Truncate])) io::file_writer(filename, ~[io::Create, io::Truncate]))
.write_str(content); .write_str(content);
@ -18,13 +18,13 @@ fn contains(haystack: ~str, needle: ~str) -> bool {
str::contains(haystack, needle) str::contains(haystack, needle)
} }
fn find_rust_files(&files: ~[~str], path: ~str) { fn find_rust_files(files: &mut ~[Path], path: &Path) {
if str::ends_with(path, ~".rs") && !contains(path, ~"utf8") { if path.filetype() == some(~"rs") && !contains(path.to_str(), ~"utf8") {
// ignoring "utf8" tests because something is broken // ignoring "utf8" tests because something is broken
files += ~[path]; vec::push(*files, *path);
} else if os::path_is_dir(path) } else if os::path_is_dir(path)
&& !contains(path, ~"compile-fail") && !contains(path.to_str(), ~"compile-fail")
&& !contains(path, ~"build") { && !contains(path.to_str(), ~"build") {
for os::list_dir_path(path).each |p| { for os::list_dir_path(path).each |p| {
find_rust_files(files, p); find_rust_files(files, p);
} }
@ -221,7 +221,7 @@ fn as_str(f: fn@(io::Writer)) -> ~str {
} }
fn check_variants_of_ast(crate: ast::crate, codemap: codemap::codemap, fn check_variants_of_ast(crate: ast::crate, codemap: codemap::codemap,
filename: ~str, cx: context) { filename: &Path, cx: context) {
let stolen = steal(crate, cx.mode); let stolen = steal(crate, cx.mode);
let extra_exprs = vec::filter(common_exprs(), let extra_exprs = vec::filter(common_exprs(),
|a| safe_to_use_expr(a, cx.mode) ); |a| safe_to_use_expr(a, cx.mode) );
@ -235,14 +235,14 @@ fn check_variants_of_ast(crate: ast::crate, codemap: codemap::codemap,
fn check_variants_T<T: copy>( fn check_variants_T<T: copy>(
crate: ast::crate, crate: ast::crate,
codemap: codemap::codemap, codemap: codemap::codemap,
filename: ~str, filename: &Path,
thing_label: ~str, thing_label: ~str,
things: ~[T], things: ~[T],
stringifier: fn@(@T, syntax::parse::token::ident_interner) -> ~str, stringifier: fn@(@T, syntax::parse::token::ident_interner) -> ~str,
replacer: fn@(ast::crate, uint, T, test_mode) -> ast::crate, replacer: fn@(ast::crate, uint, T, test_mode) -> ast::crate,
cx: context cx: context
) { ) {
error!("%s contains %u %s objects", filename, error!("%s contains %u %s objects", filename.to_str(),
vec::len(things), thing_label); vec::len(things), thing_label);
// Assuming we're not generating any token_trees // Assuming we're not generating any token_trees
@ -253,6 +253,7 @@ fn check_variants_T<T: copy>(
if L < 100u { if L < 100u {
do under(uint::min(L, 20u)) |i| { do under(uint::min(L, 20u)) |i| {
log(error, ~"Replacing... #" + uint::str(i)); log(error, ~"Replacing... #" + uint::str(i));
let fname = str::from_slice(filename.to_str());
do under(uint::min(L, 30u)) |j| { do under(uint::min(L, 30u)) |j| {
log(error, ~"With... " + stringifier(@things[j], intr)); log(error, ~"With... " + stringifier(@things[j], intr));
let crate2 = @replacer(crate, i, things[j], cx.mode); let crate2 = @replacer(crate, i, things[j], cx.mode);
@ -265,7 +266,7 @@ fn check_variants_T<T: copy>(
intr, intr,
diagnostic::mk_span_handler(handler, codemap), diagnostic::mk_span_handler(handler, codemap),
crate2, crate2,
filename, fname,
rdr, a, rdr, a,
pprust::no_ann(), pprust::no_ann(),
false)) false))
@ -276,11 +277,12 @@ fn check_variants_T<T: copy>(
} }
tm_run => { tm_run => {
let file_label = fmt!("rusttmp/%s_%s_%u_%u", let file_label = fmt!("rusttmp/%s_%s_%u_%u",
last_part(filename), last_part(filename.to_str()),
thing_label, i, j); thing_label, i, j);
let safe_to_run = !(content_is_dangerous_to_run(*str3) let safe_to_run = !(content_is_dangerous_to_run(*str3)
|| has_raw_pointers(*crate2)); || has_raw_pointers(*crate2));
check_whole_compiler(*str3, file_label, safe_to_run); check_whole_compiler(*str3, &Path(file_label),
safe_to_run);
} }
} }
} }
@ -305,9 +307,9 @@ enum happiness {
// - that would be tricky, requiring use of tasks or serialization // - that would be tricky, requiring use of tasks or serialization
// or randomness. // or randomness.
// This seems to find plenty of bugs as it is :) // This seems to find plenty of bugs as it is :)
fn check_whole_compiler(code: ~str, suggested_filename_prefix: ~str, fn check_whole_compiler(code: ~str, suggested_filename_prefix: &Path,
allow_running: bool) { allow_running: bool) {
let filename = suggested_filename_prefix + ~".rs"; let filename = &suggested_filename_prefix.with_filetype("rs");
write_file(filename, code); write_file(filename, code);
let compile_result = check_compiling(filename); let compile_result = check_compiling(filename);
@ -320,32 +322,32 @@ fn check_whole_compiler(code: ~str, suggested_filename_prefix: ~str,
match run_result { match run_result {
passed | cleanly_rejected(_) | known_bug(_) => { passed | cleanly_rejected(_) | known_bug(_) => {
removeIfExists(suggested_filename_prefix); removeIfExists(suggested_filename_prefix);
removeIfExists(suggested_filename_prefix + ~".rs"); removeIfExists(&suggested_filename_prefix.with_filetype("rs"));
removeDirIfExists(suggested_filename_prefix + ~".dSYM"); removeDirIfExists(&suggested_filename_prefix.with_filetype("dSYM"));
} }
failed(s) => { failed(s) => {
log(error, ~"check_whole_compiler failure: " + s); log(error, ~"check_whole_compiler failure: " + s);
log(error, ~"Saved as: " + filename); log(error, ~"Saved as: " + filename.to_str());
} }
} }
} }
fn removeIfExists(filename: ~str) { fn removeIfExists(filename: &Path) {
// So sketchy! // So sketchy!
assert !contains(filename, ~" "); assert !contains(filename.to_str(), ~" ");
run::program_output(~"bash", ~[~"-c", ~"rm " + filename]); run::program_output(~"bash", ~[~"-c", ~"rm " + filename.to_str()]);
} }
fn removeDirIfExists(filename: ~str) { fn removeDirIfExists(filename: &Path) {
// So sketchy! // So sketchy!
assert !contains(filename, ~" "); assert !contains(filename.to_str(), ~" ");
run::program_output(~"bash", ~[~"-c", ~"rm -r " + filename]); run::program_output(~"bash", ~[~"-c", ~"rm -r " + filename.to_str()]);
} }
fn check_running(exe_filename: ~str) -> happiness { fn check_running(exe_filename: &Path) -> happiness {
let p = run::program_output( let p = run::program_output(
~"/Users/jruderman/scripts/timed_run_rust_program.py", ~"/Users/jruderman/scripts/timed_run_rust_program.py",
~[exe_filename]); ~[exe_filename.to_str()]);
let comb = p.out + ~"\n" + p.err; let comb = p.out + ~"\n" + p.err;
if str::len(comb) > 1u { if str::len(comb) > 1u {
log(error, ~"comb comb comb: " + comb); log(error, ~"comb comb comb: " + comb);
@ -381,11 +383,11 @@ fn check_running(exe_filename: ~str) -> happiness {
} }
} }
fn check_compiling(filename: ~str) -> happiness { fn check_compiling(filename: &Path) -> happiness {
let p = run::program_output( let p = run::program_output(
~"/Users/jruderman/code/rust/build/x86_64-apple-darwin/\ ~"/Users/jruderman/code/rust/build/x86_64-apple-darwin/\
stage1/bin/rustc", stage1/bin/rustc",
~[filename]); ~[filename.to_str()]);
//error!("Status: %d", p.status); //error!("Status: %d", p.status);
if p.status == 0 { if p.status == 0 {
@ -415,11 +417,11 @@ fn check_compiling(filename: ~str) -> happiness {
fn parse_and_print(code: @~str) -> ~str { fn parse_and_print(code: @~str) -> ~str {
let filename = ~"tmp.rs"; let filename = Path("tmp.rs");
let sess = parse::new_parse_sess(option::none); let sess = parse::new_parse_sess(option::none);
write_file(filename, *code); write_file(&filename, *code);
let crate = parse::parse_crate_from_source_str( let crate = parse::parse_crate_from_source_str(
filename, code, ~[], sess); filename.to_str(), code, ~[], sess);
do io::with_str_reader(*code) |rdr| { do io::with_str_reader(*code) |rdr| {
as_str(|a| as_str(|a|
pprust::print_crate( pprust::print_crate(
@ -428,7 +430,7 @@ fn parse_and_print(code: @~str) -> ~str {
syntax::parse::token::mk_fake_ident_interner(), syntax::parse::token::mk_fake_ident_interner(),
sess.span_diagnostic, sess.span_diagnostic,
crate, crate,
filename, filename.to_str(),
rdr, a, rdr, a,
pprust::no_ann(), pprust::no_ann(),
false) ) false) )
@ -486,7 +488,7 @@ fn content_might_not_converge(code: ~str) -> bool {
return false; return false;
} }
fn file_might_not_converge(filename: ~str) -> bool { fn file_might_not_converge(filename: &Path) -> bool {
let confusing_files = ~[ let confusing_files = ~[
~"expr-alt.rs", // pretty-printing "(a = b) = c" ~"expr-alt.rs", // pretty-printing "(a = b) = c"
// vs "a = b = c" and wrapping // vs "a = b = c" and wrapping
@ -496,7 +498,11 @@ fn file_might_not_converge(filename: ~str) -> bool {
]; ];
for confusing_files.each |f| { if contains(filename, f) { return true; } } for confusing_files.each |f| {
if contains(filename.to_str(), f) {
return true;
}
}
return false; return false;
} }
@ -519,8 +525,8 @@ fn check_roundtrip_convergence(code: @~str, maxIters: uint) {
error!("Converged after %u iterations", i); error!("Converged after %u iterations", i);
} else { } else {
error!("Did not converge after %u iterations!", i); error!("Did not converge after %u iterations!", i);
write_file(~"round-trip-a.rs", *oldv); write_file(&Path("round-trip-a.rs"), *oldv);
write_file(~"round-trip-b.rs", *newv); write_file(&Path("round-trip-b.rs"), *newv);
run::run_program(~"diff", run::run_program(~"diff",
~[~"-w", ~"-u", ~"round-trip-a.rs", ~[~"-w", ~"-u", ~"round-trip-a.rs",
~"round-trip-b.rs"]); ~"round-trip-b.rs"]);
@ -528,13 +534,13 @@ fn check_roundtrip_convergence(code: @~str, maxIters: uint) {
} }
} }
fn check_convergence(files: ~[~str]) { fn check_convergence(files: &[Path]) {
error!("pp convergence tests: %u files", vec::len(files)); error!("pp convergence tests: %u files", vec::len(files));
for files.each |file| { for files.each |file| {
if !file_might_not_converge(file) { if !file_might_not_converge(&file) {
let s = @result::get(io::read_whole_file_str(file)); let s = @result::get(io::read_whole_file_str(&file));
if !content_might_not_converge(*s) { if !content_might_not_converge(*s) {
error!("pp converge: %s", file); error!("pp converge: %s", file.to_str());
// Change from 7u to 2u once // Change from 7u to 2u once
// https://github.com/mozilla/rust/issues/850 is fixed // https://github.com/mozilla/rust/issues/850 is fixed
check_roundtrip_convergence(s, 7u); check_roundtrip_convergence(s, 7u);
@ -543,15 +549,16 @@ fn check_convergence(files: ~[~str]) {
} }
} }
fn check_variants(files: ~[~str], cx: context) { fn check_variants(files: &[Path], cx: context) {
for files.each |file| { for files.each |file| {
if cx.mode == tm_converge && file_might_not_converge(file) { if cx.mode == tm_converge &&
file_might_not_converge(&file) {
error!("Skipping convergence test based on\ error!("Skipping convergence test based on\
file_might_not_converge"); file_might_not_converge");
again; again;
} }
let s = @result::get(io::read_whole_file_str(file)); let s = @result::get(io::read_whole_file_str(&file));
if contains(*s, ~"#") { if contains(*s, ~"#") {
again; // Macros are confusing again; // Macros are confusing
} }
@ -562,11 +569,11 @@ fn check_variants(files: ~[~str], cx: context) {
again; again;
} }
log(error, ~"check_variants: " + file); log(error, ~"check_variants: " + file.to_str());
let sess = parse::new_parse_sess(option::none); let sess = parse::new_parse_sess(option::none);
let crate = let crate =
parse::parse_crate_from_source_str( parse::parse_crate_from_source_str(
file, file.to_str(),
s, ~[], sess); s, ~[], sess);
io::with_str_reader(*s, |rdr| { io::with_str_reader(*s, |rdr| {
error!("%s", error!("%s",
@ -576,12 +583,12 @@ fn check_variants(files: ~[~str], cx: context) {
syntax::parse::token::mk_fake_ident_interner(), syntax::parse::token::mk_fake_ident_interner(),
sess.span_diagnostic, sess.span_diagnostic,
crate, crate,
file, file.to_str(),
rdr, a, rdr, a,
pprust::no_ann(), pprust::no_ann(),
false) )) false) ))
}); });
check_variants_of_ast(*crate, sess.cm, file, cx); check_variants_of_ast(*crate, sess.cm, &file, cx);
} }
} }
@ -591,9 +598,9 @@ fn main(args: ~[~str]) {
return; return;
} }
let mut files = ~[]; let mut files = ~[];
let root = args[1]; let root = Path(args[1]);
find_rust_files(files, root); find_rust_files(&mut files, &root);
error!("== check_convergence =="); error!("== check_convergence ==");
check_convergence(files); check_convergence(files);
error!("== check_variants: converge =="); error!("== check_variants: converge ==");

View file

@ -54,7 +54,7 @@ export send_map;
export hash; export hash;
export cmp; export cmp;
export num; export num;
export path; export path, path2;
export managed; export managed;
// NDM seems to be necessary for resolve to work // NDM seems to be necessary for resolve to work

View file

@ -4,7 +4,12 @@
import option::{some, none}; import option::{some, none};
import option = option::option; import option = option::option;
import Path = path::Path;
import Path = path2::Path;
import GenericPath = path2::GenericPath;
import WindowsPath = path2::WindowsPath;
import PosixPath = path2::PosixPath;
import tuple::{TupleOps, ExtendedTupleOps}; import tuple::{TupleOps, ExtendedTupleOps};
import str::{StrSlice, UniqueStr}; import str::{StrSlice, UniqueStr};
import vec::{ConstVector, CopyableVector, ImmutableVector}; import vec::{ConstVector, CopyableVector, ImmutableVector};
@ -14,7 +19,8 @@ import num::Num;
import ptr::Ptr; import ptr::Ptr;
import to_str::ToStr; import to_str::ToStr;
export Path, option, some, none, unreachable; export Path, WindowsPath, PosixPath, GenericPath;
export option, some, none, unreachable;
export extensions; export extensions;
// The following exports are the extension impls for numeric types // The following exports are the extension impls for numeric types
export Num, Times, TimesIx; export Num, Times, TimesIx;

View file

@ -257,13 +257,14 @@ fn FILE_reader(f: *libc::FILE, cleanup: bool) -> Reader {
fn stdin() -> Reader { rustrt::rust_get_stdin() as Reader } fn stdin() -> Reader { rustrt::rust_get_stdin() as Reader }
fn file_reader(path: ~str) -> result<Reader, ~str> { fn file_reader(path: &Path) -> result<Reader, ~str> {
let f = os::as_c_charp(path, |pathbuf| { let f = os::as_c_charp(path.to_str(), |pathbuf| {
os::as_c_charp(~"r", |modebuf| os::as_c_charp("r", |modebuf|
libc::fopen(pathbuf, modebuf) libc::fopen(pathbuf, modebuf)
) )
}); });
return if f as uint == 0u { result::err(~"error opening " + path) } return if f as uint == 0u { result::err(~"error opening "
+ path.to_str()) }
else { else {
result::ok(FILE_reader(f, true)) result::ok(FILE_reader(f, true))
} }
@ -412,7 +413,7 @@ fn fd_writer(fd: fd_t, cleanup: bool) -> Writer {
} }
fn mk_file_writer(path: ~str, flags: ~[FileFlag]) fn mk_file_writer(path: &Path, flags: ~[FileFlag])
-> result<Writer, ~str> { -> result<Writer, ~str> {
#[cfg(windows)] #[cfg(windows)]
@ -430,12 +431,13 @@ fn mk_file_writer(path: ~str, flags: ~[FileFlag])
NoFlag => () NoFlag => ()
} }
} }
let fd = do os::as_c_charp(path) |pathbuf| { let fd = do os::as_c_charp(path.to_str()) |pathbuf| {
libc::open(pathbuf, fflags, libc::open(pathbuf, fflags,
(S_IRUSR | S_IWUSR) as c_int) (S_IRUSR | S_IWUSR) as c_int)
}; };
if fd < (0 as c_int) { if fd < (0 as c_int) {
result::err(fmt!("error opening %s: %s", path, os::last_os_error())) result::err(fmt!("error opening %s: %s", path.to_str(),
os::last_os_error()))
} else { } else {
result::ok(fd_writer(fd, true)) result::ok(fd_writer(fd, true))
} }
@ -614,19 +616,20 @@ impl<T: Writer> T : WriterUtil {
fn write_u8(n: u8) { self.write(&[n]) } fn write_u8(n: u8) { self.write(&[n]) }
} }
fn file_writer(path: ~str, flags: ~[FileFlag]) -> result<Writer, ~str> { fn file_writer(path: &Path, flags: ~[FileFlag]) -> result<Writer, ~str> {
result::chain(mk_file_writer(path, flags), |w| result::ok(w)) result::chain(mk_file_writer(path, flags), |w| result::ok(w))
} }
// FIXME: fileflags // #2004 // FIXME: fileflags // #2004
fn buffered_file_writer(path: ~str) -> result<Writer, ~str> { fn buffered_file_writer(path: &Path) -> result<Writer, ~str> {
let f = do os::as_c_charp(path) |pathbuf| { let f = do os::as_c_charp(path.to_str()) |pathbuf| {
do os::as_c_charp(~"w") |modebuf| { do os::as_c_charp("w") |modebuf| {
libc::fopen(pathbuf, modebuf) libc::fopen(pathbuf, modebuf)
} }
}; };
return if f as uint == 0u { result::err(~"error opening " + path) } return if f as uint == 0u { result::err(~"error opening "
+ path.to_str()) }
else { result::ok(FILE_writer(f, true)) } else { result::ok(FILE_writer(f, true)) }
} }
@ -709,19 +712,19 @@ fn seek_in_buf(offset: int, pos: uint, len: uint, whence: SeekStyle) ->
return bpos as uint; return bpos as uint;
} }
fn read_whole_file_str(file: ~str) -> result<~str, ~str> { fn read_whole_file_str(file: &Path) -> result<~str, ~str> {
result::chain(read_whole_file(file), |bytes| { result::chain(read_whole_file(file), |bytes| {
if str::is_utf8(bytes) { if str::is_utf8(bytes) {
result::ok(str::from_bytes(bytes)) result::ok(str::from_bytes(bytes))
} else { } else {
result::err(file + ~" is not UTF-8") result::err(file.to_str() + ~" is not UTF-8")
} }
}) })
} }
// FIXME (#2004): implement this in a low-level way. Going through the // FIXME (#2004): implement this in a low-level way. Going through the
// abstractions is pointless. // abstractions is pointless.
fn read_whole_file(file: ~str) -> result<~[u8], ~str> { fn read_whole_file(file: &Path) -> result<~[u8], ~str> {
result::chain(file_reader(file), |rdr| { result::chain(file_reader(file), |rdr| {
result::ok(rdr.read_whole_stream()) result::ok(rdr.read_whole_stream())
}) })
@ -810,7 +813,7 @@ mod tests {
#[test] #[test]
fn test_simple() { fn test_simple() {
let tmpfile: ~str = ~"tmp/lib-io-test-simple.tmp"; let tmpfile = &Path("tmp/lib-io-test-simple.tmp");
log(debug, tmpfile); log(debug, tmpfile);
let frood: ~str = let frood: ~str =
~"A hoopy frood who really knows where his towel is."; ~"A hoopy frood who really knows where his towel is.";
@ -881,7 +884,7 @@ mod tests {
#[test] #[test]
fn file_reader_not_exist() { fn file_reader_not_exist() {
match io::file_reader(~"not a file") { match io::file_reader(&Path("not a file")) {
result::err(e) => { result::err(e) => {
assert e == ~"error opening not a file"; assert e == ~"error opening not a file";
} }
@ -891,9 +894,9 @@ mod tests {
#[test] #[test]
fn file_writer_bad_name() { fn file_writer_bad_name() {
match io::file_writer(~"?/?", ~[]) { match io::file_writer(&Path("?/?"), ~[]) {
result::err(e) => { result::err(e) => {
assert str::starts_with(e, ~"error opening ?/?"); assert str::starts_with(e, "error opening");
} }
result::ok(_) => fail result::ok(_) => fail
} }
@ -901,9 +904,9 @@ mod tests {
#[test] #[test]
fn buffered_file_writer_bad_name() { fn buffered_file_writer_bad_name() {
match io::buffered_file_writer(~"?/?") { match io::buffered_file_writer(&Path("?/?")) {
result::err(e) => { result::err(e) => {
assert e == ~"error opening ?/?"; assert str::starts_with(e, "error opening");
} }
result::ok(_) => fail result::ok(_) => fail
} }

View file

@ -1,3 +1,7 @@
// NB: transitionary, de-mode-ing.
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
/*! /*!
* Higher-level interfaces to libc::* functions and operating system services. * Higher-level interfaces to libc::* functions and operating system services.
* *
@ -16,16 +20,12 @@
* to write OS-ignorant code by default. * to write OS-ignorant code by default.
*/ */
#[forbid(deprecated_mode)];
#[forbid(deprecated_pattern)];
import libc::{c_char, c_void, c_int, c_uint, size_t, ssize_t, import libc::{c_char, c_void, c_int, c_uint, size_t, ssize_t,
mode_t, pid_t, FILE}; mode_t, pid_t, FILE};
import libc::{close, fclose}; import libc::{close, fclose};
import option::{some, none}; import option::{some, none};
import getcwd = rustrt::rust_getcwd;
import consts::*; import consts::*;
import task::TaskBuilder; import task::TaskBuilder;
@ -56,7 +56,11 @@ extern mod rustrt {
const tmpbuf_sz : uint = 1000u; const tmpbuf_sz : uint = 1000u;
fn as_c_charp<T>(+s: ~str, f: fn(*c_char) -> T) -> T { fn getcwd() -> Path {
Path(rustrt::rust_getcwd())
}
fn as_c_charp<T>(s: &str, f: fn(*c_char) -> T) -> T {
str::as_c_str(s, |b| f(b as *c_char)) str::as_c_str(s, |b| f(b as *c_char))
} }
@ -106,7 +110,7 @@ mod win32 {
return res; return res;
} }
fn as_utf16_p<T>(+s: ~str, f: fn(*u16) -> T) -> T { fn as_utf16_p<T>(s: &str, f: fn(*u16) -> T) -> T {
let mut t = str::to_utf16(s); let mut t = str::to_utf16(s);
// Null terminate before passing on. // Null terminate before passing on.
t += ~[0u16]; t += ~[0u16];
@ -114,11 +118,11 @@ mod win32 {
} }
} }
fn getenv(+n: ~str) -> option<~str> { fn getenv(n: &str) -> option<~str> {
global_env::getenv(n) global_env::getenv(n)
} }
fn setenv(+n: ~str, +v: ~str) { fn setenv(n: &str, v: &str) {
global_env::setenv(n, v) global_env::setenv(n, v)
} }
@ -143,17 +147,20 @@ mod global_env {
MsgEnv(comm::Chan<~[(~str,~str)]>) MsgEnv(comm::Chan<~[(~str,~str)]>)
} }
fn getenv(+n: ~str) -> option<~str> { fn getenv(n: &str) -> option<~str> {
let env_ch = get_global_env_chan(); let env_ch = get_global_env_chan();
let po = comm::port(); let po = comm::port();
comm::send(env_ch, MsgGetEnv(n, comm::chan(po))); comm::send(env_ch, MsgGetEnv(str::from_slice(n),
comm::chan(po)));
comm::recv(po) comm::recv(po)
} }
fn setenv(+n: ~str, +v: ~str) { fn setenv(n: &str, v: &str) {
let env_ch = get_global_env_chan(); let env_ch = get_global_env_chan();
let po = comm::port(); let po = comm::port();
comm::send(env_ch, MsgSetEnv(n, v, comm::chan(po))); comm::send(env_ch, MsgSetEnv(str::from_slice(n),
str::from_slice(v),
comm::chan(po)));
comm::recv(po) comm::recv(po)
} }
@ -212,7 +219,7 @@ mod global_env {
} }
#[cfg(unix)] #[cfg(unix)]
fn getenv(+n: ~str) -> option<~str> { fn getenv(n: &str) -> option<~str> {
unsafe { unsafe {
let s = str::as_c_str(n, libc::getenv); let s = str::as_c_str(n, libc::getenv);
return if unsafe::reinterpret_cast(s) == 0 { return if unsafe::reinterpret_cast(s) == 0 {
@ -225,7 +232,7 @@ mod global_env {
} }
#[cfg(windows)] #[cfg(windows)]
fn getenv(+n: ~str) -> option<~str> { fn getenv(n: &str) -> option<~str> {
import libc::types::os::arch::extra::*; import libc::types::os::arch::extra::*;
import libc::funcs::extra::kernel32::*; import libc::funcs::extra::kernel32::*;
import win32::*; import win32::*;
@ -238,7 +245,7 @@ mod global_env {
#[cfg(unix)] #[cfg(unix)]
fn setenv(+n: ~str, +v: ~str) { fn setenv(n: &str, v: &str) {
// FIXME: remove this when export globs work properly. #1238 // FIXME: remove this when export globs work properly. #1238
import libc::funcs::posix01::unistd::setenv; import libc::funcs::posix01::unistd::setenv;
@ -251,7 +258,7 @@ mod global_env {
#[cfg(windows)] #[cfg(windows)]
fn setenv(+n: ~str, +v: ~str) { fn setenv(n: &str, v: &str) {
// FIXME: remove imports when export globs work properly. #1238 // FIXME: remove imports when export globs work properly. #1238
import libc::funcs::extra::kernel32::*; import libc::funcs::extra::kernel32::*;
import win32::*; import win32::*;
@ -266,7 +273,7 @@ mod global_env {
} }
fn fdopen(fd: c_int) -> *FILE { fn fdopen(fd: c_int) -> *FILE {
return do as_c_charp(~"r") |modebuf| { return do as_c_charp("r") |modebuf| {
libc::fdopen(fd, modebuf) libc::fdopen(fd, modebuf)
}; };
} }
@ -365,8 +372,8 @@ fn dup2(src: c_int, dst: c_int) -> c_int {
} }
fn dll_filename(+base: ~str) -> ~str { fn dll_filename(base: &str) -> ~str {
return pre() + base + dll_suffix(); return pre() + str::from_slice(base) + dll_suffix();
#[cfg(unix)] #[cfg(unix)]
fn pre() -> ~str { ~"lib" } fn pre() -> ~str { ~"lib" }
@ -379,7 +386,7 @@ fn dll_filename(+base: ~str) -> ~str {
fn self_exe_path() -> option<Path> { fn self_exe_path() -> option<Path> {
#[cfg(target_os = "freebsd")] #[cfg(target_os = "freebsd")]
fn load_self() -> option<Path> { fn load_self() -> option<~str> {
unsafe { unsafe {
import libc::funcs::bsd44::*; import libc::funcs::bsd44::*;
import libc::consts::os::extra::*; import libc::consts::os::extra::*;
@ -395,17 +402,17 @@ fn self_exe_path() -> option<Path> {
} }
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
fn load_self() -> option<Path> { fn load_self() -> option<~str> {
import libc::funcs::posix01::unistd::readlink; import libc::funcs::posix01::unistd::readlink;
do fill_charp_buf() |buf, sz| { do fill_charp_buf() |buf, sz| {
do as_c_charp(~"/proc/self/exe") |proc_self_buf| { do as_c_charp("/proc/self/exe") |proc_self_buf| {
readlink(proc_self_buf, buf, sz) != (-1 as ssize_t) readlink(proc_self_buf, buf, sz) != (-1 as ssize_t)
} }
} }
} }
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
fn load_self() -> option<Path> { fn load_self() -> option<~str> {
// FIXME: remove imports when export globs work properly. #1238 // FIXME: remove imports when export globs work properly. #1238
import libc::funcs::extra::*; import libc::funcs::extra::*;
do fill_charp_buf() |buf, sz| { do fill_charp_buf() |buf, sz| {
@ -415,7 +422,7 @@ fn self_exe_path() -> option<Path> {
} }
#[cfg(windows)] #[cfg(windows)]
fn load_self() -> option<Path> { fn load_self() -> option<~str> {
// FIXME: remove imports when export globs work properly. #1238 // FIXME: remove imports when export globs work properly. #1238
import libc::types::os::arch::extra::*; import libc::types::os::arch::extra::*;
import libc::funcs::extra::kernel32::*; import libc::funcs::extra::kernel32::*;
@ -426,7 +433,7 @@ fn self_exe_path() -> option<Path> {
} }
do option::map(load_self()) |pth| { do option::map(load_self()) |pth| {
path::dirname(pth) + path::path_sep() Path(pth).dir_path()
} }
} }
@ -447,7 +454,7 @@ fn self_exe_path() -> option<Path> {
fn homedir() -> option<Path> { fn homedir() -> option<Path> {
return match getenv(~"HOME") { return match getenv(~"HOME") {
some(p) => if !str::is_empty(p) { some(p) => if !str::is_empty(p) {
some(p) some(Path(p))
} else { } else {
secondary() secondary()
}, },
@ -463,7 +470,7 @@ fn homedir() -> option<Path> {
fn secondary() -> option<Path> { fn secondary() -> option<Path> {
do option::chain(getenv(~"USERPROFILE")) |p| { do option::chain(getenv(~"USERPROFILE")) |p| {
if !str::is_empty(p) { if !str::is_empty(p) {
some(p) some(Path(p))
} else { } else {
none none
} }
@ -484,13 +491,13 @@ fn homedir() -> option<Path> {
fn tmpdir() -> Path { fn tmpdir() -> Path {
return lookup(); return lookup();
fn getenv_nonempty(+v: Path) -> option<Path> { fn getenv_nonempty(v: &str) -> option<Path> {
match getenv(v) { match getenv(v) {
some(x) => some(x) =>
if str::is_empty(x) { if str::is_empty(x) {
none none
} else { } else {
some(x) some(Path(x))
}, },
_ => none _ => none
} }
@ -498,28 +505,29 @@ fn tmpdir() -> Path {
#[cfg(unix)] #[cfg(unix)]
fn lookup() -> Path { fn lookup() -> Path {
option::get_default(getenv_nonempty(~"TMPDIR"), ~"/tmp") option::get_default(getenv_nonempty("TMPDIR"),
Path("/tmp"))
} }
#[cfg(windows)] #[cfg(windows)]
fn lookup() -> Path { fn lookup() -> Path {
option::get_default( option::get_default(
option::or(getenv_nonempty(~"TMP"), option::or(getenv_nonempty("TMP"),
option::or(getenv_nonempty(~"TEMP"), option::or(getenv_nonempty("TEMP"),
option::or(getenv_nonempty(~"USERPROFILE"), option::or(getenv_nonempty("USERPROFILE"),
getenv_nonempty(~"WINDIR")))), getenv_nonempty("WINDIR")))),
~"C:\\Windows") Path("C:\\Windows"))
} }
} }
/// Recursively walk a directory structure /// Recursively walk a directory structure
fn walk_dir(+p: Path, f: fn(Path) -> bool) { fn walk_dir(p: &Path, f: fn((&Path)) -> bool) {
walk_dir_(p, f); walk_dir_(p, f);
fn walk_dir_(+p: Path, f: fn(Path) -> bool) -> bool { fn walk_dir_(p: &Path, f: fn((&Path)) -> bool) -> bool {
let mut keepgoing = true; let mut keepgoing = true;
do list_dir(p).each |q| { do list_dir(p).each |q| {
let path = path::connect(p, q); let path = &p.push(q);
if !f(path) { if !f(path) {
keepgoing = false; keepgoing = false;
false false
@ -541,15 +549,15 @@ fn walk_dir(+p: Path, f: fn(Path) -> bool) {
} }
/// Indicates whether a path represents a directory /// Indicates whether a path represents a directory
fn path_is_dir(+p: Path) -> bool { fn path_is_dir(p: &Path) -> bool {
do str::as_c_str(p) |buf| { do str::as_c_str(p.to_str()) |buf| {
rustrt::rust_path_is_dir(buf) != 0 as c_int rustrt::rust_path_is_dir(buf) != 0 as c_int
} }
} }
/// Indicates whether a path exists /// Indicates whether a path exists
fn path_exists(+p: Path) -> bool { fn path_exists(p: &Path) -> bool {
do str::as_c_str(p) |buf| { do str::as_c_str(p.to_str()) |buf| {
rustrt::rust_path_exists(buf) != 0 as c_int rustrt::rust_path_exists(buf) != 0 as c_int
} }
} }
@ -566,58 +574,50 @@ fn path_exists(+p: Path) -> bool {
// NB: this is here rather than in path because it is a form of environment // NB: this is here rather than in path because it is a form of environment
// querying; what it does depends on the process working directory, not just // querying; what it does depends on the process working directory, not just
// the input paths. // the input paths.
fn make_absolute(+p: Path) -> Path { fn make_absolute(p: &Path) -> Path {
if path::path_is_absolute(p) { if p.is_absolute {
p copy *p
} else { } else {
path::connect(getcwd(), p) getcwd().push_many(p.components)
} }
} }
/// Creates a directory at the specified path /// Creates a directory at the specified path
fn make_dir(+p: Path, mode: c_int) -> bool { fn make_dir(p: &Path, mode: c_int) -> bool {
return mkdir(p, mode); return mkdir(p, mode);
#[cfg(windows)] #[cfg(windows)]
fn mkdir(+p: Path, _mode: c_int) -> bool { fn mkdir(p: &Path, _mode: c_int) -> bool {
// FIXME: remove imports when export globs work properly. #1238 // FIXME: remove imports when export globs work properly. #1238
import libc::types::os::arch::extra::*; import libc::types::os::arch::extra::*;
import libc::funcs::extra::kernel32::*; import libc::funcs::extra::kernel32::*;
import win32::*; import win32::*;
// FIXME: turn mode into something useful? #2623 // FIXME: turn mode into something useful? #2623
do as_utf16_p(p) |buf| { do as_utf16_p(p.to_str()) |buf| {
CreateDirectoryW(buf, unsafe { unsafe::reinterpret_cast(0) }) CreateDirectoryW(buf, unsafe { unsafe::reinterpret_cast(0) })
!= (0 as BOOL) != (0 as BOOL)
} }
} }
#[cfg(unix)] #[cfg(unix)]
fn mkdir(+p: Path, mode: c_int) -> bool { fn mkdir(p: &Path, mode: c_int) -> bool {
do as_c_charp(p) |c| { do as_c_charp(p.to_str()) |c| {
libc::mkdir(c, mode as mode_t) == (0 as c_int) libc::mkdir(c, mode as mode_t) == (0 as c_int)
} }
} }
} }
/// Lists the contents of a directory /// Lists the contents of a directory
fn list_dir(+p: Path) -> ~[~str] { fn list_dir(p: &Path) -> ~[~str] {
#[cfg(unix)] #[cfg(unix)]
fn star(+p: ~str) -> ~str { p } fn star(p: &Path) -> Path { copy *p }
#[cfg(windows)] #[cfg(windows)]
fn star(+p: ~str) -> ~str { fn star(p: &Path) -> Path { p.push("*") }
let pl = str::len(p);
if pl == 0u || (p[pl - 1u] as char != path::consts::path_sep
|| p[pl - 1u] as char != path::consts::alt_path_sep) {
p + path::path_sep() + ~"*"
} else {
p + ~"*"
}
}
do rustrt::rust_list_files(star(p)).filter |filename| { do rustrt::rust_list_files(star(p).to_str()).filter |filename| {
filename != ~"." && filename != ~".." filename != ~"." && filename != ~".."
} }
} }
@ -627,90 +627,84 @@ fn list_dir(+p: Path) -> ~[~str] {
* *
* This version prepends each entry with the directory. * This version prepends each entry with the directory.
*/ */
fn list_dir_path(+p: Path) -> ~[~str] { fn list_dir_path(p: &Path) -> ~[~Path] {
let mut p = p; os::list_dir(p).map(|f| ~p.push(f))
let pl = str::len(p);
if pl == 0u || (p[pl - 1u] as char != path::consts::path_sep
&& p[pl - 1u] as char != path::consts::alt_path_sep) {
p += path::path_sep();
}
os::list_dir(p).map(|f| p + f)
} }
/// Removes a directory at the specified path /// Removes a directory at the specified path
fn remove_dir(+p: Path) -> bool { fn remove_dir(p: &Path) -> bool {
return rmdir(p); return rmdir(p);
#[cfg(windows)] #[cfg(windows)]
fn rmdir(+p: Path) -> bool { fn rmdir(p: &Path) -> bool {
// FIXME: remove imports when export globs work properly. #1238 // FIXME: remove imports when export globs work properly. #1238
import libc::funcs::extra::kernel32::*; import libc::funcs::extra::kernel32::*;
import libc::types::os::arch::extra::*; import libc::types::os::arch::extra::*;
import win32::*; import win32::*;
return do as_utf16_p(p) |buf| { return do as_utf16_p(p.to_str()) |buf| {
RemoveDirectoryW(buf) != (0 as BOOL) RemoveDirectoryW(buf) != (0 as BOOL)
}; };
} }
#[cfg(unix)] #[cfg(unix)]
fn rmdir(+p: Path) -> bool { fn rmdir(p: &Path) -> bool {
return do as_c_charp(p) |buf| { return do as_c_charp(p.to_str()) |buf| {
libc::rmdir(buf) == (0 as c_int) libc::rmdir(buf) == (0 as c_int)
}; };
} }
} }
fn change_dir(+p: Path) -> bool { fn change_dir(p: &Path) -> bool {
return chdir(p); return chdir(p);
#[cfg(windows)] #[cfg(windows)]
fn chdir(+p: Path) -> bool { fn chdir(p: &Path) -> bool {
// FIXME: remove imports when export globs work properly. #1238 // FIXME: remove imports when export globs work properly. #1238
import libc::funcs::extra::kernel32::*; import libc::funcs::extra::kernel32::*;
import libc::types::os::arch::extra::*; import libc::types::os::arch::extra::*;
import win32::*; import win32::*;
return do as_utf16_p(p) |buf| { return do as_utf16_p(p.to_str()) |buf| {
SetCurrentDirectoryW(buf) != (0 as BOOL) SetCurrentDirectoryW(buf) != (0 as BOOL)
}; };
} }
#[cfg(unix)] #[cfg(unix)]
fn chdir(+p: Path) -> bool { fn chdir(p: &Path) -> bool {
return do as_c_charp(p) |buf| { return do as_c_charp(p.to_str()) |buf| {
libc::chdir(buf) == (0 as c_int) libc::chdir(buf) == (0 as c_int)
}; };
} }
} }
/// Copies a file from one location to another /// Copies a file from one location to another
fn copy_file(+from: Path, +to: Path) -> bool { fn copy_file(from: &Path, to: &Path) -> bool {
return do_copy_file(from, to); return do_copy_file(from, to);
#[cfg(windows)] #[cfg(windows)]
fn do_copy_file(+from: Path, +to: Path) -> bool { fn do_copy_file(from: &Path, to: &Path) -> bool {
// FIXME: remove imports when export globs work properly. #1238 // FIXME: remove imports when export globs work properly. #1238
import libc::funcs::extra::kernel32::*; import libc::funcs::extra::kernel32::*;
import libc::types::os::arch::extra::*; import libc::types::os::arch::extra::*;
import win32::*; import win32::*;
return do as_utf16_p(from) |fromp| { return do as_utf16_p(from.to_str()) |fromp| {
do as_utf16_p(to) |top| { do as_utf16_p(to.to_str()) |top| {
CopyFileW(fromp, top, (0 as BOOL)) != (0 as BOOL) CopyFileW(fromp, top, (0 as BOOL)) != (0 as BOOL)
} }
} }
} }
#[cfg(unix)] #[cfg(unix)]
fn do_copy_file(+from: Path, +to: Path) -> bool { fn do_copy_file(from: &Path, to: &Path) -> bool {
let istream = do as_c_charp(from) |fromp| { let istream = do as_c_charp(from.to_str()) |fromp| {
do as_c_charp(~"rb") |modebuf| { do as_c_charp("rb") |modebuf| {
libc::fopen(fromp, modebuf) libc::fopen(fromp, modebuf)
} }
}; };
if istream as uint == 0u { if istream as uint == 0u {
return false; return false;
} }
let ostream = do as_c_charp(to) |top| { let ostream = do as_c_charp(to.to_str()) |top| {
do as_c_charp(~"w+b") |modebuf| { do as_c_charp("w+b") |modebuf| {
libc::fopen(top, modebuf) libc::fopen(top, modebuf)
} }
}; };
@ -746,24 +740,24 @@ fn copy_file(+from: Path, +to: Path) -> bool {
} }
/// Deletes an existing file /// Deletes an existing file
fn remove_file(+p: Path) -> bool { fn remove_file(p: &Path) -> bool {
return unlink(p); return unlink(p);
#[cfg(windows)] #[cfg(windows)]
fn unlink(+p: Path) -> bool { fn unlink(p: &Path) -> bool {
// FIXME (similar to Issue #2006): remove imports when export globs // FIXME (similar to Issue #2006): remove imports when export globs
// work properly. // work properly.
import libc::funcs::extra::kernel32::*; import libc::funcs::extra::kernel32::*;
import libc::types::os::arch::extra::*; import libc::types::os::arch::extra::*;
import win32::*; import win32::*;
return do as_utf16_p(p) |buf| { return do as_utf16_p(p.to_str()) |buf| {
DeleteFileW(buf) != (0 as BOOL) DeleteFileW(buf) != (0 as BOOL)
}; };
} }
#[cfg(unix)] #[cfg(unix)]
fn unlink(+p: Path) -> bool { fn unlink(p: &Path) -> bool {
return do as_c_charp(p) |buf| { return do as_c_charp(p.to_str()) |buf| {
libc::unlink(buf) == (0 as c_int) libc::unlink(buf) == (0 as c_int)
}; };
} }
@ -887,11 +881,7 @@ mod tests {
log(debug, path); log(debug, path);
// Hard to test this function // Hard to test this function
if os::sysname() != ~"win32" { assert path.is_absolute;
assert str::starts_with(path, path::path_sep());
} else {
assert path[1] == ':' as u8;
}
} }
#[test] #[test]
@ -926,10 +916,10 @@ mod tests {
fn test() { fn test() {
assert (!path::path_is_absolute(~"test-path")); assert (!path::path_is_absolute(~"test-path"));
log(debug, ~"Current working directory: " + getcwd()); log(debug, ~"Current working directory: " + getcwd().to_str());
log(debug, make_absolute(~"test-path")); log(debug, make_absolute(&Path("test-path")));
log(debug, make_absolute(~"/usr/bin")); log(debug, make_absolute(&Path("/usr/bin")));
} }
#[test] #[test]
@ -938,7 +928,7 @@ mod tests {
let oldhome = getenv(~"HOME"); let oldhome = getenv(~"HOME");
setenv(~"HOME", ~"/home/MountainView"); setenv(~"HOME", ~"/home/MountainView");
assert os::homedir() == some(~"/home/MountainView"); assert os::homedir() == some(Path("/home/MountainView"));
setenv(~"HOME", ~""); setenv(~"HOME", ~"");
assert os::homedir() == none; assert os::homedir() == none;
@ -959,16 +949,16 @@ mod tests {
assert os::homedir() == none; assert os::homedir() == none;
setenv(~"HOME", ~"/home/MountainView"); setenv(~"HOME", ~"/home/MountainView");
assert os::homedir() == some(~"/home/MountainView"); assert os::homedir() == some(Path("/home/MountainView"));
setenv(~"HOME", ~""); setenv(~"HOME", ~"");
setenv(~"USERPROFILE", ~"/home/MountainView"); setenv(~"USERPROFILE", ~"/home/MountainView");
assert os::homedir() == some(~"/home/MountainView"); assert os::homedir() == some(Path("/home/MountainView"));
setenv(~"HOME", ~"/home/MountainView"); setenv(~"HOME", ~"/home/MountainView");
setenv(~"USERPROFILE", ~"/home/PaloAlto"); setenv(~"USERPROFILE", ~"/home/PaloAlto");
assert os::homedir() == some(~"/home/MountainView"); assert os::homedir() == some(Path("/home/MountainView"));
option::iter(oldhome, |s| setenv(~"HOME", s)); option::iter(oldhome, |s| setenv(~"HOME", s));
option::iter(olduserprofile, option::iter(olduserprofile,
@ -977,16 +967,18 @@ mod tests {
#[test] #[test]
fn tmpdir() { fn tmpdir() {
assert !str::is_empty(os::tmpdir()); assert !str::is_empty(os::tmpdir().to_str());
} }
// Issue #712 // Issue #712
#[test] #[test]
fn test_list_dir_no_invalid_memory_access() { os::list_dir(~"."); } fn test_list_dir_no_invalid_memory_access() {
os::list_dir(&Path("."));
}
#[test] #[test]
fn list_dir() { fn list_dir() {
let dirs = os::list_dir(~"."); let dirs = os::list_dir(&Path("."));
// Just assuming that we've got some contents in the current directory // Just assuming that we've got some contents in the current directory
assert (vec::len(dirs) > 0u); assert (vec::len(dirs) > 0u);
@ -995,34 +987,34 @@ mod tests {
#[test] #[test]
fn path_is_dir() { fn path_is_dir() {
assert (os::path_is_dir(~".")); assert (os::path_is_dir(&Path(".")));
assert (!os::path_is_dir(~"test/stdtest/fs.rs")); assert (!os::path_is_dir(&Path("test/stdtest/fs.rs")));
} }
#[test] #[test]
fn path_exists() { fn path_exists() {
assert (os::path_exists(~".")); assert (os::path_exists(&Path(".")));
assert (!os::path_exists(~"test/nonexistent-bogus-path")); assert (!os::path_exists(&Path("test/nonexistent-bogus-path")));
} }
#[test] #[test]
fn copy_file_does_not_exist() { fn copy_file_does_not_exist() {
assert !os::copy_file(~"test/nonexistent-bogus-path", assert !os::copy_file(&Path("test/nonexistent-bogus-path"),
~"test/other-bogus-path"); &Path("test/other-bogus-path"));
assert !os::path_exists(~"test/other-bogus-path"); assert !os::path_exists(&Path("test/other-bogus-path"));
} }
#[test] #[test]
fn copy_file_ok() { fn copy_file_ok() {
let tempdir = getcwd(); // would like to use $TMPDIR, let tempdir = getcwd(); // would like to use $TMPDIR,
// doesn't seem to work on Linux // doesn't seem to work on Linux
assert (str::len(tempdir) > 0u); assert (str::len(tempdir.to_str()) > 0u);
let in = tempdir + path::path_sep() + ~"in.txt"; let in = tempdir.push("in.txt");
let out = tempdir + path::path_sep() + ~"out.txt"; let out = tempdir.push("out.txt");
/* Write the temp input file */ /* Write the temp input file */
let ostream = do as_c_charp(in) |fromp| { let ostream = do as_c_charp(in.to_str()) |fromp| {
do as_c_charp(~"w+b") |modebuf| { do as_c_charp("w+b") |modebuf| {
libc::fopen(fromp, modebuf) libc::fopen(fromp, modebuf)
} }
}; };
@ -1034,14 +1026,14 @@ mod tests {
(str::len(s) + 1u) as size_t, ostream) (str::len(s) + 1u) as size_t, ostream)
== buf.len() as size_t)}; == buf.len() as size_t)};
assert (libc::fclose(ostream) == (0u as c_int)); assert (libc::fclose(ostream) == (0u as c_int));
let rs = os::copy_file(in, out); let rs = os::copy_file(&in, &out);
if (!os::path_exists(in)) { if (!os::path_exists(&in)) {
fail (fmt!("%s doesn't exist", in)); fail (fmt!("%s doesn't exist", in.to_str()));
} }
assert(rs); assert(rs);
let rslt = run::run_program(~"diff", ~[in, out]); let rslt = run::run_program(~"diff", ~[in.to_str(), out.to_str()]);
assert (rslt == 0); assert (rslt == 0);
assert (remove_file(in)); assert (remove_file(&in));
assert (remove_file(out)); assert (remove_file(&out));
} }
} }

View file

@ -14,73 +14,82 @@ struct PosixPath {
components: ~[~str]; components: ~[~str];
} }
trait Path { trait GenericPath {
static fn from_str((&str)) -> self; static pure fn from_str((&str)) -> self;
fn to_str() -> ~str;
fn dirname() -> ~str; pure fn dirname() -> ~str;
fn filename() -> option<~str>; pure fn filename() -> option<~str>;
fn filestem() -> option<~str>; pure fn filestem() -> option<~str>;
fn filetype() -> option<~str>; pure fn filetype() -> option<~str>;
fn with_dirname((&str)) -> self; pure fn with_dirname((&str)) -> self;
fn with_filename((&str)) -> self; pure fn with_filename((&str)) -> self;
fn with_filestem((&str)) -> self; pure fn with_filestem((&str)) -> self;
fn with_filetype((&str)) -> self; pure fn with_filetype((&str)) -> self;
fn push_components((&[~str])) -> self; pure fn push((&str)) -> self;
fn pop_component() -> self; pure fn push_rel((&self)) -> self;
pure fn push_many((&[~str])) -> self;
pure fn pop() -> self;
}
#[cfg(windows)]
type Path = WindowsPath;
#[cfg(windows)]
pure fn Path(s: &str) -> Path {
from_str::<WindowsPath>(s)
}
#[cfg(unix)]
type Path = PosixPath;
#[cfg(unix)]
pure fn Path(s: &str) -> Path {
from_str::<PosixPath>(s)
}
impl PosixPath : ToStr {
fn to_str() -> ~str {
let mut s = ~"";
if self.is_absolute {
s += "/";
}
s + str::connect(self.components, "/")
}
} }
// FIXME (#3227): when default methods in traits are working, de-duplicate // FIXME (#3227): when default methods in traits are working, de-duplicate
// PosixPath and WindowsPath, most of their methods are common. // PosixPath and WindowsPath, most of their methods are common.
impl PosixPath : GenericPath {
impl PosixPath : Path { static pure fn from_str(s: &str) -> PosixPath {
fn to_str() -> ~str {
match self.filename() {
none => self.dirname(),
some(ref f) =>
if (self.components.len() == 1 &&
!self.is_absolute) {
copy *f
} else {
self.dirname() + "/" + *f
}
}
}
static fn from_str(s: &str) -> PosixPath {
let mut components = str::split_nonempty(s, |c| c == '/'); let mut components = str::split_nonempty(s, |c| c == '/');
let is_absolute = (s.len() != 0 && s[0] == '/' as u8); let is_absolute = (s.len() != 0 && s[0] == '/' as u8);
return PosixPath { is_absolute: is_absolute, return PosixPath { is_absolute: is_absolute,
components: normalize(components) } components: normalize(components) }
} }
fn dirname() -> ~str { pure fn dirname() -> ~str {
let mut s = ~""; unchecked {
if self.is_absolute { let s = self.dir_path().to_str();
s += "/"; if s.len() == 0 {
~"."
} else {
s
}
} }
let mut d = copy self.components;
if d.len() != 0 {
vec::pop(d);
}
s += str::connect(d, "/");
if s.len() == 0 {
s = ~".";
}
return s;
} }
fn filename() -> option<~str> { pure fn filename() -> option<~str> {
match self.components.len() { match self.components.len() {
0 => none, 0 => none,
n => some(copy self.components[n - 1]) n => some(copy self.components[n - 1])
} }
} }
fn filestem() -> option<~str> { pure fn filestem() -> option<~str> {
match self.filename() { match self.filename() {
none => none, none => none,
some(ref f) => { some(ref f) => {
@ -92,7 +101,7 @@ impl PosixPath : Path {
} }
} }
fn filetype() -> option<~str> { pure fn filetype() -> option<~str> {
match self.filename() { match self.filename() {
none => none, none => none,
some(ref f) => { some(ref f) => {
@ -104,20 +113,22 @@ impl PosixPath : Path {
} }
} }
fn with_dirname(d: &str) -> PosixPath { pure fn with_dirname(d: &str) -> PosixPath {
let dpath = from_str::<PosixPath>(d); let dpath = from_str::<PosixPath>(d);
match self.filename() { match self.filename() {
some(ref f) => dpath.push_components(~[copy *f]), some(ref f) => dpath.push(*f),
none => dpath none => dpath
} }
} }
fn with_filename(f: &str) -> PosixPath { pure fn with_filename(f: &str) -> PosixPath {
assert ! str::any(f, |c| windows::is_sep(c as u8)); unchecked {
self.dir_path().push_components(~[str::from_slice(f)]) assert ! str::any(f, |c| windows::is_sep(c as u8));
self.dir_path().push(f)
}
} }
fn with_filestem(s: &str) -> PosixPath { pure fn with_filestem(s: &str) -> PosixPath {
match self.filetype() { match self.filetype() {
none => self.with_filename(s), none => self.with_filename(s),
some(ref t) => some(ref t) =>
@ -125,7 +136,7 @@ impl PosixPath : Path {
} }
} }
fn with_filetype(t: &str) -> PosixPath { pure fn with_filetype(t: &str) -> PosixPath {
if t.len() == 0 { if t.len() == 0 {
match self.filestem() { match self.filestem() {
none => copy self, none => copy self,
@ -141,15 +152,15 @@ impl PosixPath : Path {
} }
} }
fn dir_path() -> PosixPath { pure fn dir_path() -> PosixPath {
if self.components.len() != 0 { if self.components.len() != 0 {
self.pop_component() self.pop()
} else { } else {
copy self copy self
} }
} }
fn file_path() -> PosixPath { pure fn file_path() -> PosixPath {
let cs = match self.filename() { let cs = match self.filename() {
none => ~[], none => ~[],
some(ref f) => ~[copy *f] some(ref f) => ~[copy *f]
@ -158,42 +169,56 @@ impl PosixPath : Path {
components: cs } components: cs }
} }
fn push_components(cs: &[~str]) -> PosixPath { pure fn push_rel(other: &PosixPath) -> PosixPath {
assert !other.is_absolute;
self.push_many(other.components)
}
pure fn push_many(cs: &[~str]) -> PosixPath {
return PosixPath { components: normalize(self.components + cs), return PosixPath { components: normalize(self.components + cs),
..self } ..self }
} }
fn pop_component() -> PosixPath { pure fn push(s: &str) -> PosixPath {
let mut cs = copy self.components; let mut cs = self.components;
if cs.len() != 0 { unchecked { vec::push(cs, move str::from_slice(s)); }
vec::pop(cs); cs = normalize(cs);
} return PosixPath { components: move cs,
return PosixPath { components: cs, ..self } ..self }
} }
pure fn pop() -> PosixPath {
let mut cs = copy self.components;
if cs.len() != 0 {
unchecked { vec::pop(cs); }
}
return PosixPath { components: move cs, ..self }
}
} }
impl WindowsPath : Path { impl WindowsPath : ToStr {
fn to_str() -> ~str { fn to_str() -> ~str {
match self.filename() { let mut s = ~"";
none => self.dirname(), match self.host {
some(ref f) => some(h) => { s += "\\\\"; s += h; }
if (self.components.len() == 1 && none => { }
!self.is_absolute &&
self.host == none &&
self.device == none) {
copy *f
} else {
self.dirname() + "\\" + *f
}
} }
match self.device {
some(d) => { s += d; s += ":"; }
none => { }
}
if self.is_absolute {
s += "\\";
}
s + str::connect(self.components, "\\")
} }
}
static fn from_str(s: &str) -> WindowsPath {
impl WindowsPath : GenericPath {
static pure fn from_str(s: &str) -> WindowsPath {
let host; let host;
let device; let device;
let rest; let rest;
@ -229,38 +254,25 @@ impl WindowsPath : Path {
components: normalize(components) } components: normalize(components) }
} }
fn dirname() -> ~str { pure fn dirname() -> ~str {
let mut s = ~""; unchecked {
match self.host { let s = self.dir_path().to_str();
some(h) => { s += "\\\\"; s += h; } if s.len() == 0 {
none => { } ~"."
} else {
s
}
} }
match self.device {
some(d) => { s += d; s += ":"; }
none => { }
}
if self.is_absolute {
s += "\\";
}
let mut d = copy self.components;
if d.len() != 0 {
vec::pop(d);
}
s += str::connect(d, "\\");
if s.len() == 0 {
s = ~".";
}
return s;
} }
fn filename() -> option<~str> { pure fn filename() -> option<~str> {
match self.components.len() { match self.components.len() {
0 => none, 0 => none,
n => some(copy self.components[n - 1]) n => some(copy self.components[n - 1])
} }
} }
fn filestem() -> option<~str> { pure fn filestem() -> option<~str> {
match self.filename() { match self.filename() {
none => none, none => none,
some(ref f) => { some(ref f) => {
@ -272,7 +284,7 @@ impl WindowsPath : Path {
} }
} }
fn filetype() -> option<~str> { pure fn filetype() -> option<~str> {
match self.filename() { match self.filename() {
none => none, none => none,
some(ref f) => { some(ref f) => {
@ -284,20 +296,20 @@ impl WindowsPath : Path {
} }
} }
fn with_dirname(d: &str) -> WindowsPath { pure fn with_dirname(d: &str) -> WindowsPath {
let dpath = from_str::<WindowsPath>(d); let dpath = from_str::<WindowsPath>(d);
match self.filename() { match self.filename() {
some(ref f) => dpath.push_components(~[copy *f]), some(ref f) => dpath.push(*f),
none => dpath none => dpath
} }
} }
fn with_filename(f: &str) -> WindowsPath { pure fn with_filename(f: &str) -> WindowsPath {
assert ! str::any(f, |c| windows::is_sep(c as u8)); assert ! str::any(f, |c| windows::is_sep(c as u8));
self.dir_path().push_components(~[str::from_slice(f)]) self.dir_path().push(f)
} }
fn with_filestem(s: &str) -> WindowsPath { pure fn with_filestem(s: &str) -> WindowsPath {
match self.filetype() { match self.filetype() {
none => self.with_filename(s), none => self.with_filename(s),
some(ref t) => some(ref t) =>
@ -305,7 +317,7 @@ impl WindowsPath : Path {
} }
} }
fn with_filetype(t: &str) -> WindowsPath { pure fn with_filetype(t: &str) -> WindowsPath {
if t.len() == 0 { if t.len() == 0 {
match self.filestem() { match self.filestem() {
none => copy self, none => copy self,
@ -321,15 +333,15 @@ impl WindowsPath : Path {
} }
} }
fn dir_path() -> WindowsPath { pure fn dir_path() -> WindowsPath {
if self.components.len() != 0 { if self.components.len() != 0 {
self.pop_component() self.pop()
} else { } else {
copy self copy self
} }
} }
fn file_path() -> WindowsPath { pure fn file_path() -> WindowsPath {
let cs = match self.filename() { let cs = match self.filename() {
none => ~[], none => ~[],
some(ref f) => ~[copy *f] some(ref f) => ~[copy *f]
@ -340,30 +352,47 @@ impl WindowsPath : Path {
components: cs } components: cs }
} }
fn push_components(cs: &[~str]) -> WindowsPath { pure fn push_rel(other: &WindowsPath) -> WindowsPath {
assert !other.is_absolute;
self.push_many(other.components)
}
pure fn push_many(cs: &[~str]) -> WindowsPath {
return WindowsPath { components: normalize(self.components + cs), return WindowsPath { components: normalize(self.components + cs),
..self } ..self }
} }
fn pop_component() -> WindowsPath { pure fn push(s: &str) -> WindowsPath {
let mut cs = self.components;
unchecked { vec::push(cs, move str::from_slice(s)); }
cs = normalize(cs);
return WindowsPath { components: move cs,
..self }
}
pure fn pop() -> WindowsPath {
let mut cs = copy self.components; let mut cs = copy self.components;
if cs.len() != 0 { if cs.len() != 0 {
vec::pop(cs); unchecked { vec::pop(cs); }
} }
return WindowsPath { components: cs, ..self } return WindowsPath { components: move cs, ..self }
} }
} }
fn normalize(components: &[~str]) -> ~[~str] { pure fn normalize(components: &[~str]) -> ~[~str] {
let mut cs = ~[]; let mut cs = ~[];
for components.each |c| { unchecked {
if c == ~"." { again; } for components.each |c| {
if c == ~".." && cs.len() != 0 { unchecked {
vec::pop(cs); if c == ~"." && components.len() > 1 { again; }
again; if c == ~".." && cs.len() != 0 {
vec::pop(cs);
again;
}
vec::push(cs, copy c);
}
} }
vec::push(cs, copy c);
} }
cs cs
} }
@ -384,6 +413,7 @@ mod posix {
} }
t(&(mk("hi")), "hi"); t(&(mk("hi")), "hi");
t(&(mk("/lib")), "/lib");
t(&(mk("hi/there")), "hi/there"); t(&(mk("hi/there")), "hi/there");
t(&(mk("hi/there.txt")), "hi/there.txt"); t(&(mk("hi/there.txt")), "hi/there.txt");
@ -401,7 +431,7 @@ mod posix {
"a/foo.txt"); "a/foo.txt");
t(&(mk("a/b/c") t(&(mk("a/b/c")
.push_components([~".."])), "a/b"); .push("..")), "a/b");
t(&(mk("there.txt") t(&(mk("there.txt")
.with_filetype("o")), "there.o"); .with_filetype("o")), "there.o");
@ -425,7 +455,7 @@ mod posix {
"/usr/lib/there.o"); "/usr/lib/there.o");
t(&(mk("/usr/bin/rust") t(&(mk("/usr/bin/rust")
.push_components([~"lib", ~"thingy.so"]) .push_many([~"lib", ~"thingy.so"])
.with_filestem("librustc")), .with_filestem("librustc")),
"/usr/bin/rust/lib/librustc.so"); "/usr/bin/rust/lib/librustc.so");
@ -437,11 +467,11 @@ mod posix {
mod windows { mod windows {
#[inline(always)] #[inline(always)]
fn is_sep(u: u8) -> bool { pure fn is_sep(u: u8) -> bool {
u == '/' as u8 || u == '\\' as u8 u == '/' as u8 || u == '\\' as u8
} }
fn extract_unc_prefix(s: &str) -> option<(~str,~str)> { pure fn extract_unc_prefix(s: &str) -> option<(~str,~str)> {
if (s.len() > 1 && if (s.len() > 1 &&
s[0] == '\\' as u8 && s[0] == '\\' as u8 &&
s[1] == '\\' as u8) { s[1] == '\\' as u8) {
@ -458,14 +488,20 @@ mod windows {
none none
} }
fn extract_drive_prefix(s: &str) -> option<(~str,~str)> { pure fn extract_drive_prefix(s: &str) -> option<(~str,~str)> {
if (s.len() > 1 && unchecked {
libc::isalpha(s[0] as libc::c_int) != 0 && if (s.len() > 1 &&
s[1] == ':' as u8) { libc::isalpha(s[0] as libc::c_int) != 0 &&
let rest = if s.len() == 2 { ~"" } else { s.slice(2, s.len()) }; s[1] == ':' as u8) {
return some((s.slice(0,1), rest)); let rest = if s.len() == 2 {
~""
} else {
s.slice(2, s.len())
};
return some((s.slice(0,1), rest));
}
none
} }
none
} }
#[test] #[test]
@ -532,7 +568,7 @@ mod windows {
"c:\\program files C\\there.o"); "c:\\program files C\\there.o");
t(&(mk("c:\\program files (x86)\\rust") t(&(mk("c:\\program files (x86)\\rust")
.push_components([~"lib", ~"thingy.dll"]) .push_many([~"lib", ~"thingy.dll"])
.with_filename("librustc.dll")), .with_filename("librustc.dll")),
"c:\\program files (x86)\\rust\\lib\\librustc.dll"); "c:\\program files (x86)\\rust\\lib\\librustc.dll");

View file

@ -4,13 +4,14 @@ import core::option;
import option::{none, some}; import option::{none, some};
import rand; import rand;
fn mkdtemp(prefix: ~str, suffix: ~str) -> option<~str> { fn mkdtemp(tmpdir: &Path, suffix: &str) -> option<Path> {
let r = rand::rng(); let r = rand::rng();
let mut i = 0u; let mut i = 0u;
while (i < 1000u) { while (i < 1000u) {
let s = prefix + r.gen_str(16u) + suffix; let p = tmpdir.push(r.gen_str(16u) +
if os::make_dir(s, 0x1c0i32) { // FIXME: u+rwx (#2349) str::from_slice(suffix));
return some(s); if os::make_dir(&p, 0x1c0i32) { // FIXME: u+rwx (#2349)
return some(p);
} }
i += 1u; i += 1u;
} }
@ -19,11 +20,11 @@ fn mkdtemp(prefix: ~str, suffix: ~str) -> option<~str> {
#[test] #[test]
fn test_mkdtemp() { fn test_mkdtemp() {
let r = mkdtemp(~"./", ~"foobar"); let r = mkdtemp(&Path("."), "foobar");
match r { match r {
some(p) => { some(p) => {
os::remove_dir(p); os::remove_dir(&p);
assert(str::ends_with(p, ~"foobar")); assert(str::ends_with(p.to_str(), "foobar"));
} }
_ => assert(false) _ => assert(false)
} }

View file

@ -141,7 +141,7 @@ fn run_tests_console(opts: test_opts,
} }
let log_out = match opts.logfile { let log_out = match opts.logfile {
some(path) => match io::file_writer(path, some(path) => match io::file_writer(&Path(path),
~[io::Create, io::Truncate]) { ~[io::Create, io::Truncate]) {
result::ok(w) => some(w), result::ok(w) => some(w),
result::err(s) => { result::err(s) => {

View file

@ -59,7 +59,7 @@ fn expand_include(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
let args = get_mac_args(cx, sp, arg, 1u, option::some(1u), ~"include"); let args = get_mac_args(cx, sp, arg, 1u, option::some(1u), ~"include");
let file = expr_to_str(cx, args[0], ~"#include_str requires a string"); let file = expr_to_str(cx, args[0], ~"#include_str requires a string");
let p = parse::new_parser_from_file(cx.parse_sess(), cx.cfg(), let p = parse::new_parser_from_file(cx.parse_sess(), cx.cfg(),
res_rel_file(cx, sp, file), &res_rel_file(cx, sp, &Path(file)),
parse::parser::SOURCE_FILE); parse::parser::SOURCE_FILE);
return p.parse_expr(); return p.parse_expr();
} }
@ -70,7 +70,7 @@ fn expand_include_str(cx: ext_ctxt, sp: codemap::span, arg: ast::mac_arg,
let file = expr_to_str(cx, args[0], ~"#include_str requires a string"); let file = expr_to_str(cx, args[0], ~"#include_str requires a string");
let res = io::read_whole_file_str(res_rel_file(cx, sp, file)); let res = io::read_whole_file_str(&res_rel_file(cx, sp, &Path(file)));
match res { match res {
result::ok(_) => { /* Continue. */ } result::ok(_) => { /* Continue. */ }
result::err(e) => { result::err(e) => {
@ -87,7 +87,7 @@ fn expand_include_bin(cx: ext_ctxt, sp: codemap::span, arg: ast::mac_arg,
let file = expr_to_str(cx, args[0], ~"#include_bin requires a string"); let file = expr_to_str(cx, args[0], ~"#include_bin requires a string");
match io::read_whole_file(res_rel_file(cx, sp, file)) { match io::read_whole_file(&res_rel_file(cx, sp, &Path(file))) {
result::ok(src) => { result::ok(src) => {
let u8_exprs = vec::map(src, |char: u8| { let u8_exprs = vec::map(src, |char: u8| {
mk_u8(cx, sp, char) mk_u8(cx, sp, char)
@ -100,14 +100,13 @@ fn expand_include_bin(cx: ext_ctxt, sp: codemap::span, arg: ast::mac_arg,
} }
} }
fn res_rel_file(cx: ext_ctxt, sp: codemap::span, +arg: Path) -> Path { fn res_rel_file(cx: ext_ctxt, sp: codemap::span, arg: &Path) -> Path {
// NB: relative paths are resolved relative to the compilation unit // NB: relative paths are resolved relative to the compilation unit
if !path::path_is_absolute(arg) { if !arg.is_absolute {
let cu = codemap::span_to_filename(sp, cx.codemap()); let cu = Path(codemap::span_to_filename(sp, cx.codemap()));
let dir = path::dirname(cu); cu.dir_path().push_many(arg.components)
return path::connect(dir, arg);
} else { } else {
return arg; copy *arg
} }
} }

View file

@ -49,33 +49,33 @@ fn new_parse_sess_special_handler(sh: span_handler, cm: codemap::codemap)
mut chpos: 0u, mut byte_pos: 0u}; mut chpos: 0u, mut byte_pos: 0u};
} }
fn parse_crate_from_file(input: ~str, cfg: ast::crate_cfg, fn parse_crate_from_file(input: &Path, cfg: ast::crate_cfg,
sess: parse_sess) -> @ast::crate { sess: parse_sess) -> @ast::crate {
if str::ends_with(input, ~".rc") { if input.filetype() == some(~"rc") {
parse_crate_from_crate_file(input, cfg, sess) parse_crate_from_crate_file(input, cfg, sess)
} else if str::ends_with(input, ~".rs") { } else if input.filetype() == some(~"rs") {
parse_crate_from_source_file(input, cfg, sess) parse_crate_from_source_file(input, cfg, sess)
} else { } else {
sess.span_diagnostic.handler().fatal(~"unknown input file type: " + sess.span_diagnostic.handler().fatal(~"unknown input file type: " +
input) input.to_str())
} }
} }
fn parse_crate_from_crate_file(input: ~str, cfg: ast::crate_cfg, fn parse_crate_from_crate_file(input: &Path, cfg: ast::crate_cfg,
sess: parse_sess) -> @ast::crate { sess: parse_sess) -> @ast::crate {
let (p, rdr) = new_parser_etc_from_file(sess, cfg, input, let (p, rdr) = new_parser_etc_from_file(sess, cfg, input,
parser::CRATE_FILE); parser::CRATE_FILE);
let lo = p.span.lo; let lo = p.span.lo;
let prefix = path::dirname(input); let prefix = input.dir_path();
let leading_attrs = p.parse_inner_attrs_and_next(); let leading_attrs = p.parse_inner_attrs_and_next();
let { inner: crate_attrs, next: first_cdir_attr } = leading_attrs; let { inner: crate_attrs, next: first_cdir_attr } = leading_attrs;
let cdirs = p.parse_crate_directives(token::EOF, first_cdir_attr); let cdirs = p.parse_crate_directives(token::EOF, first_cdir_attr);
sess.chpos = rdr.chpos; sess.chpos = rdr.chpos;
sess.byte_pos = sess.byte_pos + rdr.pos; sess.byte_pos = sess.byte_pos + rdr.pos;
let cx = @{sess: sess, cfg: /* FIXME (#2543) */ copy p.cfg}; let cx = @{sess: sess, cfg: /* FIXME (#2543) */ copy p.cfg};
let (companionmod, _) = path::splitext(path::basename(input)); let companionmod = option::map(input.filestem(), |s| Path(s));
let (m, attrs) = eval::eval_crate_directives_to_mod( let (m, attrs) = eval::eval_crate_directives_to_mod(
cx, cdirs, prefix, option::some(companionmod)); cx, cdirs, &prefix, &companionmod);
let mut hi = p.span.hi; let mut hi = p.span.hi;
p.expect(token::EOF); p.expect(token::EOF);
return @ast_util::respan(ast_util::mk_sp(lo, hi), return @ast_util::respan(ast_util::mk_sp(lo, hi),
@ -85,7 +85,7 @@ fn parse_crate_from_crate_file(input: ~str, cfg: ast::crate_cfg,
config: /* FIXME (#2543) */ copy p.cfg}); config: /* FIXME (#2543) */ copy p.cfg});
} }
fn parse_crate_from_source_file(input: ~str, cfg: ast::crate_cfg, fn parse_crate_from_source_file(input: &Path, cfg: ast::crate_cfg,
sess: parse_sess) -> @ast::crate { sess: parse_sess) -> @ast::crate {
let (p, rdr) = new_parser_etc_from_file(sess, cfg, input, let (p, rdr) = new_parser_etc_from_file(sess, cfg, input,
parser::SOURCE_FILE); parser::SOURCE_FILE);
@ -183,7 +183,7 @@ fn new_parser_from_source_str(sess: parse_sess, cfg: ast::crate_cfg,
fn new_parser_etc_from_file(sess: parse_sess, cfg: ast::crate_cfg, fn new_parser_etc_from_file(sess: parse_sess, cfg: ast::crate_cfg,
+path: ~str, ftype: parser::file_type) -> path: &Path, ftype: parser::file_type) ->
(parser, string_reader) { (parser, string_reader) {
let res = io::read_whole_file_str(path); let res = io::read_whole_file_str(path);
match res { match res {
@ -191,14 +191,15 @@ fn new_parser_etc_from_file(sess: parse_sess, cfg: ast::crate_cfg,
result::err(e) => sess.span_diagnostic.handler().fatal(e) result::err(e) => sess.span_diagnostic.handler().fatal(e)
} }
let src = @result::unwrap(res); let src = @result::unwrap(res);
let filemap = codemap::new_filemap(path, src, sess.chpos, sess.byte_pos); let filemap = codemap::new_filemap(path.to_str(), src,
sess.chpos, sess.byte_pos);
sess.cm.files.push(filemap); sess.cm.files.push(filemap);
let srdr = lexer::new_string_reader(sess.span_diagnostic, filemap, let srdr = lexer::new_string_reader(sess.span_diagnostic, filemap,
sess.interner); sess.interner);
return (parser(sess, cfg, srdr as reader, ftype), srdr); return (parser(sess, cfg, srdr as reader, ftype), srdr);
} }
fn new_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg, +path: ~str, fn new_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg, path: &Path,
ftype: parser::file_type) -> parser { ftype: parser::file_type) -> parser {
let (p, _) = new_parser_etc_from_file(sess, cfg, path, ftype); let (p, _) = new_parser_etc_from_file(sess, cfg, path, ftype);
return p; return p;

View file

@ -9,7 +9,7 @@ type ctx =
fn eval_crate_directives(cx: ctx, fn eval_crate_directives(cx: ctx,
cdirs: ~[@ast::crate_directive], cdirs: ~[@ast::crate_directive],
prefix: ~str, prefix: &Path,
&view_items: ~[@ast::view_item], &view_items: ~[@ast::view_item],
&items: ~[@ast::item]) { &items: ~[@ast::item]) {
for cdirs.each |sub_cdir| { for cdirs.each |sub_cdir| {
@ -18,11 +18,8 @@ fn eval_crate_directives(cx: ctx,
} }
fn eval_crate_directives_to_mod(cx: ctx, cdirs: ~[@ast::crate_directive], fn eval_crate_directives_to_mod(cx: ctx, cdirs: ~[@ast::crate_directive],
prefix: ~str, suffix: option<~str>) prefix: &Path, suffix: &option<Path>)
-> (ast::_mod, ~[ast::attribute]) { -> (ast::_mod, ~[ast::attribute]) {
debug!("eval crate prefix: %s", prefix);
debug!("eval crate suffix: %s",
option::get_default(suffix, ~"none"));
let (cview_items, citems, cattrs) let (cview_items, citems, cattrs)
= parse_companion_mod(cx, prefix, suffix); = parse_companion_mod(cx, prefix, suffix);
let mut view_items: ~[@ast::view_item] = ~[]; let mut view_items: ~[@ast::view_item] = ~[];
@ -43,17 +40,17 @@ companion mod is a .rs file with the same name as the directory.
We build the path to the companion mod by combining the prefix and the We build the path to the companion mod by combining the prefix and the
optional suffix then adding the .rs extension. optional suffix then adding the .rs extension.
*/ */
fn parse_companion_mod(cx: ctx, prefix: ~str, suffix: option<~str>) fn parse_companion_mod(cx: ctx, prefix: &Path, suffix: &option<Path>)
-> (~[@ast::view_item], ~[@ast::item], ~[ast::attribute]) { -> (~[@ast::view_item], ~[@ast::item], ~[ast::attribute]) {
fn companion_file(+prefix: ~str, suffix: option<~str>) -> ~str { fn companion_file(prefix: &Path, suffix: &option<Path>) -> Path {
return match suffix { return match *suffix {
option::some(s) => path::connect(prefix, s), option::some(s) => prefix.push_many(s.components),
option::none => prefix option::none => copy *prefix
} + ~".rs"; }.with_filetype("rs");
} }
fn file_exists(path: ~str) -> bool { fn file_exists(path: &Path) -> bool {
// Crude, but there's no lib function for this and I'm not // Crude, but there's no lib function for this and I'm not
// up to writing it just now // up to writing it just now
match io::file_reader(path) { match io::file_reader(path) {
@ -62,8 +59,7 @@ fn parse_companion_mod(cx: ctx, prefix: ~str, suffix: option<~str>)
} }
} }
let modpath = companion_file(prefix, suffix); let modpath = &companion_file(prefix, suffix);
debug!("looking for companion mod %s", modpath);
if file_exists(modpath) { if file_exists(modpath) {
debug!("found companion mod"); debug!("found companion mod");
let (p0, r0) = new_parser_etc_from_file(cx.sess, cx.cfg, let (p0, r0) = new_parser_etc_from_file(cx.sess, cx.cfg,
@ -85,19 +81,21 @@ fn cdir_path_opt(default: ~str, attrs: ~[ast::attribute]) -> ~str {
} }
} }
fn eval_crate_directive(cx: ctx, cdir: @ast::crate_directive, prefix: ~str, fn eval_crate_directive(cx: ctx, cdir: @ast::crate_directive, prefix: &Path,
&view_items: ~[@ast::view_item], &view_items: ~[@ast::view_item],
&items: ~[@ast::item]) { &items: ~[@ast::item]) {
match cdir.node { match cdir.node {
ast::cdir_src_mod(id, attrs) => { ast::cdir_src_mod(id, attrs) => {
let file_path = cdir_path_opt((cx.sess.interner.get(id) + ~".rs"), let file_path = Path(cdir_path_opt(
attrs); cx.sess.interner.get(id) + ~".rs", attrs));
let full_path = let full_path = if file_path.is_absolute {
if path::path_is_absolute(file_path) { copy file_path
file_path } else {
} else { prefix + path::path_sep() + file_path }; prefix.push_many(file_path.components)
};
let (p0, r0) = let (p0, r0) =
new_parser_etc_from_file(cx.sess, cx.cfg, full_path, SOURCE_FILE); new_parser_etc_from_file(cx.sess, cx.cfg,
&full_path, SOURCE_FILE);
let inner_attrs = p0.parse_inner_attrs_and_next(); let inner_attrs = p0.parse_inner_attrs_and_next();
let mod_attrs = vec::append(attrs, inner_attrs.inner); let mod_attrs = vec::append(attrs, inner_attrs.inner);
let first_item_outer_attrs = inner_attrs.next; let first_item_outer_attrs = inner_attrs.next;
@ -112,13 +110,14 @@ fn eval_crate_directive(cx: ctx, cdir: @ast::crate_directive, prefix: ~str,
vec::push(items, i); vec::push(items, i);
} }
ast::cdir_dir_mod(id, cdirs, attrs) => { ast::cdir_dir_mod(id, cdirs, attrs) => {
let path = cdir_path_opt(*cx.sess.interner.get(id), attrs); let path = Path(cdir_path_opt(*cx.sess.interner.get(id), attrs));
let full_path = let full_path = if path.is_absolute {
if path::path_is_absolute(path) { copy path
path } else {
} else { prefix + path::path_sep() + path }; prefix.push_many(path.components)
};
let (m0, a0) = eval_crate_directives_to_mod( let (m0, a0) = eval_crate_directives_to_mod(
cx, cdirs, full_path, none); cx, cdirs, &full_path, &none);
let i = let i =
@{ident: /* FIXME (#2543) */ copy id, @{ident: /* FIXME (#2543) */ copy id,
attrs: vec::append(attrs, a0), attrs: vec::append(attrs, a0),

View file

@ -57,18 +57,7 @@ mod write {
return false; return false;
} }
// Decides what to call an intermediate file, given the name of the output fn run_passes(sess: session, llmod: ModuleRef, output: &Path) {
// and the extension to use.
fn mk_intermediate_name(output_path: ~str, extension: ~str) ->
~str unsafe {
let stem = match str::find_char(output_path, '.') {
some(dot_pos) => str::slice(output_path, 0u, dot_pos),
none => output_path
};
return stem + ~"." + extension;
}
fn run_passes(sess: session, llmod: ModuleRef, output: ~str) {
let opts = sess.opts; let opts = sess.opts;
if sess.time_llvm_passes() { llvm::LLVMRustEnableTimePasses(); } if sess.time_llvm_passes() { llvm::LLVMRustEnableTimePasses(); }
let mut pm = mk_pass_manager(); let mut pm = mk_pass_manager();
@ -85,15 +74,15 @@ mod write {
match opts.output_type { match opts.output_type {
output_type_bitcode => { output_type_bitcode => {
if opts.optimize != session::No { if opts.optimize != session::No {
let filename = mk_intermediate_name(output, ~"no-opt.bc"); let filename = output.with_filetype("no-opt.bc");
str::as_c_str(filename, |buf| { str::as_c_str(filename.to_str(), |buf| {
llvm::LLVMWriteBitcodeToFile(llmod, buf) llvm::LLVMWriteBitcodeToFile(llmod, buf)
}); });
} }
} }
_ => { _ => {
let filename = mk_intermediate_name(output, ~"bc"); let filename = output.with_filetype("bc");
str::as_c_str(filename, |buf| { str::as_c_str(filename.to_str(), |buf| {
llvm::LLVMWriteBitcodeToFile(llmod, buf) llvm::LLVMWriteBitcodeToFile(llmod, buf)
}); });
} }
@ -163,9 +152,9 @@ mod write {
if opts.save_temps { if opts.save_temps {
// Always output the bitcode file with --save-temps // Always output the bitcode file with --save-temps
let filename = mk_intermediate_name(output, ~"opt.bc"); let filename = output.with_filetype("opt.bc");
llvm::LLVMRunPassManager(pm.llpm, llmod); llvm::LLVMRunPassManager(pm.llpm, llmod);
str::as_c_str(filename, |buf| { str::as_c_str(filename.to_str(), |buf| {
llvm::LLVMWriteBitcodeToFile(llmod, buf) llvm::LLVMWriteBitcodeToFile(llmod, buf)
}); });
pm = mk_pass_manager(); pm = mk_pass_manager();
@ -175,7 +164,7 @@ mod write {
let _: () = str::as_c_str( let _: () = str::as_c_str(
sess.targ_cfg.target_strs.target_triple, sess.targ_cfg.target_strs.target_triple,
|buf_t| { |buf_t| {
str::as_c_str(output, |buf_o| { str::as_c_str(output.to_str(), |buf_o| {
WriteOutputFile( WriteOutputFile(
sess, sess,
pm.llpm, pm.llpm,
@ -197,7 +186,7 @@ mod write {
let _: () = str::as_c_str( let _: () = str::as_c_str(
sess.targ_cfg.target_strs.target_triple, sess.targ_cfg.target_strs.target_triple,
|buf_t| { |buf_t| {
str::as_c_str(output, |buf_o| { str::as_c_str(output.to_str(), |buf_o| {
WriteOutputFile( WriteOutputFile(
sess, sess,
pm.llpm, pm.llpm,
@ -217,7 +206,7 @@ mod write {
let _: () = str::as_c_str( let _: () = str::as_c_str(
sess.targ_cfg.target_strs.target_triple, sess.targ_cfg.target_strs.target_triple,
|buf_t| { |buf_t| {
str::as_c_str(output, |buf_o| { str::as_c_str(output.to_str(), |buf_o| {
WriteOutputFile( WriteOutputFile(
sess, sess,
pm.llpm, pm.llpm,
@ -239,13 +228,13 @@ mod write {
if opts.output_type == output_type_llvm_assembly { if opts.output_type == output_type_llvm_assembly {
// Given options "-S --emit-llvm": output LLVM assembly // Given options "-S --emit-llvm": output LLVM assembly
str::as_c_str(output, |buf_o| { str::as_c_str(output.to_str(), |buf_o| {
llvm::LLVMRustAddPrintModulePass(pm.llpm, llmod, buf_o)}); llvm::LLVMRustAddPrintModulePass(pm.llpm, llmod, buf_o)});
} else { } else {
// If only a bitcode file is asked for by using the '--emit-llvm' // If only a bitcode file is asked for by using the '--emit-llvm'
// flag, then output it here // flag, then output it here
llvm::LLVMRunPassManager(pm.llpm, llmod); llvm::LLVMRunPassManager(pm.llpm, llmod);
str::as_c_str(output, str::as_c_str(output.to_str(),
|buf| llvm::LLVMWriteBitcodeToFile(llmod, buf) ); |buf| llvm::LLVMWriteBitcodeToFile(llmod, buf) );
} }
@ -306,7 +295,7 @@ mod write {
* *
*/ */
fn build_link_meta(sess: session, c: ast::crate, output: ~str, fn build_link_meta(sess: session, c: ast::crate, output: &Path,
symbol_hasher: &hash::State) -> link_meta { symbol_hasher: &hash::State) -> link_meta {
type provided_metas = type provided_metas =
@ -384,21 +373,16 @@ fn build_link_meta(sess: session, c: ast::crate, output: ~str,
} }
fn crate_meta_name(sess: session, _crate: ast::crate, fn crate_meta_name(sess: session, _crate: ast::crate,
output: ~str, metas: provided_metas) -> ~str { output: &Path, metas: provided_metas) -> ~str {
return match metas.name { return match metas.name {
some(v) => v, some(v) => v,
none => { none => {
let name = let name = match output.filestem() {
{ none => sess.fatal(fmt!("output file name `%s` doesn't\
let mut os = appear to have a stem",
str::split_char(path::basename(output), '.'); output.to_str())),
if (vec::len(os) < 2u) { some(s) => s
sess.fatal(fmt!("output file name `%s` doesn't\ };
appear to have an extension", output));
}
vec::pop(os);
str::connect(os, ~".")
};
warn_missing(sess, ~"name", name); warn_missing(sess, ~"name", name);
name name
} }
@ -552,31 +536,17 @@ fn mangle_internal_name_by_seq(ccx: @crate_ctxt, flav: ~str) -> ~str {
// If the user wants an exe generated we need to invoke // If the user wants an exe generated we need to invoke
// cc to link the object file with some libs // cc to link the object file with some libs
fn link_binary(sess: session, fn link_binary(sess: session,
obj_filename: ~str, obj_filename: &Path,
out_filename: ~str, out_filename: &Path,
lm: link_meta) { lm: link_meta) {
// Converts a library file name into a cc -l argument // Converts a library file-stem into a cc -l argument
fn unlib(config: @session::config, filename: ~str) -> ~str unsafe { fn unlib(config: @session::config, stem: ~str) -> ~str {
let rmlib = fn@(filename: ~str) -> ~str { if stem.starts_with("lib") &&
let found = str::find_str(filename, ~"lib"); config.os != session::os_win32 {
if config.os == session::os_macos || stem.slice(3, stem.len())
(config.os == session::os_linux || } else {
config.os == session::os_freebsd) && stem
option::is_some(found) && option::get(found) == 0u {
return str::slice(filename, 3u, str::len(filename));
} else { return filename; }
};
fn rmext(filename: ~str) -> ~str {
let mut parts = str::split_char(filename, '.');
vec::pop(parts);
return str::connect(parts, ~".");
} }
return match config.os {
session::os_macos => rmext(rmlib(filename)),
session::os_linux => rmext(rmlib(filename)),
session::os_freebsd => rmext(rmlib(filename)),
_ => rmext(filename)
};
} }
let output = if sess.building_library { let output = if sess.building_library {
@ -585,17 +555,19 @@ fn link_binary(sess: session,
lm.name, lm.extras_hash, lm.vers)); lm.name, lm.extras_hash, lm.vers));
debug!("link_meta.name: %s", lm.name); debug!("link_meta.name: %s", lm.name);
debug!("long_libname: %s", long_libname); debug!("long_libname: %s", long_libname);
debug!("out_filename: %s", out_filename); debug!("out_filename: %s", out_filename.to_str());
debug!("dirname(out_filename): %s", path::dirname(out_filename)); debug!("dirname(out_filename): %s", out_filename.dir_path().to_str());
path::connect(path::dirname(out_filename), long_libname) out_filename.dir_path().push(long_libname)
} else { out_filename }; } else {
*out_filename
};
log(debug, ~"output: " + output); log(debug, ~"output: " + output.to_str());
// The default library location, we need this to find the runtime. // The default library location, we need this to find the runtime.
// The location of crates will be determined as needed. // The location of crates will be determined as needed.
let stage: ~str = ~"-L" + sess.filesearch.get_target_lib_path(); let stage: ~str = ~"-L" + sess.filesearch.get_target_lib_path().to_str();
// In the future, FreeBSD will use clang as default compiler. // In the future, FreeBSD will use clang as default compiler.
// It would be flexible to use cc (system's default C compiler) // It would be flexible to use cc (system's default C compiler)
@ -609,27 +581,28 @@ fn link_binary(sess: session,
let mut cc_args = let mut cc_args =
vec::append(~[stage], sess.targ_cfg.target_strs.cc_args); vec::append(~[stage], sess.targ_cfg.target_strs.cc_args);
vec::push(cc_args, ~"-o"); vec::push(cc_args, ~"-o");
vec::push(cc_args, output); vec::push(cc_args, output.to_str());
vec::push(cc_args, obj_filename); vec::push(cc_args, obj_filename.to_str());
let mut lib_cmd; let mut lib_cmd;
let os = sess.targ_cfg.os; let os = sess.targ_cfg.os;
if os == session::os_macos { if os == session::os_macos {
lib_cmd = ~"-dynamiclib"; lib_cmd = ~"-dynamiclib";
} else { lib_cmd = ~"-shared"; } } else {
lib_cmd = ~"-shared";
}
// # Crate linking // # Crate linking
let cstore = sess.cstore; let cstore = sess.cstore;
for cstore::get_used_crate_files(cstore).each |cratepath| { for cstore::get_used_crate_files(cstore).each |cratepath| {
if str::ends_with(cratepath, ~".rlib") { if cratepath.filetype() == some(~"rlib") {
vec::push(cc_args, cratepath); vec::push(cc_args, cratepath.to_str());
again; again;
} }
let cratepath = cratepath; let dir = cratepath.dirname();
let dir = path::dirname(cratepath);
if dir != ~"" { vec::push(cc_args, ~"-L" + dir); } if dir != ~"" { vec::push(cc_args, ~"-L" + dir); }
let libarg = unlib(sess.targ_cfg, path::basename(cratepath)); let libarg = unlib(sess.targ_cfg, option::get(cratepath.filestem()));
vec::push(cc_args, ~"-l" + libarg); vec::push(cc_args, ~"-l" + libarg);
} }
@ -645,7 +618,7 @@ fn link_binary(sess: session,
// forces to make sure that library can be found at runtime. // forces to make sure that library can be found at runtime.
let addl_paths = sess.opts.addl_lib_search_paths; let addl_paths = sess.opts.addl_lib_search_paths;
for addl_paths.each |path| { vec::push(cc_args, ~"-L" + path); } for addl_paths.each |path| { vec::push(cc_args, ~"-L" + path.to_str()); }
// The names of the extern libraries // The names of the extern libraries
let used_libs = cstore::get_used_libraries(cstore); let used_libs = cstore::get_used_libraries(cstore);
@ -658,7 +631,7 @@ fn link_binary(sess: session,
// be rpathed // be rpathed
if sess.targ_cfg.os == session::os_macos { if sess.targ_cfg.os == session::os_macos {
vec::push(cc_args, ~"-Wl,-install_name,@rpath/" vec::push(cc_args, ~"-Wl,-install_name,@rpath/"
+ path::basename(output)); + option::get(output.filename()));
} }
} }
@ -701,7 +674,7 @@ fn link_binary(sess: session,
// FIXME (#2397): At some point we want to rpath our guesses as to where // FIXME (#2397): At some point we want to rpath our guesses as to where
// extern libraries might live, based on the addl_lib_search_paths // extern libraries might live, based on the addl_lib_search_paths
vec::push_all(cc_args, rpath::get_rpath_flags(sess, output)); vec::push_all(cc_args, rpath::get_rpath_flags(sess, &output));
debug!("%s link args: %s", cc_prog, str::connect(cc_args, ~" ")); debug!("%s link args: %s", cc_prog, str::connect(cc_args, ~" "));
// We run 'cc' here // We run 'cc' here
@ -717,14 +690,14 @@ fn link_binary(sess: session,
// Clean up on Darwin // Clean up on Darwin
if sess.targ_cfg.os == session::os_macos { if sess.targ_cfg.os == session::os_macos {
run::run_program(~"dsymutil", ~[output]); run::run_program(~"dsymutil", ~[output.to_str()]);
} }
// Remove the temporary object file if we aren't saving temps // Remove the temporary object file if we aren't saving temps
if !sess.opts.save_temps { if !sess.opts.save_temps {
if ! os::remove_file(obj_filename) { if ! os::remove_file(obj_filename) {
sess.warn(fmt!("failed to delete object file `%s`", sess.warn(fmt!("failed to delete object file `%s`",
obj_filename)); obj_filename.to_str()));
} }
} }
} }

View file

@ -13,7 +13,7 @@ pure fn not_win32(os: session::os) -> bool {
} }
} }
fn get_rpath_flags(sess: session::session, out_filename: ~str) -> ~[~str] { fn get_rpath_flags(sess: session::session, out_filename: &Path) -> ~[~str] {
let os = sess.targ_cfg.os; let os = sess.targ_cfg.os;
// No rpath on windows // No rpath on windows
@ -23,7 +23,6 @@ fn get_rpath_flags(sess: session::session, out_filename: ~str) -> ~[~str] {
debug!("preparing the RPATH!"); debug!("preparing the RPATH!");
let cwd = os::getcwd();
let sysroot = sess.filesearch.sysroot(); let sysroot = sess.filesearch.sysroot();
let output = out_filename; let output = out_filename;
let libs = cstore::get_used_crate_files(sess.cstore); let libs = cstore::get_used_crate_files(sess.cstore);
@ -32,50 +31,48 @@ fn get_rpath_flags(sess: session::session, out_filename: ~str) -> ~[~str] {
let libs = vec::append_one(libs, get_sysroot_absolute_rt_lib(sess)); let libs = vec::append_one(libs, get_sysroot_absolute_rt_lib(sess));
let target_triple = sess.opts.target_triple; let target_triple = sess.opts.target_triple;
let rpaths = get_rpaths(os, cwd, sysroot, output, libs, target_triple); let rpaths = get_rpaths(os, &sysroot, output, libs, target_triple);
rpaths_to_flags(rpaths) rpaths_to_flags(rpaths)
} }
fn get_sysroot_absolute_rt_lib(sess: session::session) -> path::Path { fn get_sysroot_absolute_rt_lib(sess: session::session) -> Path {
let mut path = vec::append(~[sess.filesearch.sysroot()], let r = filesearch::relative_target_lib_path(sess.opts.target_triple);
filesearch::relative_target_lib_path( sess.filesearch.sysroot().push_rel(&r).push(os::dll_filename("rustrt"))
sess.opts.target_triple));
vec::push(path, os::dll_filename(~"rustrt"));
path::connect_many(path)
} }
fn rpaths_to_flags(rpaths: ~[~str]) -> ~[~str] { fn rpaths_to_flags(rpaths: &[Path]) -> ~[~str] {
vec::map(rpaths, |rpath| fmt!("-Wl,-rpath,%s",rpath) ) vec::map(rpaths, |rpath| fmt!("-Wl,-rpath,%s",rpath.to_str()))
} }
fn get_rpaths(os: session::os, cwd: path::Path, sysroot: path::Path, fn get_rpaths(os: session::os,
output: path::Path, libs: ~[path::Path], sysroot: &Path,
target_triple: ~str) -> ~[~str] { output: &Path,
debug!("cwd: %s", cwd); libs: &[Path],
debug!("sysroot: %s", sysroot); target_triple: &str) -> ~[Path] {
debug!("output: %s", output); debug!("sysroot: %s", sysroot.to_str());
debug!("output: %s", output.to_str());
debug!("libs:"); debug!("libs:");
for libs.each |libpath| { for libs.each |libpath| {
debug!(" %s", libpath); debug!(" %s", libpath.to_str());
} }
debug!("target_triple: %s", target_triple); debug!("target_triple: %s", target_triple);
// Use relative paths to the libraries. Binaries can be moved // Use relative paths to the libraries. Binaries can be moved
// as long as they maintain the relative relationship to the // as long as they maintain the relative relationship to the
// crates they depend on. // crates they depend on.
let rel_rpaths = get_rpaths_relative_to_output(os, cwd, output, libs); let rel_rpaths = get_rpaths_relative_to_output(os, output, libs);
// Make backup absolute paths to the libraries. Binaries can // Make backup absolute paths to the libraries. Binaries can
// be moved as long as the crates they link against don't move. // be moved as long as the crates they link against don't move.
let abs_rpaths = get_absolute_rpaths(cwd, libs); let abs_rpaths = get_absolute_rpaths(libs);
// And a final backup rpath to the global library location. // And a final backup rpath to the global library location.
let fallback_rpaths = ~[get_install_prefix_rpath(cwd, target_triple)]; let fallback_rpaths = ~[get_install_prefix_rpath(target_triple)];
fn log_rpaths(desc: ~str, rpaths: ~[~str]) { fn log_rpaths(desc: &str, rpaths: &[Path]) {
debug!("%s rpaths:", desc); debug!("%s rpaths:", desc);
for rpaths.each |rpath| { for rpaths.each |rpath| {
debug!(" %s", rpath); debug!(" %s", rpath.to_str());
} }
} }
@ -93,43 +90,37 @@ fn get_rpaths(os: session::os, cwd: path::Path, sysroot: path::Path,
} }
fn get_rpaths_relative_to_output(os: session::os, fn get_rpaths_relative_to_output(os: session::os,
cwd: path::Path, output: &Path,
output: path::Path, libs: &[Path]) -> ~[Path] {
libs: ~[path::Path]) -> ~[~str] {
vec::map(libs, |a| { vec::map(libs, |a| {
get_rpath_relative_to_output(os, cwd, output, a) get_rpath_relative_to_output(os, output, &a)
}) })
} }
fn get_rpath_relative_to_output(os: session::os, fn get_rpath_relative_to_output(os: session::os,
cwd: path::Path, output: &Path,
output: path::Path, lib: &Path) -> Path {
&&lib: path::Path) -> ~str {
assert not_win32(os); assert not_win32(os);
// Mac doesn't appear to support $ORIGIN // Mac doesn't appear to support $ORIGIN
let prefix = match os { let prefix = match os {
session::os_linux => ~"$ORIGIN" + path::path_sep(), session::os_linux | session::os_freebsd => "$ORIGIN",
session::os_freebsd => ~"$ORIGIN" + path::path_sep(), session::os_macos => "@executable_path",
session::os_macos => ~"@executable_path" + path::path_sep(),
session::os_win32 => core::unreachable() session::os_win32 => core::unreachable()
}; };
prefix + get_relative_to( Path(prefix).push_rel(&get_relative_to(&os::make_absolute(output),
get_absolute(cwd, output), &os::make_absolute(lib)))
get_absolute(cwd, lib))
} }
// Find the relative path from one file to another // Find the relative path from one file to another
fn get_relative_to(abs1: path::Path, abs2: path::Path) -> path::Path { fn get_relative_to(abs1: &Path, abs2: &Path) -> Path {
assert path::path_is_absolute(abs1); assert abs1.is_absolute;
assert path::path_is_absolute(abs2); assert abs2.is_absolute;
debug!("finding relative path from %s to %s", debug!("finding relative path from %s to %s",
abs1, abs2); abs1.to_str(), abs2.to_str());
let normal1 = path::normalize(abs1); let split1 = abs1.components;
let normal2 = path::normalize(abs2); let split2 = abs2.components;
let split1 = path::split(normal1);
let split2 = path::split(normal2);
let len1 = vec::len(split1); let len1 = vec::len(split1);
let len2 = vec::len(split2); let len2 = vec::len(split2);
assert len1 > 0u; assert len1 > 0u;
@ -148,48 +139,39 @@ fn get_relative_to(abs1: path::Path, abs2: path::Path) -> path::Path {
vec::push_all(path, vec::view(split2, start_idx, len2 - 1u)); vec::push_all(path, vec::view(split2, start_idx, len2 - 1u));
if vec::is_not_empty(path) { if vec::is_not_empty(path) {
return path::connect_many(path); return Path("").push_many(path);
} else { } else {
return ~"."; return Path(".");
} }
} }
fn get_absolute_rpaths(cwd: path::Path, libs: ~[path::Path]) -> ~[~str] { fn get_absolute_rpaths(libs: &[Path]) -> ~[Path] {
vec::map(libs, |a| get_absolute_rpath(cwd, a) ) vec::map(libs, |a| get_absolute_rpath(&a) )
} }
fn get_absolute_rpath(cwd: path::Path, &&lib: path::Path) -> ~str { fn get_absolute_rpath(lib: &Path) -> Path {
path::dirname(get_absolute(cwd, lib)) os::make_absolute(lib).dir_path()
} }
fn get_absolute(cwd: path::Path, lib: path::Path) -> path::Path { fn get_install_prefix_rpath(target_triple: &str) -> Path {
if path::path_is_absolute(lib) {
lib
} else {
path::connect(cwd, lib)
}
}
fn get_install_prefix_rpath(cwd: path::Path, target_triple: ~str) -> ~str {
let install_prefix = env!("CFG_PREFIX"); let install_prefix = env!("CFG_PREFIX");
if install_prefix == ~"" { if install_prefix == ~"" {
fail ~"rustc compiled without CFG_PREFIX environment variable"; fail ~"rustc compiled without CFG_PREFIX environment variable";
} }
let path = vec::append( let tlib = filesearch::relative_target_lib_path(target_triple);
~[install_prefix], os::make_absolute(&Path(install_prefix).push_rel(&tlib))
filesearch::relative_target_lib_path(target_triple));
get_absolute(cwd, path::connect_many(path))
} }
fn minimize_rpaths(rpaths: ~[~str]) -> ~[~str] { fn minimize_rpaths(rpaths: &[Path]) -> ~[Path] {
let set = map::str_hash::<()>(); let set = map::str_hash::<()>();
let mut minimized = ~[]; let mut minimized = ~[];
for rpaths.each |rpath| { for rpaths.each |rpath| {
if !set.contains_key(rpath) { let s = rpath.to_str();
if !set.contains_key(s) {
vec::push(minimized, rpath); vec::push(minimized, rpath);
set.insert(rpath, ()); set.insert(s, ());
} }
} }
return minimized; return minimized;
@ -199,116 +181,112 @@ fn minimize_rpaths(rpaths: ~[~str]) -> ~[~str] {
mod test { mod test {
#[test] #[test]
fn test_rpaths_to_flags() { fn test_rpaths_to_flags() {
let flags = rpaths_to_flags(~[~"path1", ~"path2"]); let flags = rpaths_to_flags(~[Path("path1"),
Path("path2")]);
assert flags == ~[~"-Wl,-rpath,path1", ~"-Wl,-rpath,path2"]; assert flags == ~[~"-Wl,-rpath,path1", ~"-Wl,-rpath,path2"];
} }
#[test]
fn test_get_absolute1() {
let cwd = ~"/dir";
let lib = ~"some/path/lib";
let res = get_absolute(cwd, lib);
assert res == ~"/dir/some/path/lib";
}
#[test]
fn test_get_absolute2() {
let cwd = ~"/dir";
let lib = ~"/some/path/lib";
let res = get_absolute(cwd, lib);
assert res == ~"/some/path/lib";
}
#[test] #[test]
fn test_prefix_rpath() { fn test_prefix_rpath() {
let res = get_install_prefix_rpath(~"/usr/lib", ~"triple"); let res = get_install_prefix_rpath("triple");
let d = path::connect(env!("CFG_PREFIX"), ~"/lib/rustc/triple/lib"); let d = Path(env!("CFG_PREFIX"))
assert str::ends_with(res, d); .push_rel(&Path("lib/rustc/triple/lib"));
debug!("test_prefix_path: %s vs. %s",
res.to_str(),
d.to_str());
assert str::ends_with(res.to_str(), d.to_str());
} }
#[test] #[test]
fn test_prefix_rpath_abs() { fn test_prefix_rpath_abs() {
let res = get_install_prefix_rpath(~"/usr/lib", ~"triple"); let res = get_install_prefix_rpath("triple");
assert path::path_is_absolute(res); assert res.is_absolute;
} }
#[test] #[test]
fn test_minimize1() { fn test_minimize1() {
let res = minimize_rpaths(~[~"rpath1", ~"rpath2", ~"rpath1"]); let res = minimize_rpaths([Path("rpath1"),
assert res == ~[~"rpath1", ~"rpath2"]; Path("rpath2"),
Path("rpath1")]);
assert res == ~[Path("rpath1"), Path("rpath2")];
} }
#[test] #[test]
fn test_minimize2() { fn test_minimize2() {
let res = minimize_rpaths(~[~"1a", ~"2", ~"2", ~"1a", ~"4a", let res = minimize_rpaths(~[Path("1a"), Path("2"), Path("2"),
~"1a", ~"2", ~"3", ~"4a", ~"3"]); Path("1a"), Path("4a"),Path("1a"),
assert res == ~[~"1a", ~"2", ~"4a", ~"3"]; Path("2"), Path("3"), Path("4a"),
Path("3")]);
assert res == ~[Path("1a"), Path("2"), Path("4a"), Path("3")];
} }
#[test] #[test]
fn test_relative_to1() { fn test_relative_to1() {
let p1 = ~"/usr/bin/rustc"; let p1 = Path("/usr/bin/rustc");
let p2 = ~"/usr/lib/mylib"; let p2 = Path("/usr/lib/mylib");
let res = get_relative_to(p1, p2); let res = get_relative_to(&p1, &p2);
assert res == ~"../lib"; assert res == Path("../lib");
} }
#[test] #[test]
fn test_relative_to2() { fn test_relative_to2() {
let p1 = ~"/usr/bin/rustc"; let p1 = Path("/usr/bin/rustc");
let p2 = ~"/usr/bin/../lib/mylib"; let p2 = Path("/usr/bin/../lib/mylib");
let res = get_relative_to(p1, p2); let res = get_relative_to(&p1, &p2);
assert res == ~"../lib"; assert res == Path("../lib");
} }
#[test] #[test]
fn test_relative_to3() { fn test_relative_to3() {
let p1 = ~"/usr/bin/whatever/rustc"; let p1 = Path("/usr/bin/whatever/rustc");
let p2 = ~"/usr/lib/whatever/mylib"; let p2 = Path("/usr/lib/whatever/mylib");
let res = get_relative_to(p1, p2); let res = get_relative_to(&p1, &p2);
assert res == ~"../../lib/whatever"; assert res == Path("../../lib/whatever");
} }
#[test] #[test]
fn test_relative_to4() { fn test_relative_to4() {
let p1 = ~"/usr/bin/whatever/../rustc"; let p1 = Path("/usr/bin/whatever/../rustc");
let p2 = ~"/usr/lib/whatever/mylib"; let p2 = Path("/usr/lib/whatever/mylib");
let res = get_relative_to(p1, p2); let res = get_relative_to(&p1, &p2);
assert res == ~"../lib/whatever"; assert res == Path("../lib/whatever");
} }
#[test] #[test]
fn test_relative_to5() { fn test_relative_to5() {
let p1 = ~"/usr/bin/whatever/../rustc"; let p1 = Path("/usr/bin/whatever/../rustc");
let p2 = ~"/usr/lib/whatever/../mylib"; let p2 = Path("/usr/lib/whatever/../mylib");
let res = get_relative_to(p1, p2); let res = get_relative_to(&p1, &p2);
assert res == ~"../lib"; assert res == Path("../lib");
} }
#[test] #[test]
fn test_relative_to6() { fn test_relative_to6() {
let p1 = ~"/1"; let p1 = Path("/1");
let p2 = ~"/2/3"; let p2 = Path("/2/3");
let res = get_relative_to(p1, p2); let res = get_relative_to(&p1, &p2);
assert res == ~"2"; assert res == Path("2");
} }
#[test] #[test]
fn test_relative_to7() { fn test_relative_to7() {
let p1 = ~"/1/2"; let p1 = Path("/1/2");
let p2 = ~"/3"; let p2 = Path("/3");
let res = get_relative_to(p1, p2); let res = get_relative_to(&p1, &p2);
assert res == ~".."; assert res == Path("..");
} }
#[test] #[test]
fn test_relative_to8() { fn test_relative_to8() {
let p1 = ~"/home/brian/Dev/rust/build/" let p1 = Path("/home/brian/Dev/rust/build/").push_rel(
+ ~"stage2/lib/rustc/i686-unknown-linux-gnu/lib/librustc.so"; &Path("stage2/lib/rustc/i686-unknown-linux-gnu/lib/librustc.so"));
let p2 = ~"/home/brian/Dev/rust/build/stage2/bin/.." let p2 = Path("/home/brian/Dev/rust/build/stage2/bin/..").push_rel(
+ ~"/lib/rustc/i686-unknown-linux-gnu/lib/libstd.so"; &Path("lib/rustc/i686-unknown-linux-gnu/lib/libstd.so"));
let res = get_relative_to(p1, p2); let res = get_relative_to(&p1, &p2);
assert res == ~"."; debug!("test_relative_tu8: %s vs. %s",
res.to_str(),
Path(".").to_str());
assert res == Path(".");
} }
#[test] #[test]
@ -316,8 +294,8 @@ mod test {
fn test_rpath_relative() { fn test_rpath_relative() {
let o = session::os_linux; let o = session::os_linux;
let res = get_rpath_relative_to_output(o, let res = get_rpath_relative_to_output(o,
~"/usr", ~"bin/rustc", ~"lib/libstd.so"); &Path("bin/rustc"), &Path("lib/libstd.so"));
assert res == ~"$ORIGIN/../lib"; assert res == Path("$ORIGIN/../lib");
} }
#[test] #[test]
@ -325,8 +303,8 @@ mod test {
fn test_rpath_relative() { fn test_rpath_relative() {
let o = session::os_freebsd; let o = session::os_freebsd;
let res = get_rpath_relative_to_output(o, let res = get_rpath_relative_to_output(o,
~"/usr", ~"bin/rustc", ~"lib/libstd.so"); &Path("bin/rustc"), &Path("lib/libstd.so"));
assert res == ~"$ORIGIN/../lib"; assert res == Path("$ORIGIN/../lib");
} }
#[test] #[test]
@ -334,14 +312,19 @@ mod test {
fn test_rpath_relative() { fn test_rpath_relative() {
// this is why refinements would be nice // this is why refinements would be nice
let o = session::os_macos; let o = session::os_macos;
let res = get_rpath_relative_to_output(o, ~"/usr", ~"bin/rustc", let res = get_rpath_relative_to_output(o,
~"lib/libstd.so"); &Path("bin/rustc"),
assert res == ~"@executable_path/../lib"; &Path("lib/libstd.so"));
assert res == Path("@executable_path/../lib");
} }
#[test] #[test]
fn test_get_absolute_rpath() { fn test_get_absolute_rpath() {
let res = get_absolute_rpath(~"/usr", ~"lib/libstd.so"); let res = get_absolute_rpath(&Path("lib/libstd.so"));
assert res == ~"/usr/lib"; debug!("test_get_absolute_rpath: %s vs. %s",
res.to_str(),
os::make_absolute(&Path("lib")).to_str());
assert res == os::make_absolute(&Path("lib"));
} }
} }

View file

@ -27,7 +27,7 @@ fn anon_src() -> ~str { ~"<anon>" }
fn source_name(input: input) -> ~str { fn source_name(input: input) -> ~str {
match input { match input {
file_input(ifile) => ifile, file_input(ifile) => ifile.to_str(),
str_input(_) => anon_src() str_input(_) => anon_src()
} }
} }
@ -92,7 +92,7 @@ fn parse_cfgspecs(cfgspecs: ~[~str]) -> ast::crate_cfg {
enum input { enum input {
/// Load source from file /// Load source from file
file_input(~str), file_input(Path),
/// The string is the source /// The string is the source
str_input(~str) str_input(~str)
} }
@ -101,7 +101,7 @@ fn parse_input(sess: session, cfg: ast::crate_cfg, input: input)
-> @ast::crate { -> @ast::crate {
match input { match input {
file_input(file) => { file_input(file) => {
parse::parse_crate_from_file(file, cfg, sess.parse_sess) parse::parse_crate_from_file(&file, cfg, sess.parse_sess)
} }
str_input(src) => { str_input(src) => {
// FIXME (#2319): Don't really want to box the source string // FIXME (#2319): Don't really want to box the source string
@ -236,11 +236,13 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
vtable_map: vtable_map}; vtable_map: vtable_map};
let (llmod, link_meta) = time(time_passes, ~"translation", || let (llmod, link_meta) = time(time_passes, ~"translation", ||
trans::base::trans_crate(sess, crate, ty_cx, outputs.obj_filename, trans::base::trans_crate(sess, crate, ty_cx,
&outputs.obj_filename,
exp_map, exp_map2, maps)); exp_map, exp_map2, maps));
time(time_passes, ~"LLVM passes", || time(time_passes, ~"LLVM passes", ||
link::write::run_passes(sess, llmod, outputs.obj_filename)); link::write::run_passes(sess, llmod,
&outputs.obj_filename));
let stop_after_codegen = let stop_after_codegen =
sess.opts.output_type != link::output_type_exe || sess.opts.output_type != link::output_type_exe ||
@ -249,14 +251,15 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
if stop_after_codegen { return {crate: crate, tcx: some(ty_cx)}; } if stop_after_codegen { return {crate: crate, tcx: some(ty_cx)}; }
time(time_passes, ~"linking", || time(time_passes, ~"linking", ||
link::link_binary(sess, outputs.obj_filename, link::link_binary(sess,
outputs.out_filename, link_meta)); &outputs.obj_filename,
&outputs.out_filename, link_meta));
return {crate: crate, tcx: some(ty_cx)}; return {crate: crate, tcx: some(ty_cx)};
} }
fn compile_input(sess: session, cfg: ast::crate_cfg, input: input, fn compile_input(sess: session, cfg: ast::crate_cfg, input: input,
outdir: option<~str>, output: option<~str>) { outdir: &option<Path>, output: &option<Path>) {
let upto = if sess.opts.parse_only { cu_parse } let upto = if sess.opts.parse_only { cu_parse }
else if sess.opts.no_trans { cu_no_trans } else if sess.opts.no_trans { cu_no_trans }
@ -483,6 +486,7 @@ fn build_session_options(matches: getopts::matches,
let extra_debuginfo = opt_present(matches, ~"xg"); let extra_debuginfo = opt_present(matches, ~"xg");
let debuginfo = opt_present(matches, ~"g") || extra_debuginfo; let debuginfo = opt_present(matches, ~"g") || extra_debuginfo;
let sysroot_opt = getopts::opt_maybe_str(matches, ~"sysroot"); let sysroot_opt = getopts::opt_maybe_str(matches, ~"sysroot");
let sysroot_opt = option::map(sysroot_opt, |m| Path(m));
let target_opt = getopts::opt_maybe_str(matches, ~"target"); let target_opt = getopts::opt_maybe_str(matches, ~"target");
let save_temps = getopts::opt_present(matches, ~"save-temps"); let save_temps = getopts::opt_present(matches, ~"save-temps");
match output_type { match output_type {
@ -514,7 +518,9 @@ fn build_session_options(matches: getopts::matches,
some(s) => s some(s) => s
}; };
let addl_lib_search_paths = getopts::opt_strs(matches, ~"L"); let addl_lib_search_paths =
getopts::opt_strs(matches, ~"L")
.map(|s| Path(s));
let cfg = parse_cfgspecs(getopts::opt_strs(matches, ~"cfg")); let cfg = parse_cfgspecs(getopts::opt_strs(matches, ~"cfg"));
let test = opt_present(matches, ~"test"); let test = opt_present(matches, ~"test");
let sopts: @session::options = let sopts: @session::options =
@ -614,11 +620,11 @@ fn opts() -> ~[getopts::opt] {
optflag(~"static"), optflag(~"gc")]; optflag(~"static"), optflag(~"gc")];
} }
type output_filenames = @{out_filename: ~str, obj_filename:~str}; type output_filenames = @{out_filename:Path, obj_filename:Path};
fn build_output_filenames(input: input, fn build_output_filenames(input: input,
odir: option<~str>, odir: &option<Path>,
ofile: option<~str>, ofile: &option<Path>,
sess: session) sess: session)
-> output_filenames { -> output_filenames {
let obj_path; let obj_path;
@ -639,37 +645,30 @@ fn build_output_filenames(input: input,
link::output_type_object | link::output_type_exe => ~"o" link::output_type_object | link::output_type_exe => ~"o"
}; };
match ofile { match *ofile {
none => { none => {
// "-" as input file will cause the parser to read from stdin so we // "-" as input file will cause the parser to read from stdin so we
// have to make up a name // have to make up a name
// We want to toss everything after the final '.' // We want to toss everything after the final '.'
let dirname = match odir { let dirpath = match *odir {
some(d) => d, some(d) => d,
none => match input { none => match input {
str_input(_) => os::getcwd(), str_input(_) => os::getcwd(),
file_input(ifile) => path::dirname(ifile) file_input(ifile) => ifile.dir_path()
} }
}; };
let base_filename = match input { let stem = match input {
file_input(ifile) => { file_input(ifile) => option::get(ifile.filestem()),
let (path, _) = path::splitext(ifile);
path::basename(path)
}
str_input(_) => ~"rust_out" str_input(_) => ~"rust_out"
}; };
let base_path = path::connect(dirname, base_filename);
if sess.building_library { if sess.building_library {
let basename = path::basename(base_path); out_path = dirpath.push(os::dll_filename(stem));
let dylibname = os::dll_filename(basename); obj_path = dirpath.push(stem).with_filetype(obj_suffix);
out_path = path::connect(dirname, dylibname);
obj_path = path::connect(dirname, basename + ~"." + obj_suffix);
} else { } else {
out_path = base_path; out_path = dirpath.push(stem);
obj_path = base_path + ~"." + obj_suffix; obj_path = dirpath.push(stem).with_filetype(obj_suffix);
} }
} }
@ -678,9 +677,7 @@ fn build_output_filenames(input: input,
obj_path = if stop_after_codegen { obj_path = if stop_after_codegen {
out_file out_file
} else { } else {
let (base, _) = path::splitext(out_file); out_file.with_filetype(obj_suffix)
let modified = base + ~"." + obj_suffix;
modified
}; };
if sess.building_library { if sess.building_library {
@ -690,13 +687,13 @@ fn build_output_filenames(input: input,
// lib<basename>-<hash>-<version>.so no matter what. // lib<basename>-<hash>-<version>.so no matter what.
} }
if odir != none { if *odir != none {
sess.warn(~"ignoring --out-dir flag due to -o flag."); sess.warn(~"ignoring --out-dir flag due to -o flag.");
} }
} }
} }
return @{out_filename: out_path, return @{out_filename: out_path,
obj_filename: obj_path}; obj_filename: obj_path};
} }
fn early_error(emitter: diagnostic::emitter, msg: ~str) -> ! { fn early_error(emitter: diagnostic::emitter, msg: ~str) -> ! {
@ -704,7 +701,7 @@ fn early_error(emitter: diagnostic::emitter, msg: ~str) -> ! {
fail; fail;
} }
fn list_metadata(sess: session, path: ~str, out: io::Writer) { fn list_metadata(sess: session, path: &Path, out: io::Writer) {
metadata::loader::list_file_metadata( metadata::loader::list_file_metadata(
sess.parse_sess.interner, sess.parse_sess.interner,
session::sess_os_to_meta_os(sess.targ_cfg.os), path, out); session::sess_os_to_meta_os(sess.targ_cfg.os), path, out);

View file

@ -159,7 +159,7 @@ fn run_compiler(args: ~[~str], demitter: diagnostic::emitter) {
let src = str::from_bytes(io::stdin().read_whole_stream()); let src = str::from_bytes(io::stdin().read_whole_stream());
str_input(src) str_input(src)
} else { } else {
file_input(ifile) file_input(Path(ifile))
} }
} }
_ => early_error(demitter, ~"multiple input filenames provided") _ => early_error(demitter, ~"multiple input filenames provided")
@ -168,7 +168,9 @@ fn run_compiler(args: ~[~str], demitter: diagnostic::emitter) {
let sopts = build_session_options(matches, demitter); let sopts = build_session_options(matches, demitter);
let sess = build_session(sopts, demitter); let sess = build_session(sopts, demitter);
let odir = getopts::opt_maybe_str(matches, ~"out-dir"); let odir = getopts::opt_maybe_str(matches, ~"out-dir");
let odir = option::map(odir, |o| Path(o));
let ofile = getopts::opt_maybe_str(matches, ~"o"); let ofile = getopts::opt_maybe_str(matches, ~"o");
let ofile = option::map(ofile, |o| Path(o));
let cfg = build_configuration(sess, binary, input); let cfg = build_configuration(sess, binary, input);
let pretty = let pretty =
option::map(getopts::opt_default(matches, ~"pretty", option::map(getopts::opt_default(matches, ~"pretty",
@ -185,7 +187,7 @@ fn run_compiler(args: ~[~str], demitter: diagnostic::emitter) {
if ls { if ls {
match input { match input {
file_input(ifile) => { file_input(ifile) => {
list_metadata(sess, ifile, io::stdout()); list_metadata(sess, &ifile, io::stdout());
} }
str_input(_) => { str_input(_) => {
early_error(demitter, ~"can not list metadata for stdin"); early_error(demitter, ~"can not list metadata for stdin");
@ -194,7 +196,7 @@ fn run_compiler(args: ~[~str], demitter: diagnostic::emitter) {
return; return;
} }
compile_input(sess, cfg, input, odir, ofile); compile_input(sess, cfg, input, &odir, &ofile);
} }
/* /*

View file

@ -89,8 +89,8 @@ type options =
lint_opts: ~[(lint::lint, lint::level)], lint_opts: ~[(lint::lint, lint::level)],
save_temps: bool, save_temps: bool,
output_type: back::link::output_type, output_type: back::link::output_type,
addl_lib_search_paths: ~[~str], addl_lib_search_paths: ~[Path],
maybe_sysroot: option<~str>, maybe_sysroot: option<Path>,
target_triple: ~str, target_triple: ~str,
cfg: ast::crate_cfg, cfg: ast::crate_cfg,
test: bool, test: bool,
@ -111,7 +111,7 @@ type session_ = {targ_cfg: @config,
span_diagnostic: diagnostic::span_handler, span_diagnostic: diagnostic::span_handler,
filesearch: filesearch::filesearch, filesearch: filesearch::filesearch,
mut building_library: bool, mut building_library: bool,
working_dir: ~str, working_dir: Path,
lint_settings: lint::lint_settings}; lint_settings: lint::lint_settings};
enum session { enum session {

View file

@ -199,7 +199,7 @@ fn resolve_crate(e: env, ident: ast::ident, metas: ~[@ast::meta_item],
}; };
let cinfo = loader::load_library_crate(load_ctxt); let cinfo = loader::load_library_crate(load_ctxt);
let cfilename = cinfo.ident; let cfilename = Path(cinfo.ident);
let cdata = cinfo.data; let cdata = cinfo.data;
let attrs = decoder::get_crate_attributes(cdata); let attrs = decoder::get_crate_attributes(cdata);
@ -225,7 +225,7 @@ fn resolve_crate(e: env, ident: ast::ident, metas: ~[@ast::meta_item],
let cstore = e.cstore; let cstore = e.cstore;
cstore::set_crate_data(cstore, cnum, cmeta); cstore::set_crate_data(cstore, cnum, cmeta);
cstore::add_used_crate_file(cstore, cfilename); cstore::add_used_crate_file(cstore, &cfilename);
return cnum; return cnum;
} }
some(cnum) => { some(cnum) => {

View file

@ -56,7 +56,7 @@ type cstore_private =
@{metas: map::hashmap<ast::crate_num, crate_metadata>, @{metas: map::hashmap<ast::crate_num, crate_metadata>,
use_crate_map: use_crate_map, use_crate_map: use_crate_map,
mod_path_map: mod_path_map, mod_path_map: mod_path_map,
mut used_crate_files: ~[~str], mut used_crate_files: ~[Path],
mut used_libraries: ~[~str], mut used_libraries: ~[~str],
mut used_link_args: ~[~str], mut used_link_args: ~[~str],
intr: ident_interner}; intr: ident_interner};
@ -114,13 +114,13 @@ fn iter_crate_data(cstore: cstore, i: fn(ast::crate_num, crate_metadata)) {
for p(cstore).metas.each |k,v| { i(k, v);}; for p(cstore).metas.each |k,v| { i(k, v);};
} }
fn add_used_crate_file(cstore: cstore, lib: ~str) { fn add_used_crate_file(cstore: cstore, lib: &Path) {
if !vec::contains(p(cstore).used_crate_files, lib) { if !vec::contains(p(cstore).used_crate_files, copy *lib) {
vec::push(p(cstore).used_crate_files, lib); vec::push(p(cstore).used_crate_files, copy *lib);
} }
} }
fn get_used_crate_files(cstore: cstore) -> ~[~str] { fn get_used_crate_files(cstore: cstore) -> ~[Path] {
return p(cstore).used_crate_files; return p(cstore).used_crate_files;
} }

View file

@ -14,12 +14,10 @@ export get_cargo_root;
export get_cargo_root_nearest; export get_cargo_root_nearest;
export libdir; export libdir;
import path::Path; type pick<T> = fn(path: &Path) -> option<T>;
type pick<T> = fn(path: Path) -> option<T>; fn pick_file(file: Path, path: &Path) -> option<Path> {
if path.file_path() == file { option::some(copy *path) }
fn pick_file(file: Path, path: Path) -> option<Path> {
if path::basename(path) == file { option::some(path) }
else { option::none } else { option::none }
} }
@ -27,11 +25,11 @@ trait filesearch {
fn sysroot() -> Path; fn sysroot() -> Path;
fn lib_search_paths() -> ~[Path]; fn lib_search_paths() -> ~[Path];
fn get_target_lib_path() -> Path; fn get_target_lib_path() -> Path;
fn get_target_lib_file_path(file: Path) -> Path; fn get_target_lib_file_path(file: &Path) -> Path;
} }
fn mk_filesearch(maybe_sysroot: option<Path>, fn mk_filesearch(maybe_sysroot: option<Path>,
target_triple: ~str, target_triple: &str,
addl_lib_search_paths: ~[Path]) -> filesearch { addl_lib_search_paths: ~[Path]) -> filesearch {
type filesearch_impl = {sysroot: Path, type filesearch_impl = {sysroot: Path,
addl_lib_search_paths: ~[Path], addl_lib_search_paths: ~[Path],
@ -42,7 +40,8 @@ fn mk_filesearch(maybe_sysroot: option<Path>,
let mut paths = self.addl_lib_search_paths; let mut paths = self.addl_lib_search_paths;
vec::push(paths, vec::push(paths,
make_target_lib_path(self.sysroot, self.target_triple)); make_target_lib_path(&self.sysroot,
self.target_triple));
match get_cargo_lib_path_nearest() { match get_cargo_lib_path_nearest() {
result::ok(p) => vec::push(paths, p), result::ok(p) => vec::push(paths, p),
result::err(p) => () result::err(p) => ()
@ -54,33 +53,33 @@ fn mk_filesearch(maybe_sysroot: option<Path>,
paths paths
} }
fn get_target_lib_path() -> Path { fn get_target_lib_path() -> Path {
make_target_lib_path(self.sysroot, self.target_triple) make_target_lib_path(&self.sysroot, self.target_triple)
} }
fn get_target_lib_file_path(file: Path) -> Path { fn get_target_lib_file_path(file: &Path) -> Path {
path::connect(self.get_target_lib_path(), file) self.get_target_lib_path().push_rel(file)
} }
} }
let sysroot = get_sysroot(maybe_sysroot); let sysroot = get_sysroot(maybe_sysroot);
debug!("using sysroot = %s", sysroot); debug!("using sysroot = %s", sysroot.to_str());
{sysroot: sysroot, {sysroot: sysroot,
addl_lib_search_paths: addl_lib_search_paths, addl_lib_search_paths: addl_lib_search_paths,
target_triple: target_triple} as filesearch target_triple: str::from_slice(target_triple)} as filesearch
} }
fn search<T: copy>(filesearch: filesearch, pick: pick<T>) -> option<T> { fn search<T: copy>(filesearch: filesearch, pick: pick<T>) -> option<T> {
let mut rslt = none; let mut rslt = none;
for filesearch.lib_search_paths().each |lib_search_path| { for filesearch.lib_search_paths().each |lib_search_path| {
debug!("searching %s", lib_search_path); debug!("searching %s", lib_search_path.to_str());
for os::list_dir_path(lib_search_path).each |path| { for os::list_dir_path(&lib_search_path).each |path| {
debug!("testing %s", path); debug!("testing %s", path.to_str());
let maybe_picked = pick(path); let maybe_picked = pick(path);
if option::is_some(maybe_picked) { if option::is_some(maybe_picked) {
debug!("picked %s", path); debug!("picked %s", path.to_str());
rslt = maybe_picked; rslt = maybe_picked;
break; break;
} else { } else {
debug!("rejected %s", path); debug!("rejected %s", path.to_str());
} }
} }
if option::is_some(rslt) { break; } if option::is_some(rslt) { break; }
@ -88,21 +87,20 @@ fn search<T: copy>(filesearch: filesearch, pick: pick<T>) -> option<T> {
return rslt; return rslt;
} }
fn relative_target_lib_path(target_triple: ~str) -> ~[Path] { fn relative_target_lib_path(target_triple: &str) -> Path {
~[libdir(), ~"rustc", target_triple, libdir()] Path(libdir()).push_many([~"rustc",
str::from_slice(target_triple),
libdir()])
} }
fn make_target_lib_path(sysroot: Path, fn make_target_lib_path(sysroot: &Path,
target_triple: ~str) -> Path { target_triple: &str) -> Path {
let path = vec::append(~[sysroot], sysroot.push_rel(&relative_target_lib_path(target_triple))
relative_target_lib_path(target_triple));
let path = path::connect_many(path);
return path;
} }
fn get_default_sysroot() -> Path { fn get_default_sysroot() -> Path {
match os::self_exe_path() { match os::self_exe_path() {
option::some(p) => path::normalize(path::connect(p, ~"..")), option::some(p) => p.pop(),
option::none => fail ~"can't determine value for sysroot" option::none => fail ~"can't determine value for sysroot"
} }
} }
@ -115,15 +113,14 @@ fn get_sysroot(maybe_sysroot: option<Path>) -> Path {
} }
fn get_cargo_sysroot() -> result<Path, ~str> { fn get_cargo_sysroot() -> result<Path, ~str> {
let path = ~[get_default_sysroot(), libdir(), ~"cargo"]; result::ok(get_default_sysroot().push_many([libdir(), ~"cargo"]))
result::ok(path::connect_many(path))
} }
fn get_cargo_root() -> result<Path, ~str> { fn get_cargo_root() -> result<Path, ~str> {
match os::getenv(~"CARGO_ROOT") { match os::getenv(~"CARGO_ROOT") {
some(_p) => result::ok(_p), some(_p) => result::ok(Path(_p)),
none => match os::homedir() { none => match os::homedir() {
some(_q) => result::ok(path::connect(_q, ~".cargo")), some(_q) => result::ok(_q.push(".cargo")),
none => result::err(~"no CARGO_ROOT or home directory") none => result::err(~"no CARGO_ROOT or home directory")
} }
} }
@ -132,21 +129,21 @@ fn get_cargo_root() -> result<Path, ~str> {
fn get_cargo_root_nearest() -> result<Path, ~str> { fn get_cargo_root_nearest() -> result<Path, ~str> {
do result::chain(get_cargo_root()) |p| { do result::chain(get_cargo_root()) |p| {
let cwd = os::getcwd(); let cwd = os::getcwd();
let mut dirname = path::dirname(cwd); let cwd_cargo = cwd.push(".cargo");
let mut dirpath = path::split(dirname); let mut par_cargo = cwd.pop().push(".cargo");
let cwd_cargo = path::connect(cwd, ~".cargo");
let mut par_cargo = path::connect(dirname, ~".cargo");
let mut rslt = result::ok(cwd_cargo); let mut rslt = result::ok(cwd_cargo);
if !os::path_is_dir(cwd_cargo) && cwd_cargo != p { if !os::path_is_dir(&cwd_cargo) && cwd_cargo != p {
while vec::is_not_empty(dirpath) && par_cargo != p { while par_cargo != p {
if os::path_is_dir(par_cargo) { if os::path_is_dir(&par_cargo) {
rslt = result::ok(par_cargo); rslt = result::ok(par_cargo);
break; break;
} }
vec::pop(dirpath); if par_cargo.components.len() == 1 {
dirname = path::dirname(dirname); // We just checked /.cargo, stop now.
par_cargo = path::connect(dirname, ~".cargo"); break;
}
par_cargo = par_cargo.pop().pop().push(".cargo");
} }
} }
rslt rslt
@ -155,13 +152,13 @@ fn get_cargo_root_nearest() -> result<Path, ~str> {
fn get_cargo_lib_path() -> result<Path, ~str> { fn get_cargo_lib_path() -> result<Path, ~str> {
do result::chain(get_cargo_root()) |p| { do result::chain(get_cargo_root()) |p| {
result::ok(path::connect(p, libdir())) result::ok(p.push(libdir()))
} }
} }
fn get_cargo_lib_path_nearest() -> result<Path, ~str> { fn get_cargo_lib_path_nearest() -> result<Path, ~str> {
do result::chain(get_cargo_root_nearest()) |p| { do result::chain(get_cargo_root_nearest()) |p| {
result::ok(path::connect(p, libdir())) result::ok(p.push(libdir()))
} }
} }

View file

@ -74,27 +74,28 @@ fn find_library_crate_aux(cx: ctxt,
let mut matches = ~[]; let mut matches = ~[];
filesearch::search(filesearch, |path| { filesearch::search(filesearch, |path| {
debug!("inspecting file %s", path); debug!("inspecting file %s", path.to_str());
let f: ~str = path::basename(path); let f: ~str = option::get(path.filename());
if !(str::starts_with(f, prefix) && str::ends_with(f, suffix)) { if !(str::starts_with(f, prefix) && str::ends_with(f, suffix)) {
debug!("skipping %s, doesn't look like %s*%s", path, prefix, debug!("skipping %s, doesn't look like %s*%s", path.to_str(),
suffix); prefix, suffix);
option::none::<()> option::none::<()>
} else { } else {
debug!("%s is a candidate", path); debug!("%s is a candidate", path.to_str());
match get_metadata_section(cx.os, path) { match get_metadata_section(cx.os, path) {
option::some(cvec) => { option::some(cvec) => {
if !crate_matches(cvec, cx.metas, cx.hash) { if !crate_matches(cvec, cx.metas, cx.hash) {
debug!("skipping %s, metadata doesn't match", path); debug!("skipping %s, metadata doesn't match",
path.to_str());
option::none::<()> option::none::<()>
} else { } else {
debug!("found %s with matching metadata", path); debug!("found %s with matching metadata", path.to_str());
vec::push(matches, {ident: path, data: cvec}); vec::push(matches, {ident: path.to_str(), data: cvec});
option::none::<()> option::none::<()>
} }
} }
_ => { _ => {
debug!("could not load metadata for %s", path); debug!("could not load metadata for %s", path.to_str());
option::none::<()> option::none::<()>
} }
} }
@ -168,10 +169,10 @@ fn metadata_matches(extern_metas: ~[@ast::meta_item],
} }
fn get_metadata_section(os: os, fn get_metadata_section(os: os,
filename: ~str) -> option<@~[u8]> unsafe { filename: &Path) -> option<@~[u8]> unsafe {
let mb = str::as_c_str(filename, |buf| { let mb = str::as_c_str(filename.to_str(), |buf| {
llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf) llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
}); });
if mb as int == 0 { return option::none::<@~[u8]>; } if mb as int == 0 { return option::none::<@~[u8]>; }
let of = match mk_object_file(mb) { let of = match mk_object_file(mb) {
option::some(of) => of, option::some(of) => of,
@ -204,12 +205,13 @@ fn meta_section_name(os: os) -> ~str {
} }
// A diagnostic function for dumping crate metadata to an output stream // A diagnostic function for dumping crate metadata to an output stream
fn list_file_metadata(intr: ident_interner, os: os, path: ~str, fn list_file_metadata(intr: ident_interner,
out: io::Writer) { os: os, path: &Path, out: io::Writer) {
match get_metadata_section(os, path) { match get_metadata_section(os, path) {
option::some(bytes) => decoder::list_crate_metadata(intr, bytes, out), option::some(bytes) => decoder::list_crate_metadata(intr, bytes, out),
option::none => { option::none => {
out.write_str(~"could not find metadata in " + path + ~".\n"); out.write_str(~"could not find metadata in "
+ path.to_str() + ~".\n");
} }
} }
} }

View file

@ -5778,7 +5778,7 @@ fn write_abi_version(ccx: @crate_ctxt) {
fn trans_crate(sess: session::session, fn trans_crate(sess: session::session,
crate: @ast::crate, crate: @ast::crate,
tcx: ty::ctxt, tcx: ty::ctxt,
output: ~str, output: &Path,
emap: resolve3::ExportMap, emap: resolve3::ExportMap,
emap2: resolve3::ExportMap2, emap2: resolve3::ExportMap2,
maps: astencode::maps) maps: astencode::maps)

View file

@ -172,7 +172,7 @@ fn create_compile_unit(cx: @crate_ctxt)
option::none => () option::none => ()
} }
let (_, work_dir) = get_file_path_and_dir(cx.sess.working_dir, let (_, work_dir) = get_file_path_and_dir(cx.sess.working_dir.to_str(),
crate_name); crate_name);
let unit_metadata = ~[lltag(tg), let unit_metadata = ~[lltag(tg),
llunused(), llunused(),
@ -197,13 +197,13 @@ fn get_cache(cx: @crate_ctxt) -> metadata_cache {
option::get(cx.dbg_cx).llmetadata option::get(cx.dbg_cx).llmetadata
} }
fn get_file_path_and_dir(work_dir: ~str, full_path: ~str) -> (~str, ~str) { fn get_file_path_and_dir(work_dir: &str, full_path: &str) -> (~str, ~str) {
(if str::starts_with(full_path, work_dir) { (if str::starts_with(full_path, work_dir) {
str::slice(full_path, str::len(work_dir) + 1u, str::slice(full_path, str::len(work_dir) + 1u,
str::len(full_path)) str::len(full_path))
} else { } else {
full_path str::from_slice(full_path)
}, work_dir) }, str::from_slice(work_dir))
} }
fn create_file(cx: @crate_ctxt, full_path: ~str) -> @metadata<file_md> { fn create_file(cx: @crate_ctxt, full_path: ~str) -> @metadata<file_md> {
@ -215,8 +215,9 @@ fn create_file(cx: @crate_ctxt, full_path: ~str) -> @metadata<file_md> {
option::none => () option::none => ()
} }
let (file_path, work_dir) = get_file_path_and_dir(cx.sess.working_dir, let (file_path, work_dir) =
full_path); get_file_path_and_dir(cx.sess.working_dir.to_str(),
full_path);
let unit_node = create_compile_unit(cx).node; let unit_node = create_compile_unit(cx).node;
let file_md = ~[lltag(tg), let file_md = ~[lltag(tg),
llstr(file_path), llstr(file_path),

View file

@ -210,6 +210,9 @@ fn vstore_ty_to_str(cx: ctxt, ty: ~str, vs: ty::vstore) -> ~str {
ty::vstore_fixed(_) => { ty::vstore_fixed(_) => {
fmt!("%s/%s", ty, vstore_to_str(cx, vs)) fmt!("%s/%s", ty, vstore_to_str(cx, vs))
} }
ty::vstore_slice(_) => {
fmt!("%s/%s", vstore_to_str(cx, vs), ty)
}
_ => fmt!("%s%s", vstore_to_str(cx, vs), ty) _ => fmt!("%s%s", vstore_to_str(cx, vs), ty)
} }
} }

View file

@ -51,7 +51,7 @@ fn from_str<T>(source: ~str, owner: srv_owner<T>) -> T {
} }
fn from_file<T>(file: ~str, owner: srv_owner<T>) -> T { fn from_file<T>(file: ~str, owner: srv_owner<T>) -> T {
run(owner, file, parse::from_file_sess) run(owner, file, |sess, f| parse::from_file_sess(sess, &Path(f)))
} }
fn run<T>(owner: srv_owner<T>, source: ~str, +parse: parser) -> T { fn run<T>(owner: srv_owner<T>, source: ~str, +parse: parser) -> T {

View file

@ -28,8 +28,8 @@ enum output_style {
/// The configuration for a rustdoc session /// The configuration for a rustdoc session
type config = { type config = {
input_crate: ~str, input_crate: Path,
output_dir: ~str, output_dir: Path,
output_format: output_format, output_format: output_format,
output_style: output_style, output_style: output_style,
pandoc_cmd: option<~str> pandoc_cmd: option<~str>
@ -67,10 +67,10 @@ fn usage() {
println(~""); println(~"");
} }
fn default_config(input_crate: ~str) -> config { fn default_config(input_crate: &Path) -> config {
{ {
input_crate: input_crate, input_crate: *input_crate,
output_dir: ~".", output_dir: Path("."),
output_format: pandoc_html, output_format: pandoc_html,
output_style: doc_per_mod, output_style: doc_per_mod,
pandoc_cmd: none pandoc_cmd: none
@ -103,8 +103,8 @@ fn parse_config_(
match getopts::getopts(args, opts) { match getopts::getopts(args, opts) {
result::ok(matches) => { result::ok(matches) => {
if vec::len(matches.free) == 1u { if vec::len(matches.free) == 1u {
let input_crate = vec::head(matches.free); let input_crate = Path(vec::head(matches.free));
config_from_opts(input_crate, matches, program_output) config_from_opts(&input_crate, matches, program_output)
} else if vec::is_empty(matches.free) { } else if vec::is_empty(matches.free) {
result::err(~"no crates specified") result::err(~"no crates specified")
} else { } else {
@ -118,7 +118,7 @@ fn parse_config_(
} }
fn config_from_opts( fn config_from_opts(
input_crate: ~str, input_crate: &Path,
matches: getopts::matches, matches: getopts::matches,
program_output: program_output program_output: program_output
) -> result<config, ~str> { ) -> result<config, ~str> {
@ -127,6 +127,7 @@ fn config_from_opts(
let result = result::ok(config); let result = result::ok(config);
let result = do result::chain(result) |config| { let result = do result::chain(result) |config| {
let output_dir = getopts::opt_maybe_str(matches, opt_output_dir()); let output_dir = getopts::opt_maybe_str(matches, opt_output_dir());
let output_dir = option::map(output_dir, |s| Path(s));
result::ok({ result::ok({
output_dir: option::get_default(output_dir, config.output_dir) output_dir: option::get_default(output_dir, config.output_dir)
with config with config
@ -205,7 +206,7 @@ fn maybe_find_pandoc(
none => { none => {
~[~"pandoc"] + match os::homedir() { ~[~"pandoc"] + match os::homedir() {
some(dir) => { some(dir) => {
~[path::connect(dir, ~".cabal/bin/pandoc")] ~[dir.push_rel(&Path(".cabal/bin/pandoc")).to_str()]
} }
none => ~[] none => ~[]
} }
@ -229,7 +230,7 @@ fn maybe_find_pandoc(
fn should_find_pandoc() { fn should_find_pandoc() {
let config = { let config = {
output_format: pandoc_html output_format: pandoc_html
with default_config(~"test") with default_config(&Path("test"))
}; };
let mock_program_output = fn~(_prog: &str, _args: &[~str]) -> { let mock_program_output = fn~(_prog: &str, _args: &[~str]) -> {
status: int, out: ~str, err: ~str status: int, out: ~str, err: ~str
@ -246,7 +247,7 @@ fn should_find_pandoc() {
fn should_error_with_no_pandoc() { fn should_error_with_no_pandoc() {
let config = { let config = {
output_format: pandoc_html output_format: pandoc_html
with default_config(~"test") with default_config(&Path("test"))
}; };
let mock_program_output = fn~(_prog: &str, _args: &[~str]) -> { let mock_program_output = fn~(_prog: &str, _args: &[~str]) -> {
status: int, out: ~str, err: ~str status: int, out: ~str, err: ~str
@ -282,7 +283,7 @@ fn should_error_with_multiple_crates() {
#[test] #[test]
fn should_set_output_dir_to_cwd_if_not_provided() { fn should_set_output_dir_to_cwd_if_not_provided() {
let config = test::parse_config(~[~"rustdoc", ~"crate.rc"]); let config = test::parse_config(~[~"rustdoc", ~"crate.rc"]);
assert result::get(config).output_dir == ~"."; assert result::get(config).output_dir == Path(".");
} }
#[test] #[test]
@ -290,7 +291,7 @@ fn should_set_output_dir_if_provided() {
let config = test::parse_config(~[ let config = test::parse_config(~[
~"rustdoc", ~"crate.rc", ~"--output-dir", ~"snuggles" ~"rustdoc", ~"crate.rc", ~"--output-dir", ~"snuggles"
]); ]);
assert result::get(config).output_dir == ~"snuggles"; assert result::get(config).output_dir == Path("snuggles");
} }
#[test] #[test]

View file

@ -81,7 +81,7 @@ fn item_to_entry(
let link = match doc { let link = match doc {
doc::modtag(_) | doc::nmodtag(_) doc::modtag(_) | doc::nmodtag(_)
if config.output_style == config::doc_per_mod => { if config.output_style == config::doc_per_mod => {
markdown_writer::make_filename(config, doc::itempage(doc)) markdown_writer::make_filename(config, doc::itempage(doc)).to_str()
} }
_ => { _ => {
~"#" + pandoc_header_id(markdown_pass::header_text(doc)) ~"#" + pandoc_header_id(markdown_pass::header_text(doc))
@ -230,7 +230,7 @@ mod test {
do astsrv::from_str(source) |srv| { do astsrv::from_str(source) |srv| {
let config = { let config = {
output_style: output_style output_style: output_style
with config::default_config(~"whatever") with config::default_config(&Path("whatever"))
}; };
let doc = extract::from_srv(srv, ~""); let doc = extract::from_srv(srv, ~"");
let doc = attr_pass::mk_pass().f(srv, doc); let doc = attr_pass::mk_pass().f(srv, doc);

View file

@ -785,7 +785,7 @@ mod test {
let config = { let config = {
output_style: config::doc_per_crate output_style: config::doc_per_crate
with config::default_config(~"whatever") with config::default_config(&Path("whatever"))
}; };
let doc = extract::from_srv(srv, ~""); let doc = extract::from_srv(srv, ~"");

View file

@ -66,7 +66,7 @@ fn markdown_writer(
) -> writer { ) -> writer {
let filename = make_local_filename(config, page); let filename = make_local_filename(config, page);
do generic_writer |markdown| { do generic_writer |markdown| {
write_file(filename, markdown); write_file(&filename, markdown);
} }
} }
@ -84,7 +84,7 @@ fn pandoc_writer(
~"--from=markdown", ~"--from=markdown",
~"--to=html", ~"--to=html",
~"--css=rust.css", ~"--css=rust.css",
~"--output=" + filename ~"--output=" + filename.to_str()
]; ];
do generic_writer |markdown| { do generic_writer |markdown| {
@ -166,15 +166,15 @@ fn generic_writer(+process: fn~(markdown: ~str)) -> writer {
fn make_local_filename( fn make_local_filename(
config: config::config, config: config::config,
page: doc::page page: doc::page
) -> ~str { ) -> Path {
let filename = make_filename(config, page); let filename = make_filename(config, page);
path::connect(config.output_dir, filename) config.output_dir.push_rel(&filename)
} }
fn make_filename( fn make_filename(
config: config::config, config: config::config,
page: doc::page page: doc::page
) -> ~str { ) -> Path {
let filename = { let filename = {
match page { match page {
doc::cratepage(doc) => { doc::cratepage(doc) => {
@ -196,50 +196,50 @@ fn make_filename(
config::pandoc_html => ~"html" config::pandoc_html => ~"html"
}; };
filename + ~"." + ext Path(filename).with_filetype(ext)
} }
#[test] #[test]
fn should_use_markdown_file_name_based_off_crate() { fn should_use_markdown_file_name_based_off_crate() {
let config = { let config = {
output_dir: ~"output/dir", output_dir: Path("output/dir"),
output_format: config::markdown, output_format: config::markdown,
output_style: config::doc_per_crate output_style: config::doc_per_crate
with config::default_config(~"input/test.rc") with config::default_config(&Path("input/test.rc"))
}; };
let doc = test::mk_doc(~"test", ~""); let doc = test::mk_doc(~"test", ~"");
let page = doc::cratepage(doc.cratedoc()); let page = doc::cratepage(doc.cratedoc());
let filename = make_local_filename(config, page); let filename = make_local_filename(config, page);
assert filename == ~"output/dir/test.md"; assert filename.to_str() == ~"output/dir/test.md";
} }
#[test] #[test]
fn should_name_html_crate_file_name_index_html_when_doc_per_mod() { fn should_name_html_crate_file_name_index_html_when_doc_per_mod() {
let config = { let config = {
output_dir: ~"output/dir", output_dir: Path("output/dir"),
output_format: config::pandoc_html, output_format: config::pandoc_html,
output_style: config::doc_per_mod output_style: config::doc_per_mod
with config::default_config(~"input/test.rc") with config::default_config(&Path("input/test.rc"))
}; };
let doc = test::mk_doc(~"", ~""); let doc = test::mk_doc(~"", ~"");
let page = doc::cratepage(doc.cratedoc()); let page = doc::cratepage(doc.cratedoc());
let filename = make_local_filename(config, page); let filename = make_local_filename(config, page);
assert filename == ~"output/dir/index.html"; assert filename.to_str() == ~"output/dir/index.html";
} }
#[test] #[test]
fn should_name_mod_file_names_by_path() { fn should_name_mod_file_names_by_path() {
let config = { let config = {
output_dir: ~"output/dir", output_dir: Path("output/dir"),
output_format: config::pandoc_html, output_format: config::pandoc_html,
output_style: config::doc_per_mod output_style: config::doc_per_mod
with config::default_config(~"input/test.rc") with config::default_config(&Path("input/test.rc"))
}; };
let doc = test::mk_doc(~"", ~"mod a { mod b { } }"); let doc = test::mk_doc(~"", ~"mod a { mod b { } }");
let modb = doc.cratemod().mods()[0].mods()[0]; let modb = doc.cratemod().mods()[0].mods()[0];
let page = doc::itempage(doc::modtag(modb)); let page = doc::itempage(doc::modtag(modb));
let filename = make_local_filename(config, page); let filename = make_local_filename(config, page);
assert filename == ~"output/dir/a_b.html"; assert filename == Path("output/dir/a_b.html");
} }
#[cfg(test)] #[cfg(test)]
@ -253,7 +253,7 @@ mod test {
} }
} }
fn write_file(path: ~str, s: ~str) { fn write_file(path: &Path, s: ~str) {
import io::WriterUtil; import io::WriterUtil;
match io::file_writer(path, ~[io::Create, io::Truncate]) { match io::file_writer(path, ~[io::Create, io::Truncate]) {

View file

@ -10,7 +10,7 @@ import syntax::parse;
export from_file, from_str, from_file_sess, from_str_sess; export from_file, from_str, from_file_sess, from_str_sess;
fn from_file(file: ~str) -> @ast::crate { fn from_file(file: &Path) -> @ast::crate {
parse::parse_crate_from_file( parse::parse_crate_from_file(
file, ~[], parse::new_parse_sess(none)) file, ~[], parse::new_parse_sess(none))
} }
@ -20,9 +20,9 @@ fn from_str(source: ~str) -> @ast::crate {
~"-", @source, ~[], parse::new_parse_sess(none)) ~"-", @source, ~[], parse::new_parse_sess(none))
} }
fn from_file_sess(sess: session::session, file: ~str) -> @ast::crate { fn from_file_sess(sess: session::session, file: &Path) -> @ast::crate {
parse::parse_crate_from_file( parse::parse_crate_from_file(
file, cfg(sess, file_input(file)), sess.parse_sess) file, cfg(sess, file_input(*file)), sess.parse_sess)
} }
fn from_str_sess(sess: session::session, source: ~str) -> @ast::crate { fn from_str_sess(sess: session::session, source: ~str) -> @ast::crate {

View file

@ -130,13 +130,13 @@ fn time<T>(what: ~str, f: fn() -> T) -> T {
fn run(config: config::config) { fn run(config: config::config) {
let source_file = config.input_crate; let source_file = config.input_crate;
do astsrv::from_file(source_file) |srv| { do astsrv::from_file(source_file.to_str()) |srv| {
do time(~"wait_ast") { do time(~"wait_ast") {
do astsrv::exec(srv) |_ctxt| { } do astsrv::exec(srv) |_ctxt| { }
}; };
let doc = time(~"extract", || { let doc = time(~"extract", || {
let default_name = source_file; let default_name = source_file;
extract::from_srv(srv, default_name) extract::from_srv(srv, default_name.to_str())
}); });
run_passes(srv, doc, ~[ run_passes(srv, doc, ~[
tystr_pass::mk_pass(), tystr_pass::mk_pass(),

View file

@ -52,13 +52,11 @@ fn shift_push() {
} }
fn read_line() { fn read_line() {
let path = path::connect( let path = Path(env!("CFG_SRC_DIR"))
env!("CFG_SRC_DIR"), .push_rel(&Path("src/test/bench/shootout-k-nucleotide.data"));
~"src/test/bench/shootout-k-nucleotide.data"
);
for int::range(0, 3) |_i| { for int::range(0, 3) |_i| {
let reader = result::get(io::file_reader(path)); let reader = result::get(io::file_reader(&path));
while !reader.eof() { while !reader.eof() {
reader.read_line(); reader.read_line();
} }

View file

@ -85,7 +85,8 @@ fn main(args: ~[~str]) {
}; };
let writer = if os::getenv(~"RUST_BENCH").is_some() { let writer = if os::getenv(~"RUST_BENCH").is_some() {
result::get(io::file_writer(~"./shootout-fasta.data", ~[io::Truncate, io::Create])) result::get(io::file_writer(&Path("./shootout-fasta.data"),
~[io::Truncate, io::Create]))
} else { } else {
io::stdout() io::stdout()
}; };

View file

@ -128,11 +128,9 @@ fn main(args: ~[~str]) {
let rdr = if os::getenv(~"RUST_BENCH").is_some() { let rdr = if os::getenv(~"RUST_BENCH").is_some() {
// FIXME: Using this compile-time env variable is a crummy way to // FIXME: Using this compile-time env variable is a crummy way to
// get to this massive data set, but #include_bin chokes on it (#2598) // get to this massive data set, but #include_bin chokes on it (#2598)
let path = path::connect( let path = Path(env!("CFG_SRC_DIR"))
env!("CFG_SRC_DIR"), .push_rel(&Path("src/test/bench/shootout-k-nucleotide.data"));
~"src/test/bench/shootout-k-nucleotide.data" result::get(io::file_reader(&path))
);
result::get(io::file_reader(path))
} else { } else {
io::stdin() io::stdin()
}; };

View file

@ -126,11 +126,9 @@ fn main(args: ~[~str]) {
let rdr = if os::getenv(~"RUST_BENCH").is_some() { let rdr = if os::getenv(~"RUST_BENCH").is_some() {
// FIXME: Using this compile-time env variable is a crummy way to // FIXME: Using this compile-time env variable is a crummy way to
// get to this massive data set, but #include_bin chokes on it (#2598) // get to this massive data set, but #include_bin chokes on it (#2598)
let path = path::connect( let path = Path(env!("CFG_SRC_DIR"))
env!("CFG_SRC_DIR"), .push_rel(&Path("src/test/bench/shootout-k-nucleotide.data"));
~"src/test/bench/shootout-k-nucleotide.data" result::get(io::file_reader(&path))
);
result::get(io::file_reader(path))
} else { } else {
io::stdin() io::stdin()
}; };

View file

@ -112,7 +112,7 @@ fn writer(path: ~str, writech: comm::Chan<comm::Chan<line>>, size: uint)
} }
_ => { _ => {
result::get( result::get(
io::file_writer(path, io::file_writer(&Path(path),
~[io::Create, io::Truncate])) ~[io::Create, io::Truncate]))
} }
}; };

View file

@ -80,7 +80,7 @@ impl io::Reader: word_reader {
} }
fn file_word_reader(filename: ~str) -> word_reader { fn file_word_reader(filename: ~str) -> word_reader {
match io::file_reader(filename) { match io::file_reader(&Path(filename)) {
result::ok(f) => { f as word_reader } result::ok(f) => { f as word_reader }
result::err(e) => { fail fmt!("%?", e) } result::err(e) => { fail fmt!("%?", e) }
} }