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 = {
pgp: bool,
root: ~str,
installdir: ~str,
bindir: ~str,
libdir: ~str,
workdir: ~str,
sourcedir: ~str,
root: Path,
installdir: Path,
bindir: Path,
libdir: Path,
workdir: Path,
sourcedir: Path,
sources: map::hashmap<~str, source>,
mut current_install: ~str,
dep_cache: map::hashmap<~str, bool>,
@ -185,7 +185,7 @@ fn has_archive_extension(p: ~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 {
@ -209,7 +209,7 @@ fn assume_source_method(url: ~str) -> ~str {
if is_git_url(url) {
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";
}
@ -238,7 +238,7 @@ fn load_link(mis: ~[@ast::meta_item]) -> (option<~str>,
(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 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::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
};
if method == ~"file" {
url = os::make_absolute(url);
url = os::make_absolute(&Path(url)).to_str();
}
return @{
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; }
let c = io::read_whole_file_str(filename);
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",
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) {
let dir = path::connect(c.sourcedir, src.name);
let srcfile = path::connect(dir, ~"source.json");
if !os::path_exists(srcfile) { return; }
let srcstr = io::read_whole_file_str(srcfile);
let dir = c.sourcedir.push(src.name);
let srcfile = dir.push("source.json");
if !os::path_exists(&srcfile) { return; }
let srcstr = io::read_whole_file_str(&srcfile);
match json::from_str(result::get(srcstr)) {
ok(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) {
log(debug, ~"loading source: " + src.name);
let dir = path::connect(c.sourcedir, src.name);
let pkgfile = path::connect(dir, ~"packages.json");
if !os::path_exists(pkgfile) { return; }
let pkgstr = io::read_whole_file_str(pkgfile);
let dir = c.sourcedir.push(src.name);
let pkgfile = dir.push("packages.json");
if !os::path_exists(&pkgfile) { return; }
let pkgstr = io::read_whole_file_str(&pkgfile);
match json::from_str(result::get(pkgstr)) {
ok(json::list(js)) => {
for (*js).each |j| {
@ -639,8 +639,8 @@ fn configure(opts: options) -> cargo {
let p = result::get(get_cargo_dir());
let sources = map::str_hash();
try_parse_sources(path::connect(home, ~"sources.json"), sources);
try_parse_sources(path::connect(home, ~"local-sources.json"), sources);
try_parse_sources(&home.push("sources.json"), sources);
try_parse_sources(&home.push("local-sources.json"), sources);
let dep_cache = map::str_hash();
@ -648,22 +648,22 @@ fn configure(opts: options) -> cargo {
pgp: pgp::supported(),
root: home,
installdir: p,
bindir: path::connect(p, ~"bin"),
libdir: path::connect(p, ~"lib"),
workdir: path::connect(p, ~"work"),
sourcedir: path::connect(home, ~"sources"),
bindir: p.push("bin"),
libdir: p.push("lib"),
workdir: p.push("work"),
sourcedir: home.push("sources"),
sources: sources,
mut current_install: ~"",
dep_cache: dep_cache,
opts: opts
};
need_dir(c.root);
need_dir(c.installdir);
need_dir(c.sourcedir);
need_dir(c.workdir);
need_dir(c.libdir);
need_dir(c.bindir);
need_dir(&c.root);
need_dir(&c.installdir);
need_dir(&c.sourcedir);
need_dir(&c.workdir);
need_dir(&c.libdir);
need_dir(&c.bindir);
for sources.each_key |k| {
let mut s = sources.get(k);
@ -672,7 +672,7 @@ fn configure(opts: options) -> cargo {
}
if c.pgp {
pgp::init(c.root);
pgp::init(&c.root);
} else {
warn(~"command `gpg` was not found");
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>
fn run_programs(buildpath: ~str) {
fn run_programs(buildpath: &Path) {
let newv = os::list_dir_path(buildpath);
for newv.each |ct| {
run::run_program(ct, ~[]);
run::run_program(ct.to_str(), ~[]);
}
}
// Runs rustc in <path + subdir> with the given flags
// and returns <path + subdir>
fn run_in_buildpath(what: ~str, path: ~str, subdir: ~str, cf: ~str,
extra_flags: ~[~str]) -> option<~str> {
let buildpath = path::connect(path, subdir);
need_dir(buildpath);
debug!("%s: %s -> %s", what, cf, buildpath);
// and returns <patho + subdir>
fn run_in_buildpath(what: &str, path: &Path, subdir: &Path, cf: &Path,
extra_flags: ~[~str]) -> option<Path> {
let buildpath = path.push_rel(subdir);
need_dir(&buildpath);
debug!("%s: %s -> %s", what, cf.to_str(), buildpath.to_str());
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 {
error(fmt!("rustc failed: %d\n%s\n%s", p.status, p.err, p.out));
return none;
@ -717,37 +719,42 @@ fn run_in_buildpath(what: ~str, path: ~str, subdir: ~str, cf: ~str,
some(buildpath)
}
fn test_one_crate(_c: cargo, path: ~str, cf: ~str) {
let buildpath = match run_in_buildpath(~"testing", path, ~"/test", cf,
~[ ~"--test"]) {
fn test_one_crate(_c: cargo, path: &Path, cf: &Path) {
let buildpath = match run_in_buildpath(~"testing", path,
&Path("test"),
cf,
~[ ~"--test"]) {
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,
~"/build", cf, ~[]) {
&Path("build"),
cf, ~[]) {
none => return,
some(bp) => bp
};
let newv = os::list_dir_path(buildpath);
let newv = os::list_dir_path(&buildpath);
let exec_suffix = os::exe_suffix();
for newv.each |ct| {
if (exec_suffix != ~"" && str::ends_with(ct, exec_suffix)) ||
(exec_suffix == ~"" && !str::starts_with(path::basename(ct),
~"lib")) {
debug!(" bin: %s", ct);
install_to_dir(ct, c.bindir);
if (exec_suffix != ~"" && str::ends_with(ct.to_str(),
exec_suffix)) ||
(exec_suffix == ~"" &&
!str::starts_with(option::get(ct.filename()),
~"lib")) {
debug!(" bin: %s", ct.to_str());
install_to_dir(ct, &c.bindir);
if c.opts.mode == system_mode {
// FIXME (#2662): Put this file in PATH / symlink it so it can
// be used as a generic executable
// `cargo install -G rustray` and `rustray file.obj`
}
} else {
debug!(" lib: %s", ct);
install_to_dir(ct, c.libdir);
debug!(" lib: %s", ct.to_str());
install_to_dir(ct, &c.libdir);
}
}
}
@ -756,23 +763,22 @@ fn install_one_crate(c: cargo, path: ~str, cf: ~str) {
fn rustc_sysroot() -> ~str {
match os::self_exe_path() {
some(path) => {
let path = ~[path, ~"..", ~"bin", ~"rustc"];
let rustc = path::normalize(path::connect_many(path));
debug!(" rustc: %s", rustc);
rustc
let rustc = path.push_many([~"..", ~"bin", ~"rustc"]);
debug!(" rustc: %s", rustc.to_str());
rustc.to_str()
}
none => ~"rustc"
}
}
fn install_source(c: cargo, path: ~str) {
debug!("source: %s", path);
fn install_source(c: cargo, path: &Path) {
debug!("source: %s", path.to_str());
os::change_dir(path);
let mut cratefiles = ~[];
for os::walk_dir(~".") |p| {
if str::ends_with(p, ~".rc") {
vec::push(cratefiles, p);
for os::walk_dir(&Path(".")) |p| {
if p.filetype() == some(~"rc") {
vec::push(cratefiles, *p);
}
}
@ -781,7 +787,7 @@ fn install_source(c: cargo, path: ~str) {
}
for cratefiles.each |cf| {
match load_crate(cf) {
match load_crate(&cf) {
none => again,
some(crate) => {
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
// condition")
let wd_base = c.workdir + path::path_sep();
let wd = match tempfile::mkdtemp(wd_base, ~"") {
some(wd) => wd,
none => fail fmt!("needed temp dir: %s", wd_base)
};
install_query(c, wd, query);
let wd = get_temp_workdir(c);
install_query(c, &wd, query);
}
os::change_dir(path);
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>) {
run::program_output(~"git", ~[~"clone", url, wd]);
fn install_git(c: cargo, wd: &Path, url: ~str, reference: option<~str>) {
run::program_output(~"git", ~[~"clone", url, wd.to_str()]);
if option::is_some(reference) {
let r = option::get(reference);
os::change_dir(wd);
@ -820,25 +821,27 @@ fn install_git(c: cargo, wd: ~str, url: ~str, reference: option<~str>) {
install_source(c, wd);
}
fn install_curl(c: cargo, wd: ~str, url: ~str) {
let tarpath = path::connect(wd, ~"pkg.tar");
fn install_curl(c: cargo, wd: &Path, url: ~str) {
let tarpath = wd.push("pkg.tar");
let p = run::program_output(~"curl", ~[~"-f", ~"-s", ~"-o",
tarpath, url]);
tarpath.to_str(), url]);
if p.status != 0 {
fail fmt!("fetch of %s failed: %s", url, p.err);
}
run::run_program(~"tar", ~[~"-x", ~"--strip-components=1",
~"-C", wd, ~"-f", tarpath]);
~"-C", wd.to_str(),
~"-f", tarpath.to_str()]);
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",
~"-C", wd, ~"-f", path]);
~"-C", wd.to_str(),
~"-f", path.to_str()]);
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 method = match pkg.method {
~"git" => ~"git",
@ -850,7 +853,7 @@ fn install_package(c: cargo, src: ~str, wd: ~str, pkg: package) {
match method {
~"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),
_ => ()
}
@ -866,7 +869,7 @@ fn cargo_suggestion(c: cargo, fallback: fn())
fallback();
}
fn install_uuid(c: cargo, wd: ~str, uuid: ~str) {
fn install_uuid(c: cargo, wd: &Path, uuid: ~str) {
let mut ps = ~[];
for_each_package(c, |s, p| {
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 = ~[];
for_each_package(c, |s, p| {
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) {
some(s) => {
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);
}
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) {
some(s) => {
let packages = copy s.packages;
@ -952,59 +955,45 @@ fn cmd_uninstall(c: cargo) {
return;
}
let lib = c.libdir;
let bin = c.bindir;
let lib = &c.libdir;
let bin = &c.bindir;
let target = c.opts.free[2u];
// FIXME (#2662): needs stronger pattern matching
// FIXME (#2662): needs to uninstall from a specified location in a
// cache instead of looking for it (binaries can be uninstalled by
// 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) {
for os::list_dir(lib).each |file| {
match str::find_str(file, ~"-" + target + ~"-") {
some(idx) => {
let full = path::normalize(path::connect(lib, file));
if os::remove_file(full) {
info(~"uninstalled: '" + full + ~"'");
} else {
error(~"could not uninstall: '" + full + ~"'");
}
return;
}
none => again
some(_) => if !try_uninstall(&lib.push(file)) { return },
none => ()
}
}
error(~"can't find package with uuid: " + target);
} else {
for os::list_dir(lib).each |file| {
match str::find_str(file, ~"lib" + target + ~"-") {
some(idx) => {
let full = path::normalize(path::connect(lib,
file));
if os::remove_file(full) {
info(~"uninstalled: '" + full + ~"'");
} else {
error(~"could not uninstall: '" + full + ~"'");
}
return;
}
none => again
some(_) => if !try_uninstall(&lib.push(file)) { return },
none => ()
}
}
for os::list_dir(bin).each |file| {
match str::find_str(file, target) {
some(idx) => {
let full = path::normalize(path::connect(bin, file));
if os::remove_file(full) {
info(~"uninstalled: '" + full + ~"'");
} else {
error(~"could not uninstall: '" + full + ~"'");
}
return;
}
none => again
some(_) => if !try_uninstall(&lib.push(file)) { return },
none => ()
}
}
@ -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) {
some(inst) => {
if inst {
@ -1025,7 +1014,7 @@ fn install_query(c: cargo, wd: ~str, target: ~str) {
c.dep_cache.insert(target, true);
if is_archive_path(target) {
install_file(c, wd, target);
install_file(c, wd, &Path(target));
return;
} else if is_git_url(target) {
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 {
let wd_base = c.workdir + path::path_sep();
let wd = match tempfile::mkdtemp(wd_base, ~"") {
some(wd) => wd,
none => fail fmt!("needed temp dir: %s", wd_base)
};
let wd = get_temp_workdir(c);
if vec::len(c.opts.free) == 2u {
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 {
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;
}
sync(c);
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) {
@ -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 srcfile = path::connect(dir, ~"source.json.new");
let destsrcfile = path::connect(dir, ~"source.json");
let pkgfile = path::connect(dir, ~"packages.json.new");
let destpkgfile = path::connect(dir, ~"packages.json");
let keyfile = path::connect(dir, ~"key.gpg");
let srcsigfile = path::connect(dir, ~"source.json.sig");
let sigfile = path::connect(dir, ~"packages.json.sig");
let url = src.url;
let srcfile = dir.push("source.json.new");
let destsrcfile = dir.push("source.json");
let pkgfile = dir.push("packages.json.new");
let destpkgfile = dir.push("packages.json");
let keyfile = dir.push("key.gpg");
let srcsigfile = dir.push("source.json.sig");
let sigfile = dir.push("packages.json.sig");
let url = Path(src.url);
let mut has_src_file = false;
if !os::copy_file(path::connect(url, ~"packages.json"), pkgfile) {
error(fmt!("fetch for source %s (url %s) failed", name, url));
if !os::copy_file(&url.push("packages.json"), &pkgfile) {
error(fmt!("fetch for source %s (url %s) failed",
name, url.to_str()));
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;
}
os::copy_file(path::connect(url, ~"source.json.sig"), srcsigfile);
os::copy_file(path::connect(url, ~"packages.json.sig"), sigfile);
os::copy_file(&url.push("source.json.sig"), &srcsigfile);
os::copy_file(&url.push("packages.json.sig"), &sigfile);
match copy src.key {
some(u) => {
let p = run::program_output(~"curl",
~[~"-f", ~"-s", ~"-o", keyfile, u]);
~[~"-f", ~"-s",
~"-o", keyfile.to_str(), u]);
if p.status != 0 {
error(fmt!("fetch for source %s (key %s) failed", name, u));
return false;
}
pgp::add(c.root, keyfile);
pgp::add(&c.root, &keyfile);
}
_ => ()
}
match (src.key, src.keyfp) {
(some(_), some(f)) => {
let r = pgp::verify(c.root, pkgfile, sigfile, f);
let r = pgp::verify(&c.root, &pkgfile, &sigfile, f);
if !r {
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 {
let e = pgp::verify(c.root, srcfile, srcsigfile, f);
let e = pgp::verify(&c.root, &srcfile, &srcsigfile, f);
if !e {
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 {
copy_warn(srcfile, destsrcfile);
copy_warn(&srcfile, &destsrcfile);
}
os::remove_file(keyfile);
os::remove_file(srcfile);
os::remove_file(srcsigfile);
os::remove_file(pkgfile);
os::remove_file(sigfile);
os::remove_file(&keyfile);
os::remove_file(&srcfile);
os::remove_file(&srcsigfile);
os::remove_file(&pkgfile);
os::remove_file(&sigfile);
info(fmt!("synced source: %s", name));
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 srcfile = path::connect(dir, ~"source.json");
let pkgfile = path::connect(dir, ~"packages.json");
let keyfile = path::connect(dir, ~"key.gpg");
let srcsigfile = path::connect(dir, ~"source.json.sig");
let sigfile = path::connect(dir, ~"packages.json.sig");
let srcfile = dir.push("source.json");
let pkgfile = dir.push("packages.json");
let keyfile = dir.push("key.gpg");
let srcsigfile = dir.push("source.json.sig");
let sigfile = dir.push("packages.json.sig");
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) {
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")) {
let p = run::program_output(~"git", ~[~"clone", url, dir]);
if !os::path_exists(&dir.push(".git")) {
let p = run::program_output(~"git", ~[~"clone", url, dir.to_str()]);
if p.status != 0 {
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 {
some(u) => {
let p = run::program_output(~"curl",
~[~"-f", ~"-s", ~"-o", keyfile, u]);
~[~"-f", ~"-s",
~"-o", keyfile.to_str(), u]);
if p.status != 0 {
error(fmt!("fetch for source %s (key %s) failed", name, u));
rollback(name, dir, false);
return false;
}
pgp::add(c.root, keyfile);
pgp::add(&c.root, &keyfile);
}
_ => ()
}
match (src.key, src.keyfp) {
(some(_), some(f)) => {
let r = pgp::verify(c.root, pkgfile, sigfile, f);
let r = pgp::verify(&c.root, &pkgfile, &sigfile, f);
if !r {
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 {
let e = pgp::verify(c.root, srcfile, srcsigfile, f);
let e = pgp::verify(&c.root, &srcfile, &srcsigfile, f);
if !e {
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));
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 srcfile = path::connect(dir, ~"source.json.new");
let destsrcfile = path::connect(dir, ~"source.json");
let pkgfile = path::connect(dir, ~"packages.json.new");
let destpkgfile = path::connect(dir, ~"packages.json");
let keyfile = path::connect(dir, ~"key.gpg");
let srcsigfile = path::connect(dir, ~"source.json.sig");
let sigfile = path::connect(dir, ~"packages.json.sig");
let srcfile = dir.push("source.json.new");
let destsrcfile = dir.push("source.json");
let pkgfile = dir.push("packages.json.new");
let destpkgfile = dir.push("packages.json");
let keyfile = dir.push("key.gpg");
let srcsigfile = dir.push("source.json.sig");
let sigfile = dir.push("packages.json.sig");
let mut url = src.url;
let smart = !str::ends_with(src.url, ~"packages.json");
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",
~[~"-f", ~"-s", ~"-o", pkgfile, url]);
~[~"-f", ~"-s",
~"-o", pkgfile.to_str(), url]);
if p.status != 0 {
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";
let p =
run::program_output(~"curl",
~[~"-f", ~"-s", ~"-o", srcfile, url]);
~[~"-f", ~"-s",
~"-o", srcfile.to_str(), url]);
if p.status == 0 {
has_src_file = true;
@ -1323,12 +1322,13 @@ fn sync_one_curl(c: cargo, dir: ~str, src: source) -> bool {
match copy src.key {
some(u) => {
let p = run::program_output(~"curl",
~[~"-f", ~"-s", ~"-o", keyfile, u]);
~[~"-f", ~"-s",
~"-o", keyfile.to_str(), u]);
if p.status != 0 {
error(fmt!("fetch for source %s (key %s) failed", name, u));
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";
}
let mut p = run::program_output(~"curl", ~[~"-f", ~"-s", ~"-o",
sigfile, url]);
let mut p = run::program_output(~"curl",
~[~"-f", ~"-s", ~"-o",
sigfile.to_str(), url]);
if p.status != 0 {
error(fmt!("fetch for source %s (sig %s) failed", name, url));
return false;
}
let r = pgp::verify(c.root, pkgfile, sigfile, f);
let r = pgp::verify(&c.root, &pkgfile, &sigfile, f);
if !r {
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",
~[~"-f", ~"-s", ~"-o",
srcsigfile, url]);
srcsigfile.to_str(), url]);
if p.status != 0 {
error(fmt!("fetch for source %s (sig %s) failed",
name, url));
return false;
}
let e = pgp::verify(c.root, srcfile, srcsigfile, f);
let e = pgp::verify(&c.root, &srcfile, &srcsigfile, f);
if !e {
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 {
copy_warn(srcfile, destsrcfile);
copy_warn(&srcfile, &destsrcfile);
}
os::remove_file(keyfile);
os::remove_file(srcfile);
os::remove_file(srcsigfile);
os::remove_file(pkgfile);
os::remove_file(sigfile);
os::remove_file(&keyfile);
os::remove_file(&srcfile);
os::remove_file(&srcsigfile);
os::remove_file(&pkgfile);
os::remove_file(&sigfile);
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) {
let name = src.name;
let dir = path::connect(c.sourcedir, name);
let dir = c.sourcedir.push(name);
info(fmt!("syncing source: %s...", name));
need_dir(dir);
need_dir(&dir);
let result = match src.method {
~"git" => sync_one_git(c, dir, src),
~"file" => sync_one_file(c, dir, src),
_ => sync_one_curl(c, dir, src)
~"git" => sync_one_git(c, &dir, src),
~"file" => sync_one_file(c, &dir, src),
_ => sync_one_curl(c, &dir, src)
};
if result {
@ -1421,35 +1422,39 @@ fn cmd_init(c: cargo) {
let srcurl = ~"http://www.rust-lang.org/cargo/sources.json";
let sigurl = ~"http://www.rust-lang.org/cargo/sources.json.sig";
let srcfile = path::connect(c.root, ~"sources.json.new");
let sigfile = path::connect(c.root, ~"sources.json.sig");
let destsrcfile = path::connect(c.root, ~"sources.json");
let srcfile = c.root.push("sources.json.new");
let sigfile = c.root.push("sources.json.sig");
let destsrcfile = c.root.push("sources.json");
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 {
error(fmt!("fetch of sources.json failed: %s", p.out));
return;
}
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 {
error(fmt!("fetch of sources.json.sig failed: %s", p.out));
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 {
error(fmt!("signature verification failed for '%s'", srcfile));
error(fmt!("signature verification failed for '%s'",
srcfile.to_str()));
return;
}
copy_warn(srcfile, destsrcfile);
os::remove_file(srcfile);
os::remove_file(sigfile);
copy_warn(&srcfile, &destsrcfile);
os::remove_file(&srcfile);
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) {
@ -1530,25 +1535,26 @@ fn cmd_search(c: cargo) {
info(fmt!("found %d packages", n));
}
fn install_to_dir(srcfile: ~str, destdir: ~str) {
let newfile = path::connect(destdir, path::basename(srcfile));
fn install_to_dir(srcfile: &Path, destdir: &Path) {
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 {
info(fmt!("installed: '%s'", newfile));
info(fmt!("installed: '%s'", newfile.to_str()));
} else {
error(fmt!("could not install: '%s'", newfile));
error(fmt!("could not install: '%s'", newfile.to_str()));
}
}
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());
if os::path_exists(out) {
copy_warn(out, path::connect(c.root, ~"cache.json.old"));
if os::path_exists(&out) {
copy_warn(&out, &c.root.push("cache.json.old"));
}
}
fn dump_sources(c: cargo) {
@ -1556,15 +1562,15 @@ fn dump_sources(c: cargo) {
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) {
copy_warn(out, path::connect(c.root, ~"sources.json.old"));
if os::path_exists(&out) {
copy_warn(&out, &c.root.push("sources.json.old"));
}
match io::buffered_file_writer(out) {
match io::buffered_file_writer(&out) {
result::ok(writer) => {
let hash = map::str_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) {
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 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" {
cmd_init(c);

View File

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

View File

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

View File

@ -42,12 +42,16 @@ fn parse_config(args: ~[~str]) -> config {
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"),
run_lib_path: getopts::opt_str(matches, ~"run-lib-path"),
rustc_path: getopts::opt_str(matches, ~"rustc-path"),
src_base: getopts::opt_str(matches, ~"src-base"),
build_base: getopts::opt_str(matches, ~"build-base"),
aux_base: getopts::opt_str(matches, ~"aux-base"),
rustc_path: opt_path(matches, ~"rustc-path"),
src_base: opt_path(matches, ~"src-base"),
build_base: opt_path(matches, ~"build-base"),
aux_base: opt_path(matches, ~"aux-base"),
stage_id: getopts::opt_str(matches, ~"stage-id"),
mode: str_mode(getopts::opt_str(matches, ~"mode")),
run_ignored: getopts::opt_present(matches, ~"ignored"),
@ -55,7 +59,9 @@ fn parse_config(args: ~[~str]) -> config {
if vec::len(matches.free) > 0u {
option::some(matches.free[0])
} 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"),
rustcflags: getopts::opt_maybe_str(matches, ~"rustcflags"),
verbose: getopts::opt_present(matches, ~"verbose")};
@ -66,9 +72,9 @@ fn log_config(config: config) {
logv(c, fmt!("configuration:"));
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!("rustc_path: %s", config.rustc_path));
logv(c, fmt!("src_base: %s", config.src_base));
logv(c, fmt!("build_base: %s", config.build_base));
logv(c, fmt!("rustc_path: %s", config.rustc_path.to_str()));
logv(c, fmt!("src_base: %s", config.src_base.to_str()));
logv(c, fmt!("build_base: %s", config.build_base.to_str()));
logv(c, fmt!("stage_id: %s", config.stage_id));
logv(c, fmt!("mode: %s", mode_str(config.mode)));
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,
logfile:
match config.logfile {
option::some(s) => option::some(s),
option::some(s) => option::some(s.to_str()),
option::none => option::none
}
}
}
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 = ~[];
for os::list_dir_path(config.src_base).each |file| {
let file = file;
debug!("inspecting file %s", file);
for os::list_dir_path(&config.src_base).each |file| {
let file = copy file;
debug!("inspecting file %s", file.to_str());
if is_test(config, file) {
vec::push(tests, make_test(config, file))
}
@ -141,7 +148,7 @@ fn make_tests(config: config) -> ~[test::test_desc] {
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
let valid_extensions =
match config.mode {
@ -149,7 +156,7 @@ fn is_test(config: config, testfile: ~str) -> bool {
_ => ~[~".rc", ~".rs"]
};
let invalid_prefixes = ~[~".", ~"#", ~"~"];
let name = path::basename(testfile);
let name = option::get(testfile.filename());
let mut valid = false;
@ -164,7 +171,7 @@ fn is_test(config: config, testfile: ~str) -> bool {
return valid;
}
fn make_test(config: config, testfile: ~str) ->
fn make_test(config: config, testfile: &Path) ->
test::test_desc {
{
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 {
fmt!("[%s] %s", mode_str(config.mode), testfile)
fn make_test_name(config: config, testfile: &Path) -> ~str {
fmt!("[%s] %s", mode_str(config.mode), testfile.to_str())
}
fn make_test_closure(config: config, testfile: ~str) -> test::test_fn {
fn~() { runtest::run(config, copy testfile) }
fn make_test_closure(config: config, testfile: &Path) -> test::test_fn {
let testfile = testfile.to_str();
fn~() { runtest::run(config, testfile) }
}
// Local Variables:

View File

@ -6,7 +6,7 @@ export expected_error;
type expected_error = { line: uint, kind: ~str, msg: ~str };
// 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 rdr = result::get(io::file_reader(testfile));
let mut line_num = 1u;

View File

@ -14,7 +14,7 @@ type test_props = {
compile_flags: option<~str>,
// If present, the name of a file that this test should match when
// pretty-printed
pp_exact: option<~str>,
pp_exact: option<Path>,
// Modules from aux directory that should be compiled
aux_builds: ~[~str],
// Environment settings to use during execution
@ -22,7 +22,7 @@ type test_props = {
};
// 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 aux_builds = ~[];
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;
for iter_header(testfile) |ln| {
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));
while !rdr.eof() {
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") {
option::some(s) => option::some(s),
option::some(s) => option::some(Path(s)),
option::none => {
if parse_name_directive(line, ~"pp-exact") {
option::some(path::basename(testfile))
option::some(testfile.file_path())
} else {
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.
io::stdout().write_str(~"\n\n");
}
debug!("running %s", testfile);
let props = load_props(testfile);
let testfile = Path(testfile);
debug!("running %s", testfile.to_str());
let props = load_props(&testfile);
match config.mode {
mode_compile_fail => run_cfail_test(config, props, testfile),
mode_run_fail => run_rfail_test(config, props, testfile),
mode_run_pass => run_rpass_test(config, props, testfile),
mode_pretty => run_pretty_test(config, props, testfile)
mode_compile_fail => run_cfail_test(config, props, &testfile),
mode_run_fail => run_rfail_test(config, props, &testfile),
mode_run_pass => run_rpass_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);
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);
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);
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); }
}
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) {
logv(config, ~"testing for exact 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 =
match props.pp_exact {
option::some(file) => {
let filepath = path::connect(path::dirname(testfile), file);
result::get(io::read_whole_file_str(filepath))
let filepath = testfile.dir_path().push_rel(&file);
result::get(io::read_whole_file_str(&filepath))
}
option::none => { srcs[vec::len(srcs) - 2u] }
};
@ -136,15 +137,15 @@ fn run_pretty_test(config: config, props: test_props, testfile: ~str) {
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),
~[], 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 args = ~[~"-", ~"--pretty", ~"normal"];
return {prog: prog, args: args};
return {prog: prog.to_str(), args: args};
}
fn compare_source(expected: ~str, actual: ~str) {
@ -168,28 +169,30 @@ actual:\n\
}
fn typecheck_source(config: config, props: test_props,
testfile: ~str, src: ~str) -> procres {
testfile: &Path, src: ~str) -> procres {
compose_and_run_compiler(
config, props, testfile,
make_typecheck_args(config, testfile),
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 mut args = ~[~"-",
~"--no-trans", ~"--lib", ~"-L", config.build_base,
~"-L", aux_output_dir_name(config, testfile)];
~"--no-trans", ~"--lib",
~"-L", config.build_base.to_str(),
~"-L",
aux_output_dir_name(config, testfile).to_str()];
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,
testfile: ~str,
testfile: &Path,
procres: procres) {
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 {
@ -228,7 +231,7 @@ fn check_error_patterns(props: test_props,
}
fn check_expected_errors(expected_errors: ~[errors::expected_error],
testfile: ~str,
testfile: &Path,
procres: procres) {
// 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| {
fmt!("%s:%u:", testfile, ee.line)
fmt!("%s:%u:", testfile.to_str(), ee.line)
});
// 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};
fn compile_test(config: config, props: test_props,
testfile: ~str) -> procres {
let link_args = ~[~"-L", aux_output_dir_name(config, testfile)];
testfile: &Path) -> procres {
let link_args = ~[~"-L", aux_output_dir_name(config, testfile).to_str()];
compose_and_run_compiler(
config, props, testfile,
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,
testfile: ~str) -> procres {
testfile: &Path) -> procres {
compose_and_run(config, testfile,
make_run_args(config, props, testfile),
props.exec_env,
@ -311,26 +314,28 @@ fn exec_compiled_test(config: config, props: test_props,
fn compose_and_run_compiler(
config: config,
props: test_props,
testfile: ~str,
testfile: &Path,
args: procargs,
input: option<~str>) -> procres {
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| {
let abs_ab = path::connect(config.aux_base, rel_ab);
let abs_ab = config.aux_base.push_rel(&Path(rel_ab));
let aux_args =
make_compile_args(config, props, ~[~"--lib"] + extra_link_args,
|a,b| make_lib_name(a, b, testfile), abs_ab);
let auxres = compose_and_run(config, abs_ab, aux_args, ~[],
|a,b| make_lib_name(a, b, testfile), &abs_ab);
let auxres = compose_and_run(config, &abs_ab, aux_args, ~[],
config.compile_lib_path, option::none);
if auxres.status != 0 {
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);
}
}
@ -339,14 +344,14 @@ fn compose_and_run_compiler(
config.compile_lib_path, input)
}
fn ensure_dir(path: Path) {
fn ensure_dir(path: &Path) {
if os::path_is_dir(path) { return; }
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,
procenv: ~[(~str, ~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],
xform: fn(config, ~str) -> ~str, testfile: ~str) ->
procargs {
xform: fn(config, (&Path)) -> Path,
testfile: &Path) -> procargs {
let prog = config.rustc_path;
let mut args = ~[testfile, ~"-o", xform(config, testfile),
~"-L", config.build_base] + extras;
let mut args = ~[testfile.to_str(),
~"-o", xform(config, testfile).to_str(),
~"-L", config.build_base.to_str()]
+ extras;
args += split_maybe_args(config.rustcflags);
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
// happens; rustc ignores everything except for the directory.
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 {
output_base_name(config, testfile) + os::exe_suffix()
fn make_exe_name(config: config, testfile: &Path) -> Path {
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 {
let toolargs = {
// 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)
};
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))};
}
@ -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)],
input: option<~str>) -> procres {
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))
}
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, err, ~"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) {
let outfile = make_out_name(config, testfile, extension);
let writer = result::get(
io::file_writer(outfile, ~[io::Create, io::Truncate]));
io::file_writer(&outfile, ~[io::Create, io::Truncate]));
writer.write_str(out);
}
fn make_out_name(config: config, testfile: ~str, extension: ~str) -> ~str {
output_base_name(config, testfile) + ~"." + extension
fn make_out_name(config: config, testfile: &Path, extension: ~str) -> Path {
output_base_name(config, testfile).with_filetype(extension)
}
fn aux_output_dir_name(config: config, testfile: ~str) -> ~str {
output_base_name(config, testfile) + ~".libaux"
fn aux_output_dir_name(config: config, testfile: &Path) -> Path {
output_base_name(config, testfile).with_filetype("libaux")
}
fn output_testname(testfile: ~str) -> ~str {
let parts = str::split_char(path::basename(testfile), '.');
str::connect(vec::slice(parts, 0u, vec::len(parts) - 1u), ~".")
fn output_testname(testfile: &Path) -> Path {
Path(option::get(testfile.filestem()))
}
fn output_base_name(config: config, testfile: ~str) -> ~str {
let base = config.build_base;
let filename = output_testname(testfile);
fmt!("%s%s.%s", base, filename, config.stage_id)
fn output_base_name(config: config, testfile: &Path) -> Path {
config.build_base
.push_rel(&output_testname(testfile))
.with_filetype(config.stage_id)
}
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, }
type context = { mode: test_mode }; // + rng
fn write_file(filename: ~str, content: ~str) {
fn write_file(filename: &Path, content: ~str) {
result::get(
io::file_writer(filename, ~[io::Create, io::Truncate]))
.write_str(content);
@ -18,13 +18,13 @@ fn contains(haystack: ~str, needle: ~str) -> bool {
str::contains(haystack, needle)
}
fn find_rust_files(&files: ~[~str], path: ~str) {
if str::ends_with(path, ~".rs") && !contains(path, ~"utf8") {
fn find_rust_files(files: &mut ~[Path], path: &Path) {
if path.filetype() == some(~"rs") && !contains(path.to_str(), ~"utf8") {
// ignoring "utf8" tests because something is broken
files += ~[path];
vec::push(*files, *path);
} else if os::path_is_dir(path)
&& !contains(path, ~"compile-fail")
&& !contains(path, ~"build") {
&& !contains(path.to_str(), ~"compile-fail")
&& !contains(path.to_str(), ~"build") {
for os::list_dir_path(path).each |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,
filename: ~str, cx: context) {
filename: &Path, cx: context) {
let stolen = steal(crate, cx.mode);
let extra_exprs = vec::filter(common_exprs(),
|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>(
crate: ast::crate,
codemap: codemap::codemap,
filename: ~str,
filename: &Path,
thing_label: ~str,
things: ~[T],
stringifier: fn@(@T, syntax::parse::token::ident_interner) -> ~str,
replacer: fn@(ast::crate, uint, T, test_mode) -> ast::crate,
cx: context
) {
error!("%s contains %u %s objects", filename,
error!("%s contains %u %s objects", filename.to_str(),
vec::len(things), thing_label);
// Assuming we're not generating any token_trees
@ -253,6 +253,7 @@ fn check_variants_T<T: copy>(
if L < 100u {
do under(uint::min(L, 20u)) |i| {
log(error, ~"Replacing... #" + uint::str(i));
let fname = str::from_slice(filename.to_str());
do under(uint::min(L, 30u)) |j| {
log(error, ~"With... " + stringifier(@things[j], intr));
let crate2 = @replacer(crate, i, things[j], cx.mode);
@ -265,7 +266,7 @@ fn check_variants_T<T: copy>(
intr,
diagnostic::mk_span_handler(handler, codemap),
crate2,
filename,
fname,
rdr, a,
pprust::no_ann(),
false))
@ -276,11 +277,12 @@ fn check_variants_T<T: copy>(
}
tm_run => {
let file_label = fmt!("rusttmp/%s_%s_%u_%u",
last_part(filename),
last_part(filename.to_str()),
thing_label, i, j);
let safe_to_run = !(content_is_dangerous_to_run(*str3)
|| 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
// or randomness.
// 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) {
let filename = suggested_filename_prefix + ~".rs";
let filename = &suggested_filename_prefix.with_filetype("rs");
write_file(filename, code);
let compile_result = check_compiling(filename);
@ -320,32 +322,32 @@ fn check_whole_compiler(code: ~str, suggested_filename_prefix: ~str,
match run_result {
passed | cleanly_rejected(_) | known_bug(_) => {
removeIfExists(suggested_filename_prefix);
removeIfExists(suggested_filename_prefix + ~".rs");
removeDirIfExists(suggested_filename_prefix + ~".dSYM");
removeIfExists(&suggested_filename_prefix.with_filetype("rs"));
removeDirIfExists(&suggested_filename_prefix.with_filetype("dSYM"));
}
failed(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!
assert !contains(filename, ~" ");
run::program_output(~"bash", ~[~"-c", ~"rm " + filename]);
assert !contains(filename.to_str(), ~" ");
run::program_output(~"bash", ~[~"-c", ~"rm " + filename.to_str()]);
}
fn removeDirIfExists(filename: ~str) {
fn removeDirIfExists(filename: &Path) {
// So sketchy!
assert !contains(filename, ~" ");
run::program_output(~"bash", ~[~"-c", ~"rm -r " + filename]);
assert !contains(filename.to_str(), ~" ");
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(
~"/Users/jruderman/scripts/timed_run_rust_program.py",
~[exe_filename]);
~[exe_filename.to_str()]);
let comb = p.out + ~"\n" + p.err;
if str::len(comb) > 1u {
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(
~"/Users/jruderman/code/rust/build/x86_64-apple-darwin/\
stage1/bin/rustc",
~[filename]);
~[filename.to_str()]);
//error!("Status: %d", p.status);
if p.status == 0 {
@ -415,11 +417,11 @@ fn check_compiling(filename: ~str) -> happiness {
fn parse_and_print(code: @~str) -> ~str {
let filename = ~"tmp.rs";
let filename = Path("tmp.rs");
let sess = parse::new_parse_sess(option::none);
write_file(filename, *code);
write_file(&filename, *code);
let crate = parse::parse_crate_from_source_str(
filename, code, ~[], sess);
filename.to_str(), code, ~[], sess);
do io::with_str_reader(*code) |rdr| {
as_str(|a|
pprust::print_crate(
@ -428,7 +430,7 @@ fn parse_and_print(code: @~str) -> ~str {
syntax::parse::token::mk_fake_ident_interner(),
sess.span_diagnostic,
crate,
filename,
filename.to_str(),
rdr, a,
pprust::no_ann(),
false) )
@ -486,7 +488,7 @@ fn content_might_not_converge(code: ~str) -> bool {
return false;
}
fn file_might_not_converge(filename: ~str) -> bool {
fn file_might_not_converge(filename: &Path) -> bool {
let confusing_files = ~[
~"expr-alt.rs", // pretty-printing "(a = b) = c"
// 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;
}
@ -519,8 +525,8 @@ fn check_roundtrip_convergence(code: @~str, maxIters: uint) {
error!("Converged after %u iterations", i);
} else {
error!("Did not converge after %u iterations!", i);
write_file(~"round-trip-a.rs", *oldv);
write_file(~"round-trip-b.rs", *newv);
write_file(&Path("round-trip-a.rs"), *oldv);
write_file(&Path("round-trip-b.rs"), *newv);
run::run_program(~"diff",
~[~"-w", ~"-u", ~"round-trip-a.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));
for files.each |file| {
if !file_might_not_converge(file) {
let s = @result::get(io::read_whole_file_str(file));
if !file_might_not_converge(&file) {
let s = @result::get(io::read_whole_file_str(&file));
if !content_might_not_converge(*s) {
error!("pp converge: %s", file);
error!("pp converge: %s", file.to_str());
// Change from 7u to 2u once
// https://github.com/mozilla/rust/issues/850 is fixed
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| {
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\
file_might_not_converge");
again;
}
let s = @result::get(io::read_whole_file_str(file));
let s = @result::get(io::read_whole_file_str(&file));
if contains(*s, ~"#") {
again; // Macros are confusing
}
@ -562,11 +569,11 @@ fn check_variants(files: ~[~str], cx: context) {
again;
}
log(error, ~"check_variants: " + file);
log(error, ~"check_variants: " + file.to_str());
let sess = parse::new_parse_sess(option::none);
let crate =
parse::parse_crate_from_source_str(
file,
file.to_str(),
s, ~[], sess);
io::with_str_reader(*s, |rdr| {
error!("%s",
@ -576,12 +583,12 @@ fn check_variants(files: ~[~str], cx: context) {
syntax::parse::token::mk_fake_ident_interner(),
sess.span_diagnostic,
crate,
file,
file.to_str(),
rdr, a,
pprust::no_ann(),
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;
}
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 ==");
check_convergence(files);
error!("== check_variants: converge ==");

View File

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

View File

@ -4,7 +4,12 @@
import option::{some, none};
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 str::{StrSlice, UniqueStr};
import vec::{ConstVector, CopyableVector, ImmutableVector};
@ -14,7 +19,8 @@ import num::Num;
import ptr::Ptr;
import to_str::ToStr;
export Path, option, some, none, unreachable;
export Path, WindowsPath, PosixPath, GenericPath;
export option, some, none, unreachable;
export extensions;
// The following exports are the extension impls for numeric types
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 file_reader(path: ~str) -> result<Reader, ~str> {
let f = os::as_c_charp(path, |pathbuf| {
os::as_c_charp(~"r", |modebuf|
fn file_reader(path: &Path) -> result<Reader, ~str> {
let f = os::as_c_charp(path.to_str(), |pathbuf| {
os::as_c_charp("r", |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_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> {
#[cfg(windows)]
@ -430,12 +431,13 @@ fn mk_file_writer(path: ~str, flags: ~[FileFlag])
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,
(S_IRUSR | S_IWUSR) 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 {
result::ok(fd_writer(fd, true))
}
@ -614,19 +616,20 @@ impl<T: Writer> T : WriterUtil {
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))
}
// FIXME: fileflags // #2004
fn buffered_file_writer(path: ~str) -> result<Writer, ~str> {
let f = do os::as_c_charp(path) |pathbuf| {
do os::as_c_charp(~"w") |modebuf| {
fn buffered_file_writer(path: &Path) -> result<Writer, ~str> {
let f = do os::as_c_charp(path.to_str()) |pathbuf| {
do os::as_c_charp("w") |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)) }
}
@ -709,19 +712,19 @@ fn seek_in_buf(offset: int, pos: uint, len: uint, whence: SeekStyle) ->
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| {
if str::is_utf8(bytes) {
result::ok(str::from_bytes(bytes))
} 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
// 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::ok(rdr.read_whole_stream())
})
@ -810,7 +813,7 @@ mod tests {
#[test]
fn test_simple() {
let tmpfile: ~str = ~"tmp/lib-io-test-simple.tmp";
let tmpfile = &Path("tmp/lib-io-test-simple.tmp");
log(debug, tmpfile);
let frood: ~str =
~"A hoopy frood who really knows where his towel is.";
@ -881,7 +884,7 @@ mod tests {
#[test]
fn file_reader_not_exist() {
match io::file_reader(~"not a file") {
match io::file_reader(&Path("not a file")) {
result::err(e) => {
assert e == ~"error opening not a file";
}
@ -891,9 +894,9 @@ mod tests {
#[test]
fn file_writer_bad_name() {
match io::file_writer(~"?/?", ~[]) {
match io::file_writer(&Path("?/?"), ~[]) {
result::err(e) => {
assert str::starts_with(e, ~"error opening ?/?");
assert str::starts_with(e, "error opening");
}
result::ok(_) => fail
}
@ -901,9 +904,9 @@ mod tests {
#[test]
fn buffered_file_writer_bad_name() {
match io::buffered_file_writer(~"?/?") {
match io::buffered_file_writer(&Path("?/?")) {
result::err(e) => {
assert e == ~"error opening ?/?";
assert str::starts_with(e, "error opening");
}
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.
*
@ -16,16 +20,12 @@
* 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,
mode_t, pid_t, FILE};
import libc::{close, fclose};
import option::{some, none};
import getcwd = rustrt::rust_getcwd;
import consts::*;
import task::TaskBuilder;
@ -56,7 +56,11 @@ extern mod rustrt {
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))
}
@ -106,7 +110,7 @@ mod win32 {
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);
// Null terminate before passing on.
t += ~[0u16];
@ -114,11 +118,11 @@ mod win32 {
}
}
fn getenv(+n: ~str) -> option<~str> {
fn getenv(n: &str) -> option<~str> {
global_env::getenv(n)
}
fn setenv(+n: ~str, +v: ~str) {
fn setenv(n: &str, v: &str) {
global_env::setenv(n, v)
}
@ -143,17 +147,20 @@ mod global_env {
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 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)
}
fn setenv(+n: ~str, +v: ~str) {
fn setenv(n: &str, v: &str) {
let env_ch = get_global_env_chan();
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)
}
@ -212,7 +219,7 @@ mod global_env {
}
#[cfg(unix)]
fn getenv(+n: ~str) -> option<~str> {
fn getenv(n: &str) -> option<~str> {
unsafe {
let s = str::as_c_str(n, libc::getenv);
return if unsafe::reinterpret_cast(s) == 0 {
@ -225,7 +232,7 @@ mod global_env {
}
#[cfg(windows)]
fn getenv(+n: ~str) -> option<~str> {
fn getenv(n: &str) -> option<~str> {
import libc::types::os::arch::extra::*;
import libc::funcs::extra::kernel32::*;
import win32::*;
@ -238,7 +245,7 @@ mod global_env {
#[cfg(unix)]
fn setenv(+n: ~str, +v: ~str) {
fn setenv(n: &str, v: &str) {
// FIXME: remove this when export globs work properly. #1238
import libc::funcs::posix01::unistd::setenv;
@ -251,7 +258,7 @@ mod global_env {
#[cfg(windows)]
fn setenv(+n: ~str, +v: ~str) {
fn setenv(n: &str, v: &str) {
// FIXME: remove imports when export globs work properly. #1238
import libc::funcs::extra::kernel32::*;
import win32::*;
@ -266,7 +273,7 @@ mod global_env {
}
fn fdopen(fd: c_int) -> *FILE {
return do as_c_charp(~"r") |modebuf| {
return do as_c_charp("r") |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 {
return pre() + base + dll_suffix();
fn dll_filename(base: &str) -> ~str {
return pre() + str::from_slice(base) + dll_suffix();
#[cfg(unix)]
fn pre() -> ~str { ~"lib" }
@ -379,7 +386,7 @@ fn dll_filename(+base: ~str) -> ~str {
fn self_exe_path() -> option<Path> {
#[cfg(target_os = "freebsd")]
fn load_self() -> option<Path> {
fn load_self() -> option<~str> {
unsafe {
import libc::funcs::bsd44::*;
import libc::consts::os::extra::*;
@ -395,17 +402,17 @@ fn self_exe_path() -> option<Path> {
}
#[cfg(target_os = "linux")]
fn load_self() -> option<Path> {
fn load_self() -> option<~str> {
import libc::funcs::posix01::unistd::readlink;
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)
}
}
}
#[cfg(target_os = "macos")]
fn load_self() -> option<Path> {
fn load_self() -> option<~str> {
// FIXME: remove imports when export globs work properly. #1238
import libc::funcs::extra::*;
do fill_charp_buf() |buf, sz| {
@ -415,7 +422,7 @@ fn self_exe_path() -> option<Path> {
}
#[cfg(windows)]
fn load_self() -> option<Path> {
fn load_self() -> option<~str> {
// FIXME: remove imports when export globs work properly. #1238
import libc::types::os::arch::extra::*;
import libc::funcs::extra::kernel32::*;
@ -426,7 +433,7 @@ fn self_exe_path() -> option<Path> {
}
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> {
return match getenv(~"HOME") {
some(p) => if !str::is_empty(p) {
some(p)
some(Path(p))
} else {
secondary()
},
@ -463,7 +470,7 @@ fn homedir() -> option<Path> {
fn secondary() -> option<Path> {
do option::chain(getenv(~"USERPROFILE")) |p| {
if !str::is_empty(p) {
some(p)
some(Path(p))
} else {
none
}
@ -484,13 +491,13 @@ fn homedir() -> option<Path> {
fn tmpdir() -> Path {
return lookup();
fn getenv_nonempty(+v: Path) -> option<Path> {
fn getenv_nonempty(v: &str) -> option<Path> {
match getenv(v) {
some(x) =>
if str::is_empty(x) {
none
} else {
some(x)
some(Path(x))
},
_ => none
}
@ -498,28 +505,29 @@ fn tmpdir() -> Path {
#[cfg(unix)]
fn lookup() -> Path {
option::get_default(getenv_nonempty(~"TMPDIR"), ~"/tmp")
option::get_default(getenv_nonempty("TMPDIR"),
Path("/tmp"))
}
#[cfg(windows)]
fn lookup() -> Path {
option::get_default(
option::or(getenv_nonempty(~"TMP"),
option::or(getenv_nonempty(~"TEMP"),
option::or(getenv_nonempty(~"USERPROFILE"),
getenv_nonempty(~"WINDIR")))),
~"C:\\Windows")
option::or(getenv_nonempty("TMP"),
option::or(getenv_nonempty("TEMP"),
option::or(getenv_nonempty("USERPROFILE"),
getenv_nonempty("WINDIR")))),
Path("C:\\Windows"))
}
}
/// 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);
fn walk_dir_(+p: Path, f: fn(Path) -> bool) -> bool {
fn walk_dir_(p: &Path, f: fn((&Path)) -> bool) -> bool {
let mut keepgoing = true;
do list_dir(p).each |q| {
let path = path::connect(p, q);
let path = &p.push(q);
if !f(path) {
keepgoing = false;
false
@ -541,15 +549,15 @@ fn walk_dir(+p: Path, f: fn(Path) -> bool) {
}
/// Indicates whether a path represents a directory
fn path_is_dir(+p: Path) -> bool {
do str::as_c_str(p) |buf| {
fn path_is_dir(p: &Path) -> bool {
do str::as_c_str(p.to_str()) |buf| {
rustrt::rust_path_is_dir(buf) != 0 as c_int
}
}
/// Indicates whether a path exists
fn path_exists(+p: Path) -> bool {
do str::as_c_str(p) |buf| {
fn path_exists(p: &Path) -> bool {
do str::as_c_str(p.to_str()) |buf| {
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
// querying; what it does depends on the process working directory, not just
// the input paths.
fn make_absolute(+p: Path) -> Path {
if path::path_is_absolute(p) {
p
fn make_absolute(p: &Path) -> Path {
if p.is_absolute {
copy *p
} else {
path::connect(getcwd(), p)
getcwd().push_many(p.components)
}
}
/// 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);
#[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
import libc::types::os::arch::extra::*;
import libc::funcs::extra::kernel32::*;
import win32::*;
// 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) })
!= (0 as BOOL)
}
}
#[cfg(unix)]
fn mkdir(+p: Path, mode: c_int) -> bool {
do as_c_charp(p) |c| {
fn mkdir(p: &Path, mode: c_int) -> bool {
do as_c_charp(p.to_str()) |c| {
libc::mkdir(c, mode as mode_t) == (0 as c_int)
}
}
}
/// Lists the contents of a directory
fn list_dir(+p: Path) -> ~[~str] {
fn list_dir(p: &Path) -> ~[~str] {
#[cfg(unix)]
fn star(+p: ~str) -> ~str { p }
fn star(p: &Path) -> Path { copy *p }
#[cfg(windows)]
fn star(+p: ~str) -> ~str {
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 + ~"*"
}
}
fn star(p: &Path) -> Path { p.push("*") }
do rustrt::rust_list_files(star(p)).filter |filename| {
do rustrt::rust_list_files(star(p).to_str()).filter |filename| {
filename != ~"." && filename != ~".."
}
}
@ -627,90 +627,84 @@ fn list_dir(+p: Path) -> ~[~str] {
*
* This version prepends each entry with the directory.
*/
fn list_dir_path(+p: Path) -> ~[~str] {
let mut p = p;
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)
fn list_dir_path(p: &Path) -> ~[~Path] {
os::list_dir(p).map(|f| ~p.push(f))
}
/// Removes a directory at the specified path
fn remove_dir(+p: Path) -> bool {
fn remove_dir(p: &Path) -> bool {
return rmdir(p);
#[cfg(windows)]
fn rmdir(+p: Path) -> bool {
fn rmdir(p: &Path) -> bool {
// FIXME: remove imports when export globs work properly. #1238
import libc::funcs::extra::kernel32::*;
import libc::types::os::arch::extra::*;
import win32::*;
return do as_utf16_p(p) |buf| {
return do as_utf16_p(p.to_str()) |buf| {
RemoveDirectoryW(buf) != (0 as BOOL)
};
}
#[cfg(unix)]
fn rmdir(+p: Path) -> bool {
return do as_c_charp(p) |buf| {
fn rmdir(p: &Path) -> bool {
return do as_c_charp(p.to_str()) |buf| {
libc::rmdir(buf) == (0 as c_int)
};
}
}
fn change_dir(+p: Path) -> bool {
fn change_dir(p: &Path) -> bool {
return chdir(p);
#[cfg(windows)]
fn chdir(+p: Path) -> bool {
fn chdir(p: &Path) -> bool {
// FIXME: remove imports when export globs work properly. #1238
import libc::funcs::extra::kernel32::*;
import libc::types::os::arch::extra::*;
import win32::*;
return do as_utf16_p(p) |buf| {
return do as_utf16_p(p.to_str()) |buf| {
SetCurrentDirectoryW(buf) != (0 as BOOL)
};
}
#[cfg(unix)]
fn chdir(+p: Path) -> bool {
return do as_c_charp(p) |buf| {
fn chdir(p: &Path) -> bool {
return do as_c_charp(p.to_str()) |buf| {
libc::chdir(buf) == (0 as c_int)
};
}
}
/// 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);
#[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
import libc::funcs::extra::kernel32::*;
import libc::types::os::arch::extra::*;
import win32::*;
return do as_utf16_p(from) |fromp| {
do as_utf16_p(to) |top| {
return do as_utf16_p(from.to_str()) |fromp| {
do as_utf16_p(to.to_str()) |top| {
CopyFileW(fromp, top, (0 as BOOL)) != (0 as BOOL)
}
}
}
#[cfg(unix)]
fn do_copy_file(+from: Path, +to: Path) -> bool {
let istream = do as_c_charp(from) |fromp| {
do as_c_charp(~"rb") |modebuf| {
fn do_copy_file(from: &Path, to: &Path) -> bool {
let istream = do as_c_charp(from.to_str()) |fromp| {
do as_c_charp("rb") |modebuf| {
libc::fopen(fromp, modebuf)
}
};
if istream as uint == 0u {
return false;
}
let ostream = do as_c_charp(to) |top| {
do as_c_charp(~"w+b") |modebuf| {
let ostream = do as_c_charp(to.to_str()) |top| {
do as_c_charp("w+b") |modebuf| {
libc::fopen(top, modebuf)
}
};
@ -746,24 +740,24 @@ fn copy_file(+from: Path, +to: Path) -> bool {
}
/// Deletes an existing file
fn remove_file(+p: Path) -> bool {
fn remove_file(p: &Path) -> bool {
return unlink(p);
#[cfg(windows)]
fn unlink(+p: Path) -> bool {
fn unlink(p: &Path) -> bool {
// FIXME (similar to Issue #2006): remove imports when export globs
// work properly.
import libc::funcs::extra::kernel32::*;
import libc::types::os::arch::extra::*;
import win32::*;
return do as_utf16_p(p) |buf| {
return do as_utf16_p(p.to_str()) |buf| {
DeleteFileW(buf) != (0 as BOOL)
};
}
#[cfg(unix)]
fn unlink(+p: Path) -> bool {
return do as_c_charp(p) |buf| {
fn unlink(p: &Path) -> bool {
return do as_c_charp(p.to_str()) |buf| {
libc::unlink(buf) == (0 as c_int)
};
}
@ -887,11 +881,7 @@ mod tests {
log(debug, path);
// Hard to test this function
if os::sysname() != ~"win32" {
assert str::starts_with(path, path::path_sep());
} else {
assert path[1] == ':' as u8;
}
assert path.is_absolute;
}
#[test]
@ -926,10 +916,10 @@ mod tests {
fn test() {
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(~"/usr/bin"));
log(debug, make_absolute(&Path("test-path")));
log(debug, make_absolute(&Path("/usr/bin")));
}
#[test]
@ -938,7 +928,7 @@ mod tests {
let oldhome = getenv(~"HOME");
setenv(~"HOME", ~"/home/MountainView");
assert os::homedir() == some(~"/home/MountainView");
assert os::homedir() == some(Path("/home/MountainView"));
setenv(~"HOME", ~"");
assert os::homedir() == none;
@ -959,16 +949,16 @@ mod tests {
assert os::homedir() == none;
setenv(~"HOME", ~"/home/MountainView");
assert os::homedir() == some(~"/home/MountainView");
assert os::homedir() == some(Path("/home/MountainView"));
setenv(~"HOME", ~"");
setenv(~"USERPROFILE", ~"/home/MountainView");
assert os::homedir() == some(~"/home/MountainView");
assert os::homedir() == some(Path("/home/MountainView"));
setenv(~"HOME", ~"/home/MountainView");
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(olduserprofile,
@ -977,16 +967,18 @@ mod tests {
#[test]
fn tmpdir() {
assert !str::is_empty(os::tmpdir());
assert !str::is_empty(os::tmpdir().to_str());
}
// Issue #712
#[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]
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
assert (vec::len(dirs) > 0u);
@ -995,34 +987,34 @@ mod tests {
#[test]
fn path_is_dir() {
assert (os::path_is_dir(~"."));
assert (!os::path_is_dir(~"test/stdtest/fs.rs"));
assert (os::path_is_dir(&Path(".")));
assert (!os::path_is_dir(&Path("test/stdtest/fs.rs")));
}
#[test]
fn path_exists() {
assert (os::path_exists(~"."));
assert (!os::path_exists(~"test/nonexistent-bogus-path"));
assert (os::path_exists(&Path(".")));
assert (!os::path_exists(&Path("test/nonexistent-bogus-path")));
}
#[test]
fn copy_file_does_not_exist() {
assert !os::copy_file(~"test/nonexistent-bogus-path",
~"test/other-bogus-path");
assert !os::path_exists(~"test/other-bogus-path");
assert !os::copy_file(&Path("test/nonexistent-bogus-path"),
&Path("test/other-bogus-path"));
assert !os::path_exists(&Path("test/other-bogus-path"));
}
#[test]
fn copy_file_ok() {
let tempdir = getcwd(); // would like to use $TMPDIR,
// doesn't seem to work on Linux
assert (str::len(tempdir) > 0u);
let in = tempdir + path::path_sep() + ~"in.txt";
let out = tempdir + path::path_sep() + ~"out.txt";
assert (str::len(tempdir.to_str()) > 0u);
let in = tempdir.push("in.txt");
let out = tempdir.push("out.txt");
/* Write the temp input file */
let ostream = do as_c_charp(in) |fromp| {
do as_c_charp(~"w+b") |modebuf| {
let ostream = do as_c_charp(in.to_str()) |fromp| {
do as_c_charp("w+b") |modebuf| {
libc::fopen(fromp, modebuf)
}
};
@ -1034,14 +1026,14 @@ mod tests {
(str::len(s) + 1u) as size_t, ostream)
== buf.len() as size_t)};
assert (libc::fclose(ostream) == (0u as c_int));
let rs = os::copy_file(in, out);
if (!os::path_exists(in)) {
fail (fmt!("%s doesn't exist", in));
let rs = os::copy_file(&in, &out);
if (!os::path_exists(&in)) {
fail (fmt!("%s doesn't exist", in.to_str()));
}
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 (remove_file(in));
assert (remove_file(out));
assert (remove_file(&in));
assert (remove_file(&out));
}
}

View File

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

View File

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

View File

@ -141,7 +141,7 @@ fn run_tests_console(opts: test_opts,
}
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]) {
result::ok(w) => some(w),
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 file = expr_to_str(cx, args[0], ~"#include_str requires a string");
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);
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 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 {
result::ok(_) => { /* Continue. */ }
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");
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) => {
let u8_exprs = vec::map(src, |char: u8| {
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
if !path::path_is_absolute(arg) {
let cu = codemap::span_to_filename(sp, cx.codemap());
let dir = path::dirname(cu);
return path::connect(dir, arg);
if !arg.is_absolute {
let cu = Path(codemap::span_to_filename(sp, cx.codemap()));
cu.dir_path().push_many(arg.components)
} 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};
}
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 {
if str::ends_with(input, ~".rc") {
if input.filetype() == some(~"rc") {
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)
} else {
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 {
let (p, rdr) = new_parser_etc_from_file(sess, cfg, input,
parser::CRATE_FILE);
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 { inner: crate_attrs, next: first_cdir_attr } = leading_attrs;
let cdirs = p.parse_crate_directives(token::EOF, first_cdir_attr);
sess.chpos = rdr.chpos;
sess.byte_pos = sess.byte_pos + rdr.pos;
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(
cx, cdirs, prefix, option::some(companionmod));
cx, cdirs, &prefix, &companionmod);
let mut hi = p.span.hi;
p.expect(token::EOF);
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});
}
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 {
let (p, rdr) = new_parser_etc_from_file(sess, cfg, input,
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,
+path: ~str, ftype: parser::file_type) ->
path: &Path, ftype: parser::file_type) ->
(parser, string_reader) {
let res = io::read_whole_file_str(path);
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)
}
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);
let srdr = lexer::new_string_reader(sess.span_diagnostic, filemap,
sess.interner);
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 {
let (p, _) = new_parser_etc_from_file(sess, cfg, path, ftype);
return p;

View File

@ -9,7 +9,7 @@ type ctx =
fn eval_crate_directives(cx: ctx,
cdirs: ~[@ast::crate_directive],
prefix: ~str,
prefix: &Path,
&view_items: ~[@ast::view_item],
&items: ~[@ast::item]) {
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],
prefix: ~str, suffix: option<~str>)
prefix: &Path, suffix: &option<Path>)
-> (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)
= parse_companion_mod(cx, prefix, suffix);
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
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]) {
fn companion_file(+prefix: ~str, suffix: option<~str>) -> ~str {
return match suffix {
option::some(s) => path::connect(prefix, s),
option::none => prefix
} + ~".rs";
fn companion_file(prefix: &Path, suffix: &option<Path>) -> Path {
return match *suffix {
option::some(s) => prefix.push_many(s.components),
option::none => copy *prefix
}.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
// up to writing it just now
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);
debug!("looking for companion mod %s", modpath);
let modpath = &companion_file(prefix, suffix);
if file_exists(modpath) {
debug!("found companion mod");
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],
&items: ~[@ast::item]) {
match cdir.node {
ast::cdir_src_mod(id, attrs) => {
let file_path = cdir_path_opt((cx.sess.interner.get(id) + ~".rs"),
attrs);
let full_path =
if path::path_is_absolute(file_path) {
file_path
} else { prefix + path::path_sep() + file_path };
let file_path = Path(cdir_path_opt(
cx.sess.interner.get(id) + ~".rs", attrs));
let full_path = if file_path.is_absolute {
copy file_path
} else {
prefix.push_many(file_path.components)
};
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 mod_attrs = vec::append(attrs, inner_attrs.inner);
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);
}
ast::cdir_dir_mod(id, cdirs, attrs) => {
let path = cdir_path_opt(*cx.sess.interner.get(id), attrs);
let full_path =
if path::path_is_absolute(path) {
path
} else { prefix + path::path_sep() + path };
let path = Path(cdir_path_opt(*cx.sess.interner.get(id), attrs));
let full_path = if path.is_absolute {
copy path
} else {
prefix.push_many(path.components)
};
let (m0, a0) = eval_crate_directives_to_mod(
cx, cdirs, full_path, none);
cx, cdirs, &full_path, &none);
let i =
@{ident: /* FIXME (#2543) */ copy id,
attrs: vec::append(attrs, a0),

View File

@ -57,18 +57,7 @@ mod write {
return false;
}
// Decides what to call an intermediate file, given the name of the output
// 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) {
fn run_passes(sess: session, llmod: ModuleRef, output: &Path) {
let opts = sess.opts;
if sess.time_llvm_passes() { llvm::LLVMRustEnableTimePasses(); }
let mut pm = mk_pass_manager();
@ -85,15 +74,15 @@ mod write {
match opts.output_type {
output_type_bitcode => {
if opts.optimize != session::No {
let filename = mk_intermediate_name(output, ~"no-opt.bc");
str::as_c_str(filename, |buf| {
let filename = output.with_filetype("no-opt.bc");
str::as_c_str(filename.to_str(), |buf| {
llvm::LLVMWriteBitcodeToFile(llmod, buf)
});
}
}
_ => {
let filename = mk_intermediate_name(output, ~"bc");
str::as_c_str(filename, |buf| {
let filename = output.with_filetype("bc");
str::as_c_str(filename.to_str(), |buf| {
llvm::LLVMWriteBitcodeToFile(llmod, buf)
});
}
@ -163,9 +152,9 @@ mod write {
if opts.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);
str::as_c_str(filename, |buf| {
str::as_c_str(filename.to_str(), |buf| {
llvm::LLVMWriteBitcodeToFile(llmod, buf)
});
pm = mk_pass_manager();
@ -175,7 +164,7 @@ mod write {
let _: () = str::as_c_str(
sess.targ_cfg.target_strs.target_triple,
|buf_t| {
str::as_c_str(output, |buf_o| {
str::as_c_str(output.to_str(), |buf_o| {
WriteOutputFile(
sess,
pm.llpm,
@ -197,7 +186,7 @@ mod write {
let _: () = str::as_c_str(
sess.targ_cfg.target_strs.target_triple,
|buf_t| {
str::as_c_str(output, |buf_o| {
str::as_c_str(output.to_str(), |buf_o| {
WriteOutputFile(
sess,
pm.llpm,
@ -217,7 +206,7 @@ mod write {
let _: () = str::as_c_str(
sess.targ_cfg.target_strs.target_triple,
|buf_t| {
str::as_c_str(output, |buf_o| {
str::as_c_str(output.to_str(), |buf_o| {
WriteOutputFile(
sess,
pm.llpm,
@ -239,13 +228,13 @@ mod write {
if opts.output_type == output_type_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)});
} else {
// If only a bitcode file is asked for by using the '--emit-llvm'
// flag, then output it here
llvm::LLVMRunPassManager(pm.llpm, llmod);
str::as_c_str(output,
str::as_c_str(output.to_str(),
|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 {
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,
output: ~str, metas: provided_metas) -> ~str {
output: &Path, metas: provided_metas) -> ~str {
return match metas.name {
some(v) => v,
none => {
let name =
{
let mut os =
str::split_char(path::basename(output), '.');
if (vec::len(os) < 2u) {
sess.fatal(fmt!("output file name `%s` doesn't\
appear to have an extension", output));
}
vec::pop(os);
str::connect(os, ~".")
};
let name = match output.filestem() {
none => sess.fatal(fmt!("output file name `%s` doesn't\
appear to have a stem",
output.to_str())),
some(s) => s
};
warn_missing(sess, ~"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
// cc to link the object file with some libs
fn link_binary(sess: session,
obj_filename: ~str,
out_filename: ~str,
obj_filename: &Path,
out_filename: &Path,
lm: link_meta) {
// Converts a library file name into a cc -l argument
fn unlib(config: @session::config, filename: ~str) -> ~str unsafe {
let rmlib = fn@(filename: ~str) -> ~str {
let found = str::find_str(filename, ~"lib");
if config.os == session::os_macos ||
(config.os == session::os_linux ||
config.os == session::os_freebsd) &&
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, ~".");
// Converts a library file-stem into a cc -l argument
fn unlib(config: @session::config, stem: ~str) -> ~str {
if stem.starts_with("lib") &&
config.os != session::os_win32 {
stem.slice(3, stem.len())
} else {
stem
}
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 {
@ -585,17 +555,19 @@ fn link_binary(sess: session,
lm.name, lm.extras_hash, lm.vers));
debug!("link_meta.name: %s", lm.name);
debug!("long_libname: %s", long_libname);
debug!("out_filename: %s", out_filename);
debug!("dirname(out_filename): %s", path::dirname(out_filename));
debug!("out_filename: %s", out_filename.to_str());
debug!("dirname(out_filename): %s", out_filename.dir_path().to_str());
path::connect(path::dirname(out_filename), long_libname)
} else { out_filename };
out_filename.dir_path().push(long_libname)
} 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 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.
// 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 =
vec::append(~[stage], sess.targ_cfg.target_strs.cc_args);
vec::push(cc_args, ~"-o");
vec::push(cc_args, output);
vec::push(cc_args, obj_filename);
vec::push(cc_args, output.to_str());
vec::push(cc_args, obj_filename.to_str());
let mut lib_cmd;
let os = sess.targ_cfg.os;
if os == session::os_macos {
lib_cmd = ~"-dynamiclib";
} else { lib_cmd = ~"-shared"; }
} else {
lib_cmd = ~"-shared";
}
// # Crate linking
let cstore = sess.cstore;
for cstore::get_used_crate_files(cstore).each |cratepath| {
if str::ends_with(cratepath, ~".rlib") {
vec::push(cc_args, cratepath);
if cratepath.filetype() == some(~"rlib") {
vec::push(cc_args, cratepath.to_str());
again;
}
let cratepath = cratepath;
let dir = path::dirname(cratepath);
let dir = cratepath.dirname();
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);
}
@ -645,7 +618,7 @@ fn link_binary(sess: session,
// forces to make sure that library can be found at runtime.
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
let used_libs = cstore::get_used_libraries(cstore);
@ -658,7 +631,7 @@ fn link_binary(sess: session,
// be rpathed
if sess.targ_cfg.os == session::os_macos {
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
// 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, ~" "));
// We run 'cc' here
@ -717,14 +690,14 @@ fn link_binary(sess: session,
// Clean up on Darwin
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
if !sess.opts.save_temps {
if ! os::remove_file(obj_filename) {
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;
// No rpath on windows
@ -23,7 +23,6 @@ fn get_rpath_flags(sess: session::session, out_filename: ~str) -> ~[~str] {
debug!("preparing the RPATH!");
let cwd = os::getcwd();
let sysroot = sess.filesearch.sysroot();
let output = out_filename;
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 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)
}
fn get_sysroot_absolute_rt_lib(sess: session::session) -> path::Path {
let mut path = vec::append(~[sess.filesearch.sysroot()],
filesearch::relative_target_lib_path(
sess.opts.target_triple));
vec::push(path, os::dll_filename(~"rustrt"));
path::connect_many(path)
fn get_sysroot_absolute_rt_lib(sess: session::session) -> Path {
let r = filesearch::relative_target_lib_path(sess.opts.target_triple);
sess.filesearch.sysroot().push_rel(&r).push(os::dll_filename("rustrt"))
}
fn rpaths_to_flags(rpaths: ~[~str]) -> ~[~str] {
vec::map(rpaths, |rpath| fmt!("-Wl,-rpath,%s",rpath) )
fn rpaths_to_flags(rpaths: &[Path]) -> ~[~str] {
vec::map(rpaths, |rpath| fmt!("-Wl,-rpath,%s",rpath.to_str()))
}
fn get_rpaths(os: session::os, cwd: path::Path, sysroot: path::Path,
output: path::Path, libs: ~[path::Path],
target_triple: ~str) -> ~[~str] {
debug!("cwd: %s", cwd);
debug!("sysroot: %s", sysroot);
debug!("output: %s", output);
fn get_rpaths(os: session::os,
sysroot: &Path,
output: &Path,
libs: &[Path],
target_triple: &str) -> ~[Path] {
debug!("sysroot: %s", sysroot.to_str());
debug!("output: %s", output.to_str());
debug!("libs:");
for libs.each |libpath| {
debug!(" %s", libpath);
debug!(" %s", libpath.to_str());
}
debug!("target_triple: %s", target_triple);
// Use relative paths to the libraries. Binaries can be moved
// as long as they maintain the relative relationship to the
// 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
// 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.
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);
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,
cwd: path::Path,
output: path::Path,
libs: ~[path::Path]) -> ~[~str] {
output: &Path,
libs: &[Path]) -> ~[Path] {
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,
cwd: path::Path,
output: path::Path,
&&lib: path::Path) -> ~str {
output: &Path,
lib: &Path) -> Path {
assert not_win32(os);
// Mac doesn't appear to support $ORIGIN
let prefix = match os {
session::os_linux => ~"$ORIGIN" + path::path_sep(),
session::os_freebsd => ~"$ORIGIN" + path::path_sep(),
session::os_macos => ~"@executable_path" + path::path_sep(),
session::os_linux | session::os_freebsd => "$ORIGIN",
session::os_macos => "@executable_path",
session::os_win32 => core::unreachable()
};
prefix + get_relative_to(
get_absolute(cwd, output),
get_absolute(cwd, lib))
Path(prefix).push_rel(&get_relative_to(&os::make_absolute(output),
&os::make_absolute(lib)))
}
// Find the relative path from one file to another
fn get_relative_to(abs1: path::Path, abs2: path::Path) -> path::Path {
assert path::path_is_absolute(abs1);
assert path::path_is_absolute(abs2);
fn get_relative_to(abs1: &Path, abs2: &Path) -> Path {
assert abs1.is_absolute;
assert abs2.is_absolute;
debug!("finding relative path from %s to %s",
abs1, abs2);
let normal1 = path::normalize(abs1);
let normal2 = path::normalize(abs2);
let split1 = path::split(normal1);
let split2 = path::split(normal2);
abs1.to_str(), abs2.to_str());
let split1 = abs1.components;
let split2 = abs2.components;
let len1 = vec::len(split1);
let len2 = vec::len(split2);
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));
if vec::is_not_empty(path) {
return path::connect_many(path);
return Path("").push_many(path);
} else {
return ~".";
return Path(".");
}
}
fn get_absolute_rpaths(cwd: path::Path, libs: ~[path::Path]) -> ~[~str] {
vec::map(libs, |a| get_absolute_rpath(cwd, a) )
fn get_absolute_rpaths(libs: &[Path]) -> ~[Path] {
vec::map(libs, |a| get_absolute_rpath(&a) )
}
fn get_absolute_rpath(cwd: path::Path, &&lib: path::Path) -> ~str {
path::dirname(get_absolute(cwd, lib))
fn get_absolute_rpath(lib: &Path) -> Path {
os::make_absolute(lib).dir_path()
}
fn get_absolute(cwd: path::Path, lib: path::Path) -> path::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 {
fn get_install_prefix_rpath(target_triple: &str) -> Path {
let install_prefix = env!("CFG_PREFIX");
if install_prefix == ~"" {
fail ~"rustc compiled without CFG_PREFIX environment variable";
}
let path = vec::append(
~[install_prefix],
filesearch::relative_target_lib_path(target_triple));
get_absolute(cwd, path::connect_many(path))
let tlib = filesearch::relative_target_lib_path(target_triple);
os::make_absolute(&Path(install_prefix).push_rel(&tlib))
}
fn minimize_rpaths(rpaths: ~[~str]) -> ~[~str] {
fn minimize_rpaths(rpaths: &[Path]) -> ~[Path] {
let set = map::str_hash::<()>();
let mut minimized = ~[];
for rpaths.each |rpath| {
if !set.contains_key(rpath) {
let s = rpath.to_str();
if !set.contains_key(s) {
vec::push(minimized, rpath);
set.insert(rpath, ());
set.insert(s, ());
}
}
return minimized;
@ -199,116 +181,112 @@ fn minimize_rpaths(rpaths: ~[~str]) -> ~[~str] {
mod test {
#[test]
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"];
}
#[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]
fn test_prefix_rpath() {
let res = get_install_prefix_rpath(~"/usr/lib", ~"triple");
let d = path::connect(env!("CFG_PREFIX"), ~"/lib/rustc/triple/lib");
assert str::ends_with(res, d);
let res = get_install_prefix_rpath("triple");
let d = Path(env!("CFG_PREFIX"))
.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]
fn test_prefix_rpath_abs() {
let res = get_install_prefix_rpath(~"/usr/lib", ~"triple");
assert path::path_is_absolute(res);
let res = get_install_prefix_rpath("triple");
assert res.is_absolute;
}
#[test]
fn test_minimize1() {
let res = minimize_rpaths(~[~"rpath1", ~"rpath2", ~"rpath1"]);
assert res == ~[~"rpath1", ~"rpath2"];
let res = minimize_rpaths([Path("rpath1"),
Path("rpath2"),
Path("rpath1")]);
assert res == ~[Path("rpath1"), Path("rpath2")];
}
#[test]
fn test_minimize2() {
let res = minimize_rpaths(~[~"1a", ~"2", ~"2", ~"1a", ~"4a",
~"1a", ~"2", ~"3", ~"4a", ~"3"]);
assert res == ~[~"1a", ~"2", ~"4a", ~"3"];
let res = minimize_rpaths(~[Path("1a"), Path("2"), Path("2"),
Path("1a"), Path("4a"),Path("1a"),
Path("2"), Path("3"), Path("4a"),
Path("3")]);
assert res == ~[Path("1a"), Path("2"), Path("4a"), Path("3")];
}
#[test]
fn test_relative_to1() {
let p1 = ~"/usr/bin/rustc";
let p2 = ~"/usr/lib/mylib";
let res = get_relative_to(p1, p2);
assert res == ~"../lib";
let p1 = Path("/usr/bin/rustc");
let p2 = Path("/usr/lib/mylib");
let res = get_relative_to(&p1, &p2);
assert res == Path("../lib");
}
#[test]
fn test_relative_to2() {
let p1 = ~"/usr/bin/rustc";
let p2 = ~"/usr/bin/../lib/mylib";
let res = get_relative_to(p1, p2);
assert res == ~"../lib";
let p1 = Path("/usr/bin/rustc");
let p2 = Path("/usr/bin/../lib/mylib");
let res = get_relative_to(&p1, &p2);
assert res == Path("../lib");
}
#[test]
fn test_relative_to3() {
let p1 = ~"/usr/bin/whatever/rustc";
let p2 = ~"/usr/lib/whatever/mylib";
let res = get_relative_to(p1, p2);
assert res == ~"../../lib/whatever";
let p1 = Path("/usr/bin/whatever/rustc");
let p2 = Path("/usr/lib/whatever/mylib");
let res = get_relative_to(&p1, &p2);
assert res == Path("../../lib/whatever");
}
#[test]
fn test_relative_to4() {
let p1 = ~"/usr/bin/whatever/../rustc";
let p2 = ~"/usr/lib/whatever/mylib";
let res = get_relative_to(p1, p2);
assert res == ~"../lib/whatever";
let p1 = Path("/usr/bin/whatever/../rustc");
let p2 = Path("/usr/lib/whatever/mylib");
let res = get_relative_to(&p1, &p2);
assert res == Path("../lib/whatever");
}
#[test]
fn test_relative_to5() {
let p1 = ~"/usr/bin/whatever/../rustc";
let p2 = ~"/usr/lib/whatever/../mylib";
let res = get_relative_to(p1, p2);
assert res == ~"../lib";
let p1 = Path("/usr/bin/whatever/../rustc");
let p2 = Path("/usr/lib/whatever/../mylib");
let res = get_relative_to(&p1, &p2);
assert res == Path("../lib");
}
#[test]
fn test_relative_to6() {
let p1 = ~"/1";
let p2 = ~"/2/3";
let res = get_relative_to(p1, p2);
assert res == ~"2";
let p1 = Path("/1");
let p2 = Path("/2/3");
let res = get_relative_to(&p1, &p2);
assert res == Path("2");
}
#[test]
fn test_relative_to7() {
let p1 = ~"/1/2";
let p2 = ~"/3";
let res = get_relative_to(p1, p2);
assert res == ~"..";
let p1 = Path("/1/2");
let p2 = Path("/3");
let res = get_relative_to(&p1, &p2);
assert res == Path("..");
}
#[test]
fn test_relative_to8() {
let p1 = ~"/home/brian/Dev/rust/build/"
+ ~"stage2/lib/rustc/i686-unknown-linux-gnu/lib/librustc.so";
let p2 = ~"/home/brian/Dev/rust/build/stage2/bin/.."
+ ~"/lib/rustc/i686-unknown-linux-gnu/lib/libstd.so";
let res = get_relative_to(p1, p2);
assert res == ~".";
let p1 = Path("/home/brian/Dev/rust/build/").push_rel(
&Path("stage2/lib/rustc/i686-unknown-linux-gnu/lib/librustc.so"));
let p2 = Path("/home/brian/Dev/rust/build/stage2/bin/..").push_rel(
&Path("lib/rustc/i686-unknown-linux-gnu/lib/libstd.so"));
let res = get_relative_to(&p1, &p2);
debug!("test_relative_tu8: %s vs. %s",
res.to_str(),
Path(".").to_str());
assert res == Path(".");
}
#[test]
@ -316,8 +294,8 @@ mod test {
fn test_rpath_relative() {
let o = session::os_linux;
let res = get_rpath_relative_to_output(o,
~"/usr", ~"bin/rustc", ~"lib/libstd.so");
assert res == ~"$ORIGIN/../lib";
&Path("bin/rustc"), &Path("lib/libstd.so"));
assert res == Path("$ORIGIN/../lib");
}
#[test]
@ -325,8 +303,8 @@ mod test {
fn test_rpath_relative() {
let o = session::os_freebsd;
let res = get_rpath_relative_to_output(o,
~"/usr", ~"bin/rustc", ~"lib/libstd.so");
assert res == ~"$ORIGIN/../lib";
&Path("bin/rustc"), &Path("lib/libstd.so"));
assert res == Path("$ORIGIN/../lib");
}
#[test]
@ -334,14 +312,19 @@ mod test {
fn test_rpath_relative() {
// this is why refinements would be nice
let o = session::os_macos;
let res = get_rpath_relative_to_output(o, ~"/usr", ~"bin/rustc",
~"lib/libstd.so");
assert res == ~"@executable_path/../lib";
let res = get_rpath_relative_to_output(o,
&Path("bin/rustc"),
&Path("lib/libstd.so"));
assert res == Path("@executable_path/../lib");
}
#[test]
fn test_get_absolute_rpath() {
let res = get_absolute_rpath(~"/usr", ~"lib/libstd.so");
assert res == ~"/usr/lib";
let res = get_absolute_rpath(&Path("lib/libstd.so"));
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 {
match input {
file_input(ifile) => ifile,
file_input(ifile) => ifile.to_str(),
str_input(_) => anon_src()
}
}
@ -92,7 +92,7 @@ fn parse_cfgspecs(cfgspecs: ~[~str]) -> ast::crate_cfg {
enum input {
/// Load source from file
file_input(~str),
file_input(Path),
/// The string is the source
str_input(~str)
}
@ -101,7 +101,7 @@ fn parse_input(sess: session, cfg: ast::crate_cfg, input: input)
-> @ast::crate {
match input {
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) => {
// 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};
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));
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 =
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)}; }
time(time_passes, ~"linking", ||
link::link_binary(sess, outputs.obj_filename,
outputs.out_filename, link_meta));
link::link_binary(sess,
&outputs.obj_filename,
&outputs.out_filename, link_meta));
return {crate: crate, tcx: some(ty_cx)};
}
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 }
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 debuginfo = opt_present(matches, ~"g") || extra_debuginfo;
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 save_temps = getopts::opt_present(matches, ~"save-temps");
match output_type {
@ -514,7 +518,9 @@ fn build_session_options(matches: getopts::matches,
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 test = opt_present(matches, ~"test");
let sopts: @session::options =
@ -614,11 +620,11 @@ fn opts() -> ~[getopts::opt] {
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,
odir: option<~str>,
ofile: option<~str>,
odir: &option<Path>,
ofile: &option<Path>,
sess: session)
-> output_filenames {
let obj_path;
@ -639,37 +645,30 @@ fn build_output_filenames(input: input,
link::output_type_object | link::output_type_exe => ~"o"
};
match ofile {
match *ofile {
none => {
// "-" as input file will cause the parser to read from stdin so we
// have to make up a name
// We want to toss everything after the final '.'
let dirname = match odir {
let dirpath = match *odir {
some(d) => d,
none => match input {
str_input(_) => os::getcwd(),
file_input(ifile) => path::dirname(ifile)
file_input(ifile) => ifile.dir_path()
}
};
let base_filename = match input {
file_input(ifile) => {
let (path, _) = path::splitext(ifile);
path::basename(path)
}
let stem = match input {
file_input(ifile) => option::get(ifile.filestem()),
str_input(_) => ~"rust_out"
};
let base_path = path::connect(dirname, base_filename);
if sess.building_library {
let basename = path::basename(base_path);
let dylibname = os::dll_filename(basename);
out_path = path::connect(dirname, dylibname);
obj_path = path::connect(dirname, basename + ~"." + obj_suffix);
out_path = dirpath.push(os::dll_filename(stem));
obj_path = dirpath.push(stem).with_filetype(obj_suffix);
} else {
out_path = base_path;
obj_path = base_path + ~"." + obj_suffix;
out_path = dirpath.push(stem);
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 {
out_file
} else {
let (base, _) = path::splitext(out_file);
let modified = base + ~"." + obj_suffix;
modified
out_file.with_filetype(obj_suffix)
};
if sess.building_library {
@ -690,13 +687,13 @@ fn build_output_filenames(input: input,
// lib<basename>-<hash>-<version>.so no matter what.
}
if odir != none {
if *odir != none {
sess.warn(~"ignoring --out-dir flag due to -o flag.");
}
}
}
return @{out_filename: out_path,
obj_filename: obj_path};
obj_filename: obj_path};
}
fn early_error(emitter: diagnostic::emitter, msg: ~str) -> ! {
@ -704,7 +701,7 @@ fn early_error(emitter: diagnostic::emitter, msg: ~str) -> ! {
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(
sess.parse_sess.interner,
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());
str_input(src)
} else {
file_input(ifile)
file_input(Path(ifile))
}
}
_ => 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 sess = build_session(sopts, demitter);
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 = option::map(ofile, |o| Path(o));
let cfg = build_configuration(sess, binary, input);
let pretty =
option::map(getopts::opt_default(matches, ~"pretty",
@ -185,7 +187,7 @@ fn run_compiler(args: ~[~str], demitter: diagnostic::emitter) {
if ls {
match input {
file_input(ifile) => {
list_metadata(sess, ifile, io::stdout());
list_metadata(sess, &ifile, io::stdout());
}
str_input(_) => {
early_error(demitter, ~"can not list metadata for stdin");
@ -194,7 +196,7 @@ fn run_compiler(args: ~[~str], demitter: diagnostic::emitter) {
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)],
save_temps: bool,
output_type: back::link::output_type,
addl_lib_search_paths: ~[~str],
maybe_sysroot: option<~str>,
addl_lib_search_paths: ~[Path],
maybe_sysroot: option<Path>,
target_triple: ~str,
cfg: ast::crate_cfg,
test: bool,
@ -111,7 +111,7 @@ type session_ = {targ_cfg: @config,
span_diagnostic: diagnostic::span_handler,
filesearch: filesearch::filesearch,
mut building_library: bool,
working_dir: ~str,
working_dir: Path,
lint_settings: lint::lint_settings};
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 cfilename = cinfo.ident;
let cfilename = Path(cinfo.ident);
let cdata = cinfo.data;
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;
cstore::set_crate_data(cstore, cnum, cmeta);
cstore::add_used_crate_file(cstore, cfilename);
cstore::add_used_crate_file(cstore, &cfilename);
return cnum;
}
some(cnum) => {

View File

@ -56,7 +56,7 @@ type cstore_private =
@{metas: map::hashmap<ast::crate_num, crate_metadata>,
use_crate_map: use_crate_map,
mod_path_map: mod_path_map,
mut used_crate_files: ~[~str],
mut used_crate_files: ~[Path],
mut used_libraries: ~[~str],
mut used_link_args: ~[~str],
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);};
}
fn add_used_crate_file(cstore: cstore, lib: ~str) {
if !vec::contains(p(cstore).used_crate_files, lib) {
vec::push(p(cstore).used_crate_files, lib);
fn add_used_crate_file(cstore: cstore, lib: &Path) {
if !vec::contains(p(cstore).used_crate_files, copy *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;
}

View File

@ -14,12 +14,10 @@ export get_cargo_root;
export get_cargo_root_nearest;
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::basename(path) == file { option::some(path) }
fn pick_file(file: Path, path: &Path) -> option<Path> {
if path.file_path() == file { option::some(copy *path) }
else { option::none }
}
@ -27,11 +25,11 @@ trait filesearch {
fn sysroot() -> Path;
fn lib_search_paths() -> ~[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>,
target_triple: ~str,
target_triple: &str,
addl_lib_search_paths: ~[Path]) -> filesearch {
type filesearch_impl = {sysroot: 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;
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() {
result::ok(p) => vec::push(paths, p),
result::err(p) => ()
@ -54,33 +53,33 @@ fn mk_filesearch(maybe_sysroot: option<Path>,
paths
}
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 {
path::connect(self.get_target_lib_path(), file)
fn get_target_lib_file_path(file: &Path) -> Path {
self.get_target_lib_path().push_rel(file)
}
}
let sysroot = get_sysroot(maybe_sysroot);
debug!("using sysroot = %s", sysroot);
debug!("using sysroot = %s", sysroot.to_str());
{sysroot: sysroot,
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> {
let mut rslt = none;
for filesearch.lib_search_paths().each |lib_search_path| {
debug!("searching %s", lib_search_path);
for os::list_dir_path(lib_search_path).each |path| {
debug!("testing %s", path);
debug!("searching %s", lib_search_path.to_str());
for os::list_dir_path(&lib_search_path).each |path| {
debug!("testing %s", path.to_str());
let maybe_picked = pick(path);
if option::is_some(maybe_picked) {
debug!("picked %s", path);
debug!("picked %s", path.to_str());
rslt = maybe_picked;
break;
} else {
debug!("rejected %s", path);
debug!("rejected %s", path.to_str());
}
}
if option::is_some(rslt) { break; }
@ -88,21 +87,20 @@ fn search<T: copy>(filesearch: filesearch, pick: pick<T>) -> option<T> {
return rslt;
}
fn relative_target_lib_path(target_triple: ~str) -> ~[Path] {
~[libdir(), ~"rustc", target_triple, libdir()]
fn relative_target_lib_path(target_triple: &str) -> Path {
Path(libdir()).push_many([~"rustc",
str::from_slice(target_triple),
libdir()])
}
fn make_target_lib_path(sysroot: Path,
target_triple: ~str) -> Path {
let path = vec::append(~[sysroot],
relative_target_lib_path(target_triple));
let path = path::connect_many(path);
return path;
fn make_target_lib_path(sysroot: &Path,
target_triple: &str) -> Path {
sysroot.push_rel(&relative_target_lib_path(target_triple))
}
fn get_default_sysroot() -> 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"
}
}
@ -115,15 +113,14 @@ fn get_sysroot(maybe_sysroot: option<Path>) -> Path {
}
fn get_cargo_sysroot() -> result<Path, ~str> {
let path = ~[get_default_sysroot(), libdir(), ~"cargo"];
result::ok(path::connect_many(path))
result::ok(get_default_sysroot().push_many([libdir(), ~"cargo"]))
}
fn get_cargo_root() -> result<Path, ~str> {
match os::getenv(~"CARGO_ROOT") {
some(_p) => result::ok(_p),
some(_p) => result::ok(Path(_p)),
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")
}
}
@ -132,21 +129,21 @@ fn get_cargo_root() -> result<Path, ~str> {
fn get_cargo_root_nearest() -> result<Path, ~str> {
do result::chain(get_cargo_root()) |p| {
let cwd = os::getcwd();
let mut dirname = path::dirname(cwd);
let mut dirpath = path::split(dirname);
let cwd_cargo = path::connect(cwd, ~".cargo");
let mut par_cargo = path::connect(dirname, ~".cargo");
let cwd_cargo = cwd.push(".cargo");
let mut par_cargo = cwd.pop().push(".cargo");
let mut rslt = result::ok(cwd_cargo);
if !os::path_is_dir(cwd_cargo) && cwd_cargo != p {
while vec::is_not_empty(dirpath) && par_cargo != p {
if os::path_is_dir(par_cargo) {
if !os::path_is_dir(&cwd_cargo) && cwd_cargo != p {
while par_cargo != p {
if os::path_is_dir(&par_cargo) {
rslt = result::ok(par_cargo);
break;
}
vec::pop(dirpath);
dirname = path::dirname(dirname);
par_cargo = path::connect(dirname, ~".cargo");
if par_cargo.components.len() == 1 {
// We just checked /.cargo, stop now.
break;
}
par_cargo = par_cargo.pop().pop().push(".cargo");
}
}
rslt
@ -155,13 +152,13 @@ fn get_cargo_root_nearest() -> result<Path, ~str> {
fn get_cargo_lib_path() -> result<Path, ~str> {
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> {
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 = ~[];
filesearch::search(filesearch, |path| {
debug!("inspecting file %s", path);
let f: ~str = path::basename(path);
debug!("inspecting file %s", path.to_str());
let f: ~str = option::get(path.filename());
if !(str::starts_with(f, prefix) && str::ends_with(f, suffix)) {
debug!("skipping %s, doesn't look like %s*%s", path, prefix,
suffix);
debug!("skipping %s, doesn't look like %s*%s", path.to_str(),
prefix, suffix);
option::none::<()>
} else {
debug!("%s is a candidate", path);
debug!("%s is a candidate", path.to_str());
match get_metadata_section(cx.os, path) {
option::some(cvec) => {
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::<()>
} else {
debug!("found %s with matching metadata", path);
vec::push(matches, {ident: path, data: cvec});
debug!("found %s with matching metadata", path.to_str());
vec::push(matches, {ident: path.to_str(), data: cvec});
option::none::<()>
}
}
_ => {
debug!("could not load metadata for %s", path);
debug!("could not load metadata for %s", path.to_str());
option::none::<()>
}
}
@ -168,10 +169,10 @@ fn metadata_matches(extern_metas: ~[@ast::meta_item],
}
fn get_metadata_section(os: os,
filename: ~str) -> option<@~[u8]> unsafe {
let mb = str::as_c_str(filename, |buf| {
filename: &Path) -> option<@~[u8]> unsafe {
let mb = str::as_c_str(filename.to_str(), |buf| {
llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
});
});
if mb as int == 0 { return option::none::<@~[u8]>; }
let of = match mk_object_file(mb) {
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
fn list_file_metadata(intr: ident_interner, os: os, path: ~str,
out: io::Writer) {
fn list_file_metadata(intr: ident_interner,
os: os, path: &Path, out: io::Writer) {
match get_metadata_section(os, path) {
option::some(bytes) => decoder::list_crate_metadata(intr, bytes, out),
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,
crate: @ast::crate,
tcx: ty::ctxt,
output: ~str,
output: &Path,
emap: resolve3::ExportMap,
emap2: resolve3::ExportMap2,
maps: astencode::maps)

View File

@ -172,7 +172,7 @@ fn create_compile_unit(cx: @crate_ctxt)
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);
let unit_metadata = ~[lltag(tg),
llunused(),
@ -197,13 +197,13 @@ fn get_cache(cx: @crate_ctxt) -> metadata_cache {
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) {
str::slice(full_path, str::len(work_dir) + 1u,
str::len(full_path))
} else {
full_path
}, work_dir)
str::from_slice(full_path)
}, str::from_slice(work_dir))
}
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 => ()
}
let (file_path, work_dir) = get_file_path_and_dir(cx.sess.working_dir,
full_path);
let (file_path, work_dir) =
get_file_path_and_dir(cx.sess.working_dir.to_str(),
full_path);
let unit_node = create_compile_unit(cx).node;
let file_md = ~[lltag(tg),
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(_) => {
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)
}
}

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 {
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 {

View File

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

View File

@ -81,7 +81,7 @@ fn item_to_entry(
let link = match doc {
doc::modtag(_) | doc::nmodtag(_)
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))
@ -230,7 +230,7 @@ mod test {
do astsrv::from_str(source) |srv| {
let config = {
output_style: output_style
with config::default_config(~"whatever")
with config::default_config(&Path("whatever"))
};
let doc = extract::from_srv(srv, ~"");
let doc = attr_pass::mk_pass().f(srv, doc);

View File

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

View File

@ -66,7 +66,7 @@ fn markdown_writer(
) -> writer {
let filename = make_local_filename(config, page);
do generic_writer |markdown| {
write_file(filename, markdown);
write_file(&filename, markdown);
}
}
@ -84,7 +84,7 @@ fn pandoc_writer(
~"--from=markdown",
~"--to=html",
~"--css=rust.css",
~"--output=" + filename
~"--output=" + filename.to_str()
];
do generic_writer |markdown| {
@ -166,15 +166,15 @@ fn generic_writer(+process: fn~(markdown: ~str)) -> writer {
fn make_local_filename(
config: config::config,
page: doc::page
) -> ~str {
) -> Path {
let filename = make_filename(config, page);
path::connect(config.output_dir, filename)
config.output_dir.push_rel(&filename)
}
fn make_filename(
config: config::config,
page: doc::page
) -> ~str {
) -> Path {
let filename = {
match page {
doc::cratepage(doc) => {
@ -196,50 +196,50 @@ fn make_filename(
config::pandoc_html => ~"html"
};
filename + ~"." + ext
Path(filename).with_filetype(ext)
}
#[test]
fn should_use_markdown_file_name_based_off_crate() {
let config = {
output_dir: ~"output/dir",
output_dir: Path("output/dir"),
output_format: config::markdown,
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 page = doc::cratepage(doc.cratedoc());
let filename = make_local_filename(config, page);
assert filename == ~"output/dir/test.md";
assert filename.to_str() == ~"output/dir/test.md";
}
#[test]
fn should_name_html_crate_file_name_index_html_when_doc_per_mod() {
let config = {
output_dir: ~"output/dir",
output_dir: Path("output/dir"),
output_format: config::pandoc_html,
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 page = doc::cratepage(doc.cratedoc());
let filename = make_local_filename(config, page);
assert filename == ~"output/dir/index.html";
assert filename.to_str() == ~"output/dir/index.html";
}
#[test]
fn should_name_mod_file_names_by_path() {
let config = {
output_dir: ~"output/dir",
output_dir: Path("output/dir"),
output_format: config::pandoc_html,
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 modb = doc.cratemod().mods()[0].mods()[0];
let page = doc::itempage(doc::modtag(modb));
let filename = make_local_filename(config, page);
assert filename == ~"output/dir/a_b.html";
assert filename == Path("output/dir/a_b.html");
}
#[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;
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;
fn from_file(file: ~str) -> @ast::crate {
fn from_file(file: &Path) -> @ast::crate {
parse::parse_crate_from_file(
file, ~[], parse::new_parse_sess(none))
}
@ -20,9 +20,9 @@ fn from_str(source: ~str) -> @ast::crate {
~"-", @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(
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 {

View File

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

View File

@ -52,13 +52,11 @@ fn shift_push() {
}
fn read_line() {
let path = path::connect(
env!("CFG_SRC_DIR"),
~"src/test/bench/shootout-k-nucleotide.data"
);
let path = Path(env!("CFG_SRC_DIR"))
.push_rel(&Path("src/test/bench/shootout-k-nucleotide.data"));
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() {
reader.read_line();
}

View File

@ -85,7 +85,8 @@ fn main(args: ~[~str]) {
};
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 {
io::stdout()
};

View File

@ -128,11 +128,9 @@ fn main(args: ~[~str]) {
let rdr = if os::getenv(~"RUST_BENCH").is_some() {
// 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)
let path = path::connect(
env!("CFG_SRC_DIR"),
~"src/test/bench/shootout-k-nucleotide.data"
);
result::get(io::file_reader(path))
let path = Path(env!("CFG_SRC_DIR"))
.push_rel(&Path("src/test/bench/shootout-k-nucleotide.data"));
result::get(io::file_reader(&path))
} else {
io::stdin()
};

View File

@ -126,11 +126,9 @@ fn main(args: ~[~str]) {
let rdr = if os::getenv(~"RUST_BENCH").is_some() {
// 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)
let path = path::connect(
env!("CFG_SRC_DIR"),
~"src/test/bench/shootout-k-nucleotide.data"
);
result::get(io::file_reader(path))
let path = Path(env!("CFG_SRC_DIR"))
.push_rel(&Path("src/test/bench/shootout-k-nucleotide.data"));
result::get(io::file_reader(&path))
} else {
io::stdin()
};

View File

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

View File

@ -80,7 +80,7 @@ impl io::Reader: 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::err(e) => { fail fmt!("%?", e) }
}