path2: Replace the path module outright

Remove the old path.
Rename path2 to path.
Update all clients for the new path.

Also make some miscellaneous changes to the Path APIs to help the
adoption process.
This commit is contained in:
Kevin Ballard 2013-09-26 17:21:59 -07:00
parent 6741241f40
commit 73d3d00ec4
63 changed files with 2501 additions and 2989 deletions

View File

@ -102,15 +102,15 @@ pub fn parse_config(args: ~[~str]) -> config {
}
fn opt_path(m: &getopts::Matches, nm: &str) -> Path {
Path(m.opt_str(nm).unwrap())
Path::from_str(m.opt_str(nm).unwrap())
}
config {
compile_lib_path: matches.opt_str("compile-lib-path").unwrap(),
run_lib_path: matches.opt_str("run-lib-path").unwrap(),
rustc_path: opt_path(matches, "rustc-path"),
clang_path: matches.opt_str("clang-path").map(|s| Path(s)),
llvm_bin_path: matches.opt_str("llvm-bin-path").map(|s| Path(s)),
clang_path: matches.opt_str("clang-path").map(|s| Path::from_str(s)),
llvm_bin_path: matches.opt_str("llvm-bin-path").map(|s| Path::from_str(s)),
src_base: opt_path(matches, "src-base"),
build_base: opt_path(matches, "build-base"),
aux_base: opt_path(matches, "aux-base"),
@ -123,10 +123,10 @@ pub fn parse_config(args: ~[~str]) -> config {
} else {
None
},
logfile: matches.opt_str("logfile").map(|s| Path(s)),
save_metrics: matches.opt_str("save-metrics").map(|s| Path(s)),
logfile: matches.opt_str("logfile").map(|s| Path::from_str(s)),
save_metrics: matches.opt_str("save-metrics").map(|s| Path::from_str(s)),
ratchet_metrics:
matches.opt_str("ratchet-metrics").map(|s| Path(s)),
matches.opt_str("ratchet-metrics").map(|s| Path::from_str(s)),
ratchet_noise_percent:
matches.opt_str("ratchet-noise-percent").and_then(|s| from_str::<f64>(s)),
runtool: matches.opt_str("runtool"),
@ -155,9 +155,9 @@ pub fn log_config(config: &config) {
logv(c, format!("configuration:"));
logv(c, format!("compile_lib_path: {}", config.compile_lib_path));
logv(c, format!("run_lib_path: {}", config.run_lib_path));
logv(c, format!("rustc_path: {}", config.rustc_path.to_str()));
logv(c, format!("src_base: {}", config.src_base.to_str()));
logv(c, format!("build_base: {}", config.build_base.to_str()));
logv(c, format!("rustc_path: {}", config.rustc_path.display()));
logv(c, format!("src_base: {}", config.src_base.display()));
logv(c, format!("build_base: {}", config.build_base.display()));
logv(c, format!("stage_id: {}", config.stage_id));
logv(c, format!("mode: {}", mode_str(config.mode)));
logv(c, format!("run_ignored: {}", config.run_ignored));
@ -245,12 +245,12 @@ pub fn test_opts(config: &config) -> test::TestOpts {
pub fn make_tests(config: &config) -> ~[test::TestDescAndFn] {
debug2!("making tests from {}",
config.src_base.to_str());
config.src_base.display());
let mut tests = ~[];
let dirs = os::list_dir_path(&config.src_base);
for file in dirs.iter() {
let file = file.clone();
debug2!("inspecting file {}", file.to_str());
debug2!("inspecting file {}", file.display());
if is_test(config, &file) {
let t = do make_test(config, &file) {
match config.mode {
@ -272,7 +272,7 @@ pub fn is_test(config: &config, testfile: &Path) -> bool {
_ => ~[~".rc", ~".rs"]
};
let invalid_prefixes = ~[~".", ~"#", ~"~"];
let name = testfile.filename().unwrap();
let name = testfile.filename_str().unwrap();
let mut valid = false;
@ -303,9 +303,9 @@ pub fn make_test_name(config: &config, testfile: &Path) -> test::TestName {
// Try to elide redundant long paths
fn shorten(path: &Path) -> ~str {
let filename = path.filename();
let p = path.pop();
let dir = p.filename();
let filename = path.filename_str();
let p = path.dir_path();
let dir = p.filename_str();
format!("{}/{}", dir.unwrap_or(""), filename.unwrap_or(""))
}
@ -317,13 +317,15 @@ pub fn make_test_name(config: &config, testfile: &Path) -> test::TestName {
pub fn make_test_closure(config: &config, testfile: &Path) -> test::TestFn {
use std::cell::Cell;
let config = Cell::new((*config).clone());
let testfile = Cell::new(testfile.to_str());
// FIXME (#9639): This needs to handle non-utf8 paths
let testfile = Cell::new(testfile.as_str().unwrap().to_owned());
test::DynTestFn(|| { runtest::run(config.take(), testfile.take()) })
}
pub fn make_metrics_test_closure(config: &config, testfile: &Path) -> test::TestFn {
use std::cell::Cell;
let config = Cell::new((*config).clone());
let testfile = Cell::new(testfile.to_str());
// FIXME (#9639): This needs to handle non-utf8 paths
let testfile = Cell::new(testfile.as_str().unwrap().to_owned());
test::DynMetricFn(|mm| { runtest::run_metrics(config.take(), testfile.take(), mm) })
}

View File

@ -161,10 +161,10 @@ fn parse_exec_env(line: &str) -> Option<(~str, ~str)> {
fn parse_pp_exact(line: &str, testfile: &Path) -> Option<Path> {
match parse_name_value_directive(line, ~"pp-exact") {
Some(s) => Some(Path(s)),
Some(s) => Some(Path::from_str(s)),
None => {
if parse_name_directive(line, "pp-exact") {
Some(testfile.file_path())
testfile.file_path()
} else {
None
}

View File

@ -62,8 +62,8 @@ pub fn run_metrics(config: config, testfile: ~str, mm: &mut MetricMap) {
// We're going to be dumping a lot of info. Start on a new line.
io::stdout().write_str("\n\n");
}
let testfile = Path(testfile);
debug2!("running {}", testfile.to_str());
let testfile = Path::from_str(testfile);
debug2!("running {}", testfile.display());
let props = load_props(&testfile);
debug2!("loaded props");
match config.mode {
@ -189,7 +189,7 @@ fn run_pretty_test(config: &config, props: &TestProps, testfile: &Path) {
let mut expected = match props.pp_exact {
Some(ref file) => {
let filepath = testfile.dir_path().push_rel(file);
let filepath = testfile.dir_path().join_path(file);
io::read_whole_file_str(&filepath).unwrap()
}
None => { srcs[srcs.len() - 2u].clone() }
@ -221,7 +221,8 @@ fn run_pretty_test(config: &config, props: &TestProps, testfile: &Path) {
fn make_pp_args(config: &config, _testfile: &Path) -> ProcArgs {
let args = ~[~"-", ~"--pretty", ~"normal"];
return ProcArgs {prog: config.rustc_path.to_str(), args: args};
// FIXME (#9639): This needs to handle non-utf8 paths
return ProcArgs {prog: config.rustc_path.as_str().unwrap().to_owned(), args: args};
}
fn compare_source(expected: &str, actual: &str) {
@ -251,14 +252,17 @@ actual:\n\
}
fn make_typecheck_args(config: &config, props: &TestProps, testfile: &Path) -> ProcArgs {
let aux_dir = aux_output_dir_name(config, testfile);
// FIXME (#9639): This needs to handle non-utf8 paths
let mut args = ~[~"-",
~"--no-trans", ~"--lib",
~"-L", config.build_base.to_str(),
~"-L", config.build_base.as_str().unwrap().to_owned(),
~"-L",
aux_output_dir_name(config, testfile).to_str()];
aux_dir.as_str().unwrap().to_owned()];
args.push_all_move(split_maybe_args(&config.rustcflags));
args.push_all_move(split_maybe_args(&props.compile_flags));
return ProcArgs {prog: config.rustc_path.to_str(), args: args};
// FIXME (#9639): This needs to handle non-utf8 paths
return ProcArgs {prog: config.rustc_path.as_str().unwrap().to_owned(), args: args};
}
}
@ -294,9 +298,11 @@ fn run_debuginfo_test(config: &config, props: &TestProps, testfile: &Path) {
#[cfg(unix)]
fn debugger() -> ~str { ~"gdb" }
let debugger_script = make_out_name(config, testfile, "debugger.script");
let exe_file = make_exe_name(config, testfile);
// FIXME (#9639): This needs to handle non-utf8 paths
let debugger_opts = ~[~"-quiet", ~"-batch", ~"-nx",
~"-command=" + debugger_script.to_str(),
make_exe_name(config, testfile).to_str()];
~"-command=" + debugger_script.as_str().unwrap().to_owned(),
exe_file.as_str().unwrap().to_owned()];
let ProcArgs = ProcArgs {prog: debugger(), args: debugger_opts};
ProcRes = compose_and_run(config, testfile, ProcArgs, ~[], "", None);
if ProcRes.status != 0 {
@ -328,7 +334,9 @@ fn check_error_patterns(props: &TestProps,
testfile: &Path,
ProcRes: &ProcRes) {
if props.error_patterns.is_empty() {
fatal(~"no error pattern specified in " + testfile.to_str());
do testfile.with_display_str |s| {
fatal(~"no error pattern specified in " + s);
}
}
if ProcRes.status == 0 {
@ -378,7 +386,7 @@ fn check_expected_errors(expected_errors: ~[errors::ExpectedError],
}
let prefixes = expected_errors.iter().map(|ee| {
format!("{}:{}:", testfile.to_str(), ee.line)
format!("{}:{}:", testfile.display(), ee.line)
}).collect::<~[~str]>();
fn to_lower( s : &str ) -> ~str {
@ -538,7 +546,9 @@ fn jit_test(config: &config, props: &TestProps, testfile: &Path) -> ProcRes {
fn compile_test_(config: &config, props: &TestProps,
testfile: &Path, extra_args: &[~str]) -> ProcRes {
let link_args = ~[~"-L", aux_output_dir_name(config, testfile).to_str()];
let aux_dir = aux_output_dir_name(config, testfile);
// FIXME (#9639): This needs to handle non-utf8 paths
let link_args = ~[~"-L", aux_dir.as_str().unwrap().to_owned()];
let args = make_compile_args(config, props, link_args + extra_args,
make_exe_name, testfile);
compose_and_run_compiler(config, props, testfile, args, None)
@ -579,11 +589,12 @@ fn compose_and_run_compiler(
ensure_dir(&aux_output_dir_name(config, testfile));
}
let extra_link_args = ~[~"-L",
aux_output_dir_name(config, testfile).to_str()];
let aux_dir = aux_output_dir_name(config, testfile);
// FIXME (#9639): This needs to handle non-utf8 paths
let extra_link_args = ~[~"-L", aux_dir.as_str().unwrap().to_owned()];
for rel_ab in props.aux_builds.iter() {
let abs_ab = config.aux_base.push_rel(&Path(*rel_ab));
let abs_ab = config.aux_base.join_str(*rel_ab);
let aux_args =
make_compile_args(config, props, ~[~"--lib"] + extra_link_args,
|a,b| make_lib_name(a, b, testfile), &abs_ab);
@ -592,7 +603,7 @@ fn compose_and_run_compiler(
if auxres.status != 0 {
fatal_ProcRes(
format!("auxiliary build of {} failed to compile: ",
abs_ab.to_str()),
abs_ab.display()),
&auxres);
}
@ -615,7 +626,7 @@ fn compose_and_run_compiler(
fn ensure_dir(path: &Path) {
if os::path_is_dir(path) { return; }
if !os::make_dir(path, 0x1c0i32) {
fail2!("can't make dir {}", path.to_str());
fail2!("can't make dir {}", path.display());
}
}
@ -631,24 +642,28 @@ fn compose_and_run(config: &config, testfile: &Path,
fn make_compile_args(config: &config, props: &TestProps, extras: ~[~str],
xform: &fn(&config, (&Path)) -> Path,
testfile: &Path) -> ProcArgs {
let mut args = ~[testfile.to_str(),
~"-o", xform(config, testfile).to_str(),
~"-L", config.build_base.to_str()]
let xform_file = xform(config, testfile);
// FIXME (#9639): This needs to handle non-utf8 paths
let mut args = ~[testfile.as_str().unwrap().to_owned(),
~"-o", xform_file.as_str().unwrap().to_owned(),
~"-L", config.build_base.as_str().unwrap().to_owned()]
+ extras;
args.push_all_move(split_maybe_args(&config.rustcflags));
args.push_all_move(split_maybe_args(&props.compile_flags));
return ProcArgs {prog: config.rustc_path.to_str(), args: args};
return ProcArgs {prog: config.rustc_path.as_str().unwrap().to_owned(), args: args};
}
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);
aux_output_dir_name(config, testfile).push_rel(&auxname)
aux_output_dir_name(config, testfile).join_path(&auxname)
}
fn make_exe_name(config: &config, testfile: &Path) -> Path {
Path(output_base_name(config, testfile).to_str() + os::EXE_SUFFIX)
let mut f = output_base_name(config, testfile);
f.add_extension_str(os::EXE_EXTENSION);
f
}
fn make_run_args(config: &config, _props: &TestProps, testfile: &Path) ->
@ -656,7 +671,9 @@ fn make_run_args(config: &config, _props: &TestProps, testfile: &Path) ->
// If we've got another tool to run under (valgrind),
// then split apart its command
let mut args = split_maybe_args(&config.runtool);
args.push(make_exe_name(config, testfile).to_str());
let exe_file = make_exe_name(config, testfile);
// FIXME (#9639): This needs to handle non-utf8 paths
args.push(exe_file.as_str().unwrap().to_owned());
let prog = args.shift();
return ProcArgs {prog: prog, args: args};
}
@ -725,21 +742,23 @@ fn dump_output_file(config: &config, testfile: &Path,
}
fn make_out_name(config: &config, testfile: &Path, extension: &str) -> Path {
output_base_name(config, testfile).with_filetype(extension)
output_base_name(config, testfile).with_extension_str(extension)
}
fn aux_output_dir_name(config: &config, testfile: &Path) -> Path {
Path(output_base_name(config, testfile).to_str() + ".libaux")
let mut f = output_base_name(config, testfile);
f.add_extension_str("libaux");
f
}
fn output_testname(testfile: &Path) -> Path {
Path(testfile.filestem().unwrap())
Path::from_vec(testfile.filestem().unwrap())
}
fn output_base_name(config: &config, testfile: &Path) -> Path {
config.build_base
.push_rel(&output_testname(testfile))
.with_filetype(config.stage_id)
.join_path(&output_testname(testfile))
.with_extension_str(config.stage_id)
}
fn maybe_dump_to_stdout(config: &config, out: &str, err: &str) {
@ -875,20 +894,19 @@ fn _dummy_exec_compiled_test(config: &config, props: &TestProps,
}
fn _arm_push_aux_shared_library(config: &config, testfile: &Path) {
let tstr = aux_output_dir_name(config, testfile).to_str();
let tdir = aux_output_dir_name(config, testfile);
let dirs = os::list_dir_path(&Path(tstr));
let dirs = os::list_dir_path(&tdir);
for file in dirs.iter() {
if (file.filetype() == Some(".so")) {
if file.extension_str() == Some("so") {
// FIXME (#9639): This needs to handle non-utf8 paths
let copy_result = procsrv::run("", config.adb_path,
[~"push", file.to_str(), config.adb_test_dir.clone()],
[~"push", file.as_str().unwrap().to_owned(), config.adb_test_dir.clone()],
~[(~"",~"")], Some(~""));
if config.verbose {
io::stdout().write_str(format!("push ({}) {} {} {}",
config.target, file.to_str(),
config.target, file.display(),
copy_result.out, copy_result.err));
}
}
@ -898,7 +916,7 @@ fn _arm_push_aux_shared_library(config: &config, testfile: &Path) {
// codegen tests (vs. clang)
fn make_o_name(config: &config, testfile: &Path) -> Path {
output_base_name(config, testfile).with_filetype("o")
output_base_name(config, testfile).with_extension_str("o")
}
fn append_suffix_to_stem(p: &Path, suffix: &str) -> Path {
@ -906,13 +924,15 @@ fn append_suffix_to_stem(p: &Path, suffix: &str) -> Path {
(*p).clone()
} else {
let stem = p.filestem().unwrap();
p.with_filestem(stem + "-" + suffix)
p.with_filename(stem + bytes!("-") + suffix.as_bytes())
}
}
fn compile_test_and_save_bitcode(config: &config, props: &TestProps,
testfile: &Path) -> ProcRes {
let link_args = ~[~"-L", aux_output_dir_name(config, testfile).to_str()];
let aux_dir = aux_output_dir_name(config, testfile);
// FIXME (#9639): This needs to handle non-utf8 paths
let link_args = ~[~"-L", aux_dir.as_str().unwrap().to_owned()];
let llvm_args = ~[~"-c", ~"--lib", ~"--save-temps"];
let args = make_compile_args(config, props,
link_args + llvm_args,
@ -922,14 +942,16 @@ fn compile_test_and_save_bitcode(config: &config, props: &TestProps,
fn compile_cc_with_clang_and_save_bitcode(config: &config, _props: &TestProps,
testfile: &Path) -> ProcRes {
let bitcodefile = output_base_name(config, testfile).with_filetype("bc");
let bitcodefile = output_base_name(config, testfile).with_extension_str("bc");
let bitcodefile = append_suffix_to_stem(&bitcodefile, "clang");
let testcc = testfile.with_extension_str("cc");
let ProcArgs = ProcArgs {
prog: config.clang_path.get_ref().to_str(),
// FIXME (#9639): This needs to handle non-utf8 paths
prog: config.clang_path.get_ref().as_str().unwrap().to_owned(),
args: ~[~"-c",
~"-emit-llvm",
~"-o", bitcodefile.to_str(),
testfile.with_filetype("cc").to_str() ]
~"-o", bitcodefile.as_str().unwrap().to_owned(),
testcc.as_str().unwrap().to_owned() ]
};
compose_and_run(config, testfile, ProcArgs, ~[], "", None)
}
@ -937,35 +959,39 @@ fn compile_cc_with_clang_and_save_bitcode(config: &config, _props: &TestProps,
fn extract_function_from_bitcode(config: &config, _props: &TestProps,
fname: &str, testfile: &Path,
suffix: &str) -> ProcRes {
let bitcodefile = output_base_name(config, testfile).with_filetype("bc");
let bitcodefile = output_base_name(config, testfile).with_extension_str("bc");
let bitcodefile = append_suffix_to_stem(&bitcodefile, suffix);
let extracted_bc = append_suffix_to_stem(&bitcodefile, "extract");
let prog = config.llvm_bin_path.get_ref().join_str("llvm-extract");
let ProcArgs = ProcArgs {
prog: config.llvm_bin_path.get_ref().push("llvm-extract").to_str(),
args: ~[~"-func=" + fname,
~"-o=" + extracted_bc.to_str(),
bitcodefile.to_str() ]
// FIXME (#9639): This needs to handle non-utf8 paths
prog: prog.as_str().unwrap().to_owned(),
args: ~["-func=" + fname,
"-o=" + extracted_bc.as_str().unwrap(),
bitcodefile.as_str().unwrap().to_owned() ]
};
compose_and_run(config, testfile, ProcArgs, ~[], "", None)
}
fn disassemble_extract(config: &config, _props: &TestProps,
testfile: &Path, suffix: &str) -> ProcRes {
let bitcodefile = output_base_name(config, testfile).with_filetype("bc");
let bitcodefile = output_base_name(config, testfile).with_extension_str("bc");
let bitcodefile = append_suffix_to_stem(&bitcodefile, suffix);
let extracted_bc = append_suffix_to_stem(&bitcodefile, "extract");
let extracted_ll = extracted_bc.with_filetype("ll");
let extracted_ll = extracted_bc.with_extension_str("ll");
let prog = config.llvm_bin_path.get_ref().join_str("llvm-dis");
let ProcArgs = ProcArgs {
prog: config.llvm_bin_path.get_ref().push("llvm-dis").to_str(),
args: ~[~"-o=" + extracted_ll.to_str(),
extracted_bc.to_str() ]
// FIXME (#9639): This needs to handle non-utf8 paths
prog: prog.as_str().unwrap().to_owned(),
args: ~["-o=" + extracted_ll.as_str().unwrap(),
extracted_bc.as_str().unwrap().to_owned() ]
};
compose_and_run(config, testfile, ProcArgs, ~[], "", None)
}
fn count_extracted_lines(p: &Path) -> uint {
let x = io::read_whole_file_str(&p.with_filetype("ll")).unwrap();
let x = io::read_whole_file_str(&p.with_extension_str("ll")).unwrap();
x.line_iter().len()
}

View File

@ -362,7 +362,7 @@ pub fn make_path_option_vec(vec: &[~str], stdin_hyphen : bool) -> ~[Option<Path>
if stdin_hyphen && "-" == *str {
None
} else {
Some(Path(*str))
Some(Path::from_str(*str))
}
}).collect()
}
@ -435,14 +435,14 @@ mod test {
fn test_make_path_option_vec() {
let strs = [~"some/path",
~"some/other/path"];
let paths = ~[Some(Path("some/path")),
Some(Path("some/other/path"))];
let paths = ~[Some(Path::from_str("some/path")),
Some(Path::from_str("some/other/path"))];
assert_eq!(make_path_option_vec(strs, true), paths.clone());
assert_eq!(make_path_option_vec(strs, false), paths);
assert_eq!(make_path_option_vec([~"-"], true), ~[None]);
assert_eq!(make_path_option_vec([~"-"], false), ~[Some(Path("-"))]);
assert_eq!(make_path_option_vec([~"-"], false), ~[Some(Path::from_str("-"))]);
}
#[test]
@ -567,9 +567,9 @@ mod test {
#[test]
fn test_no_trailing_newline() {
let f1 =
Some(Path("tmp/lib-fileinput-test-no-trailing-newline-1.tmp"));
Some(Path::from_str("tmp/lib-fileinput-test-no-trailing-newline-1.tmp"));
let f2 =
Some(Path("tmp/lib-fileinput-test-no-trailing-newline-2.tmp"));
Some(Path::from_str("tmp/lib-fileinput-test-no-trailing-newline-2.tmp"));
{
let mut wr = file::open(f1.get_ref(), io::CreateOrTruncate,

View File

@ -35,7 +35,7 @@ pub struct GlobIterator {
priv root: Path,
priv dir_patterns: ~[Pattern],
priv options: MatchOptions,
priv todo: ~[Path]
priv todo: ~[(Path,uint)]
}
/**
@ -80,18 +80,32 @@ pub fn glob(pattern: &str) -> GlobIterator {
* Paths are yielded in alphabetical order, as absolute paths.
*/
pub fn glob_with(pattern: &str, options: MatchOptions) -> GlobIterator {
#[cfg(windows)]
use is_sep = std::path::windows::is_sep2;
#[cfg(not(windows))]
fn is_sep(c: char) -> bool { c <= '\x7F' && ::std::path::posix::is_sep(&(c as u8)) }
#[cfg(windows)]
fn check_windows_verbatim(p: &Path) -> bool { p.is_verbatim() }
#[cfg(not(windows))]
fn check_windows_verbatim(_: &Path) -> bool { false }
// note that this relies on the glob meta characters not
// having any special meaning in actual pathnames
let path = Path(pattern);
let dir_patterns = path.components.map(|s| Pattern::new(*s));
// calculate root this way to handle volume-relative Windows paths correctly
let mut root = os::getcwd();
let pat_root = Path::from_str(pattern).root_path();
if pat_root.is_some() {
if check_windows_verbatim(pat_root.get_ref()) {
// XXX: How do we want to handle verbatim paths? I'm inclined to return nothing,
// since we can't very well find all UNC shares with a 1-letter server name.
return GlobIterator { root: root, dir_patterns: ~[], options: options, todo: ~[] };
}
root.push_path(pat_root.get_ref());
}
let root = if path.is_absolute() {
Path {components: ~[], .. path} // preserve windows path host/device
} else {
os::getcwd()
};
let todo = list_dir_sorted(&root);
let root_len = pat_root.map_move_default(0u, |p| p.as_vec().len());
let dir_patterns = pattern.slice_from(root_len.min(&pattern.len()))
.split_terminator_iter(is_sep).map(|s| Pattern::new(s)).to_owned_vec();
let todo = list_dir_sorted(&root).move_iter().map(|x|(x,0u)).to_owned_vec();
GlobIterator {
root: root,
@ -109,18 +123,24 @@ impl Iterator<Path> for GlobIterator {
return None;
}
let path = self.todo.pop();
let pattern_index = path.components.len() - self.root.components.len() - 1;
let ref pattern = self.dir_patterns[pattern_index];
let (path,idx) = self.todo.pop();
let ref pattern = self.dir_patterns[idx];
if pattern.matches_with(*path.components.last(), self.options) {
if pattern_index == self.dir_patterns.len() - 1 {
if pattern.matches_with(match path.filename_str() {
// this ugly match needs to go here to avoid a borrowck error
None => {
// FIXME (#9639): How do we handle non-utf8 filenames? Ignore them for now
// Ideally we'd still match them against a *
loop;
}
Some(x) => x
}, self.options) {
if idx == self.dir_patterns.len() - 1 {
// it is not possible for a pattern to match a directory *AND* its children
// so we don't need to check the children
return Some(path);
} else {
self.todo.push_all(list_dir_sorted(&path));
self.todo.extend(&mut list_dir_sorted(&path).move_iter().map(|x|(x,idx+1)));
}
}
}
@ -130,7 +150,7 @@ impl Iterator<Path> for GlobIterator {
fn list_dir_sorted(path: &Path) -> ~[Path] {
let mut children = os::list_dir_path(path);
sort::quick_sort(children, |p1, p2| p2.components.last() <= p1.components.last());
sort::quick_sort(children, |p1, p2| p2.filename().unwrap() <= p1.filename().unwrap());
children
}
@ -285,7 +305,10 @@ impl Pattern {
* using the default match options (i.e. `MatchOptions::new()`).
*/
pub fn matches_path(&self, path: &Path) -> bool {
self.matches(path.to_str())
// FIXME (#9639): This needs to handle non-utf8 paths
do path.as_str().map_move_default(false) |s| {
self.matches(s)
}
}
/**
@ -300,7 +323,10 @@ impl Pattern {
* using the specified match options.
*/
pub fn matches_path_with(&self, path: &Path, options: MatchOptions) -> bool {
self.matches_with(path.to_str(), options)
// FIXME (#9639): This needs to handle non-utf8 paths
do path.as_str().map_move_default(false) |s| {
self.matches_with(s, options)
}
}
fn matches_from(&self,
@ -436,7 +462,7 @@ fn in_char_specifiers(specifiers: &[CharSpecifier], c: char, options: MatchOptio
/// A helper function to determine if two chars are (possibly case-insensitively) equal.
fn chars_eq(a: char, b: char, case_sensitive: bool) -> bool {
if cfg!(windows) && path::windows::is_sep(a) && path::windows::is_sep(b) {
if cfg!(windows) && path::windows::is_sep2(a) && path::windows::is_sep2(b) {
true
} else if !case_sensitive && a.is_ascii() && b.is_ascii() {
// FIXME: work with non-ascii chars properly (issue #1347)
@ -449,9 +475,9 @@ fn chars_eq(a: char, b: char, case_sensitive: bool) -> bool {
/// A helper function to determine if a char is a path separator on the current platform.
fn is_sep(c: char) -> bool {
if cfg!(windows) {
path::windows::is_sep(c)
path::windows::is_sep2(c)
} else {
path::posix::is_sep(c)
c <= '\x7F' && path::posix::is_sep(&(c as u8))
}
}
@ -522,8 +548,9 @@ mod test {
assert!(glob("//").next().is_none());
// check windows absolute paths with host/device components
let root_with_device = (Path {components: ~[], .. os::getcwd()}).to_str() + "*";
assert!(glob(root_with_device).next().is_some());
let root_with_device = os::getcwd().root_path().unwrap().join_str("*");
// FIXME (#9639): This needs to handle non-utf8 paths
assert!(glob(root_with_device.as_str().unwrap()).next().is_some());
}
#[test]
@ -745,9 +772,9 @@ mod test {
#[test]
fn test_matches_path() {
// on windows, (Path("a/b").to_str() == "a\\b"), so this
// on windows, (Path::from_str("a/b").as_str().unwrap() == "a\\b"), so this
// tests that / and \ are considered equivalent on windows
assert!(Pattern::new("a/b").matches_path(&Path("a/b")));
assert!(Pattern::new("a/b").matches_path(&Path::from_str("a/b")));
}
}

View File

@ -35,7 +35,7 @@ impl TempDir {
let mut r = rand::rng();
for _ in range(0u, 1000) {
let p = tmpdir.push(r.gen_ascii_str(16) + suffix);
let p = tmpdir.join_str(r.gen_ascii_str(16) + suffix);
if os::make_dir(&p, 0x1c0) { // 700
return Some(TempDir { path: Some(p) });
}

View File

@ -14,10 +14,9 @@
use std::{os, str};
use std::os::getenv;
use std::io::{file_reader, Reader};
use path = std::path::Path;
/// Return path to database entry for `term`
pub fn get_dbpath_for_term(term: &str) -> Option<~path> {
pub fn get_dbpath_for_term(term: &str) -> Option<~Path> {
if term.len() == 0 {
return None;
}
@ -29,25 +28,26 @@ pub fn get_dbpath_for_term(term: &str) -> Option<~path> {
// Find search directory
match getenv("TERMINFO") {
Some(dir) => dirs_to_search.push(path(dir)),
Some(dir) => dirs_to_search.push(Path::from_str(dir)),
None => {
if homedir.is_some() {
dirs_to_search.push(homedir.unwrap().push(".terminfo")); // ncurses compatability
// ncurses compatability;
dirs_to_search.push(homedir.unwrap().join_str(".terminfo"))
}
match getenv("TERMINFO_DIRS") {
Some(dirs) => for i in dirs.split_iter(':') {
if i == "" {
dirs_to_search.push(path("/usr/share/terminfo"));
dirs_to_search.push(Path::from_str("/usr/share/terminfo"));
} else {
dirs_to_search.push(path(i.to_owned()));
dirs_to_search.push(Path::from_str(i.to_owned()));
}
},
// Found nothing, use the default paths
// /usr/share/terminfo is the de facto location, but it seems
// Ubuntu puts it in /lib/terminfo
None => {
dirs_to_search.push(path("/usr/share/terminfo"));
dirs_to_search.push(path("/lib/terminfo"));
dirs_to_search.push(Path::from_str("/usr/share/terminfo"));
dirs_to_search.push(Path::from_str("/lib/terminfo"));
}
}
}
@ -55,14 +55,18 @@ pub fn get_dbpath_for_term(term: &str) -> Option<~path> {
// Look for the terminal in all of the search directories
for p in dirs_to_search.iter() {
let newp = ~p.push_many(&[str::from_char(first_char), term.to_owned()]);
if os::path_exists(p) && os::path_exists(newp) {
return Some(newp);
}
// on some installations the dir is named after the hex of the char (e.g. OS X)
let newp = ~p.push_many(&[format!("{:x}", first_char as uint), term.to_owned()]);
if os::path_exists(p) && os::path_exists(newp) {
return Some(newp);
if os::path_exists(p) {
let f = str::from_char(first_char);
let newp = p.join_many_str([f.as_slice(), term]);
if os::path_exists(&newp) {
return Some(~newp);
}
// on some installations the dir is named after the hex of the char (e.g. OS X)
let f = format!("{:x}", first_char as uint);
let newp = p.join_many_str([f.as_slice(), term]);
if os::path_exists(&newp) {
return Some(~newp);
}
}
}
None
@ -82,7 +86,11 @@ fn test_get_dbpath_for_term() {
// woefully inadequate test coverage
// note: current tests won't work with non-standard terminfo hierarchies (e.g. OS X's)
use std::os::{setenv, unsetenv};
fn x(t: &str) -> ~str { get_dbpath_for_term(t).expect("no terminfo entry found").to_str() };
// FIXME (#9639): This needs to handle non-utf8 paths
fn x(t: &str) -> ~str {
let p = get_dbpath_for_term(t).expect("no terminfo entry found");
p.as_str().unwrap().to_owned()
};
assert!(x("screen") == ~"/usr/share/terminfo/s/screen");
assert!(get_dbpath_for_term("") == None);
setenv("TERMINFO_DIRS", ":");

View File

@ -271,20 +271,20 @@ pub fn parse_opts(args: &[~str]) -> Option<OptRes> {
let run_ignored = matches.opt_present("ignored");
let logfile = matches.opt_str("logfile");
let logfile = logfile.map(|s| Path(s));
let logfile = logfile.map(|s| Path::from_str(s));
let run_benchmarks = matches.opt_present("bench");
let run_tests = ! run_benchmarks ||
matches.opt_present("test");
let ratchet_metrics = matches.opt_str("ratchet-metrics");
let ratchet_metrics = ratchet_metrics.map(|s| Path(s));
let ratchet_metrics = ratchet_metrics.map(|s| Path::from_str(s));
let ratchet_noise_percent = matches.opt_str("ratchet-noise-percent");
let ratchet_noise_percent = ratchet_noise_percent.map(|s| from_str::<f64>(s).unwrap());
let save_metrics = matches.opt_str("save-metrics");
let save_metrics = save_metrics.map(|s| Path(s));
let save_metrics = save_metrics.map(|s| Path::from_str(s));
let test_shard = matches.opt_str("test-shard");
let test_shard = opt_shard(test_shard);
@ -547,7 +547,7 @@ impl ConsoleTestState {
let ratchet_success = match *ratchet_metrics {
None => true,
Some(ref pth) => {
self.out.write_str(format!("\nusing metrics ratchet: {}\n", pth.to_str()));
self.out.write_str(format!("\nusing metrics ratchet: {}\n", pth.display()));
match ratchet_pct {
None => (),
Some(pct) =>
@ -659,7 +659,7 @@ pub fn run_tests_console(opts: &TestOpts,
None => (),
Some(ref pth) => {
st.metrics.save(pth);
st.out.write_str(format!("\nmetrics saved to: {}", pth.to_str()));
st.out.write_str(format!("\nmetrics saved to: {}", pth.display()));
}
}
return st.write_run_finish(&opts.ratchet_metrics, opts.ratchet_noise_percent);
@ -1440,7 +1440,7 @@ mod tests {
pub fn ratchet_test() {
let dpth = TempDir::new("test-ratchet").expect("missing test for ratchet");
let pth = dpth.path().push("ratchet.json");
let pth = dpth.path().join_str("ratchet.json");
let mut m1 = MetricMap::new();
m1.insert_metric("runtime", 1000.0, 2.0);

View File

@ -184,11 +184,11 @@ impl Database {
let f = io::file_reader(&self.db_filename);
match f {
Err(e) => fail2!("Couldn't load workcache database {}: {}",
self.db_filename.to_str(), e.to_str()),
self.db_filename.display(), e.to_str()),
Ok(r) =>
match json::from_reader(r) {
Err(e) => fail2!("Couldn't parse workcache database (from file {}): {}",
self.db_filename.to_str(), e.to_str()),
self.db_filename.display(), e.to_str()),
Ok(r) => {
let mut decoder = json::Decoder(r);
self.db_cache = Decodable::decode(&mut decoder);
@ -498,7 +498,7 @@ fn test() {
// Create a path to a new file 'filename' in the directory in which
// this test is running.
fn make_path(filename: ~str) -> Path {
let pth = os::self_exe_path().expect("workcache::test failed").pop().push(filename);
let pth = os::self_exe_path().expect("workcache::test failed").with_filename_str(filename);
if os::path_exists(&pth) {
os::remove_file(&pth);
}
@ -522,15 +522,20 @@ fn test() {
let subcx = cx.clone();
let pth = pth.clone();
prep.declare_input("file", pth.to_str(), digest_file(&pth));
// FIXME (#9639): This needs to handle non-utf8 paths
prep.declare_input("file", pth.as_str().unwrap(), digest_file(&pth));
do prep.exec |_exe| {
let out = make_path(~"foo.o");
run::process_status("gcc", [pth.to_str(), ~"-o", out.to_str()]);
// FIXME (#9639): This needs to handle non-utf8 paths
run::process_status("gcc", [pth.as_str().unwrap().to_owned(),
~"-o",
out.as_str().unwrap().to_owned()]);
let _proof_of_concept = subcx.prep("subfn");
// Could run sub-rules inside here.
out.to_str()
// FIXME (#9639): This needs to handle non-utf8 paths
out.as_str().unwrap().to_owned()
}
};

View File

@ -70,7 +70,7 @@ pub fn WriteOutputFile(
Target: lib::llvm::TargetMachineRef,
PM: lib::llvm::PassManagerRef,
M: ModuleRef,
Output: &str,
Output: &Path,
FileType: lib::llvm::FileType) {
unsafe {
do Output.with_c_str |Output| {
@ -129,15 +129,13 @@ pub mod jit {
let cstore = sess.cstore;
let r = cstore::get_used_crate_files(cstore);
for cratepath in r.iter() {
let path = cratepath.to_str();
debug2!("linking: {}", cratepath.display());
debug2!("linking: {}", path);
do path.with_c_str |buf_t| {
do cratepath.with_c_str |buf_t| {
if !llvm::LLVMRustLoadCrate(manager, buf_t) {
llvm_err(sess, ~"Could not link");
}
debug2!("linked: {}", path);
debug2!("linked: {}", cratepath.display());
}
}
@ -251,7 +249,7 @@ pub mod write {
llvm::LLVMInitializeMipsAsmParser();
if sess.opts.save_temps {
do output.with_filetype("no-opt.bc").with_c_str |buf| {
do output.with_extension_str("no-opt.bc").with_c_str |buf| {
llvm::LLVMWriteBitcodeToFile(llmod, buf);
}
}
@ -319,7 +317,7 @@ pub mod write {
llvm::LLVMDisposePassManager(mpm);
if sess.opts.save_temps {
do output.with_filetype("bc").with_c_str |buf| {
do output.with_extension_str("bc").with_c_str |buf| {
llvm::LLVMWriteBitcodeToFile(llmod, buf);
}
}
@ -350,12 +348,10 @@ pub mod write {
}
}
output_type_assembly => {
WriteOutputFile(sess, tm, cpm, llmod, output.to_str(),
lib::llvm::AssemblyFile);
WriteOutputFile(sess, tm, cpm, llmod, output, lib::llvm::AssemblyFile);
}
output_type_exe | output_type_object => {
WriteOutputFile(sess, tm, cpm, llmod, output.to_str(),
lib::llvm::ObjectFile);
WriteOutputFile(sess, tm, cpm, llmod, output, lib::llvm::ObjectFile);
}
}
@ -375,10 +371,11 @@ pub mod write {
pub fn run_assembler(sess: Session, assembly: &Path, object: &Path) {
let cc_prog = super::get_cc_prog(sess);
// FIXME (#9639): This needs to handle non-utf8 paths
let cc_args = ~[
~"-c",
~"-o", object.to_str(),
assembly.to_str()];
~"-o", object.as_str().unwrap().to_owned(),
assembly.as_str().unwrap().to_owned()];
let prog = run::process_output(cc_prog, cc_args);
@ -612,11 +609,12 @@ pub fn build_link_meta(sess: Session,
_ => {
// to_managed could go away if there was a version of
// filestem that returned an @str
// FIXME (#9639): Non-utf8 filenames will give a misleading error
let name = session::expect(sess,
output.filestem(),
output.filestem_str(),
|| format!("output file name `{}` doesn't\
appear to have a stem",
output.to_str())).to_managed();
output.display())).to_managed();
if name.is_empty() {
sess.fatal("missing crate link meta `name`, and the \
inferred name is blank");
@ -919,15 +917,16 @@ pub fn link_binary(sess: Session,
let long_libname = output_dll_filename(sess.targ_cfg.os, lm);
debug2!("link_meta.name: {}", lm.name);
debug2!("long_libname: {}", long_libname);
debug2!("out_filename: {}", out_filename.to_str());
debug2!("dirname(out_filename): {}", out_filename.dir_path().to_str());
debug2!("out_filename: {}", out_filename.display());
let out_dirname = out_filename.dir_path();
debug2!("dirname(out_filename): {}", out_dirname.display());
out_filename.dir_path().push(long_libname)
out_filename.with_filename_str(long_libname)
} else {
out_filename.clone()
};
debug2!("output: {}", output.to_str());
debug2!("output: {}", output.display());
let cc_args = link_args(sess, obj_filename, out_filename, lm);
debug2!("{} link args: {}", cc_prog, cc_args.connect(" "));
if (sess.opts.debugging_opts & session::print_link_args) != 0 {
@ -947,14 +946,15 @@ pub fn link_binary(sess: Session,
// Clean up on Darwin
if sess.targ_cfg.os == session::OsMacos {
run::process_status("dsymutil", [output.to_str()]);
// FIXME (#9639): This needs to handle non-utf8 paths
run::process_status("dsymutil", [output.as_str().unwrap().to_owned()]);
}
// Remove the temporary object file if we aren't saving temps
if !sess.opts.save_temps {
if ! os::remove_file(obj_filename) {
sess.warn(format!("failed to delete object file `{}`",
obj_filename.to_str()));
obj_filename.display()));
}
}
}
@ -977,20 +977,23 @@ pub fn link_args(sess: Session,
let output = if *sess.building_library {
let long_libname = output_dll_filename(sess.targ_cfg.os, lm);
out_filename.dir_path().push(long_libname)
out_filename.with_filename_str(long_libname)
} else {
out_filename.clone()
};
// 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().to_str();
// FIXME (#9639): This needs to handle non-utf8 paths
let lib_path = sess.filesearch.get_target_lib_path();
let stage: ~str = ~"-L" + lib_path.as_str().unwrap();
let mut args = vec::append(~[stage], sess.targ_cfg.target_strs.cc_args);
// FIXME (#9639): This needs to handle non-utf8 paths
args.push_all([
~"-o", output.to_str(),
obj_filename.to_str()]);
~"-o", output.as_str().unwrap().to_owned(),
obj_filename.as_str().unwrap().to_owned()]);
let lib_cmd = match sess.targ_cfg.os {
session::OsMacos => ~"-dynamiclib",
@ -1001,14 +1004,15 @@ pub fn link_args(sess: Session,
let cstore = sess.cstore;
let r = cstore::get_used_crate_files(cstore);
// FIXME (#9639): This needs to handle non-utf8 paths
for cratepath in r.iter() {
if cratepath.filetype() == Some(".rlib") {
args.push(cratepath.to_str());
if cratepath.extension_str() == Some("rlib") {
args.push(cratepath.as_str().unwrap().to_owned());
continue;
}
let dir = cratepath.dirname();
let dir = cratepath.dirname_str().unwrap();
if !dir.is_empty() { args.push("-L" + dir); }
let libarg = unlib(sess.targ_cfg, cratepath.filestem().unwrap().to_owned());
let libarg = unlib(sess.targ_cfg, cratepath.filestem_str().unwrap().to_owned());
args.push("-l" + libarg);
}
@ -1032,12 +1036,14 @@ pub fn link_args(sess: Session,
// forces to make sure that library can be found at runtime.
for path in sess.opts.addl_lib_search_paths.iter() {
args.push("-L" + path.to_str());
// FIXME (#9639): This needs to handle non-utf8 paths
args.push("-L" + path.as_str().unwrap().to_owned());
}
let rustpath = filesearch::rust_path();
for path in rustpath.iter() {
args.push("-L" + path.to_str());
// FIXME (#9639): This needs to handle non-utf8 paths
args.push("-L" + path.as_str().unwrap().to_owned());
}
// The names of the extern libraries
@ -1050,8 +1056,9 @@ pub fn link_args(sess: Session,
// On mac we need to tell the linker to let this library
// be rpathed
if sess.targ_cfg.os == session::OsMacos {
// FIXME (#9639): This needs to handle non-utf8 paths
args.push("-Wl,-install_name,@rpath/"
+ output.filename().unwrap());
+ output.filename_str().unwrap());
}
}

View File

@ -45,23 +45,26 @@ pub fn get_rpath_flags(sess: session::Session, out_filename: &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"))
let mut p = sess.filesearch.sysroot().join_path(&r);
p.push_str(os::dll_filename("rustrt"));
p
}
pub fn rpaths_to_flags(rpaths: &[Path]) -> ~[~str] {
rpaths.iter().map(|rpath| format!("-Wl,-rpath,{}",rpath.to_str())).collect()
pub fn rpaths_to_flags(rpaths: &[~str]) -> ~[~str] {
// FIXME (#9639): This needs to handle non-utf8 paths
rpaths.iter().map(|rpath| format!("-Wl,-rpath,{}",*rpath)).collect()
}
fn get_rpaths(os: session::Os,
sysroot: &Path,
output: &Path,
libs: &[Path],
target_triple: &str) -> ~[Path] {
debug2!("sysroot: {}", sysroot.to_str());
debug2!("output: {}", output.to_str());
target_triple: &str) -> ~[~str] {
debug2!("sysroot: {}", sysroot.display());
debug2!("output: {}", output.display());
debug2!("libs:");
for libpath in libs.iter() {
debug2!(" {}", libpath.to_str());
debug2!(" {}", libpath.display());
}
debug2!("target_triple: {}", target_triple);
@ -77,10 +80,10 @@ fn get_rpaths(os: session::Os,
// And a final backup rpath to the global library location.
let fallback_rpaths = ~[get_install_prefix_rpath(target_triple)];
fn log_rpaths(desc: &str, rpaths: &[Path]) {
fn log_rpaths(desc: &str, rpaths: &[~str]) {
debug2!("{} rpaths:", desc);
for rpath in rpaths.iter() {
debug2!(" {}", rpath.to_str());
debug2!(" {}", *rpath);
}
}
@ -99,14 +102,14 @@ fn get_rpaths(os: session::Os,
fn get_rpaths_relative_to_output(os: session::Os,
output: &Path,
libs: &[Path]) -> ~[Path] {
libs: &[Path]) -> ~[~str] {
libs.iter().map(|a| get_rpath_relative_to_output(os, output, a)).collect()
}
pub fn get_rpath_relative_to_output(os: session::Os,
output: &Path,
lib: &Path)
-> Path {
-> ~str {
use std::os;
assert!(not_win32(os));
@ -119,29 +122,43 @@ pub fn get_rpath_relative_to_output(os: session::Os,
session::OsWin32 => unreachable!()
};
Path(prefix).push_rel(&os::make_absolute(output).get_relative_to(&os::make_absolute(lib)))
let mut lib = os::make_absolute(lib);
lib.pop();
let mut output = os::make_absolute(output);
output.pop();
let relative = lib.path_relative_from(&output);
let relative = relative.expect("could not create rpath relative to output");
// FIXME (#9639): This needs to handle non-utf8 paths
prefix+"/"+relative.as_str().expect("non-utf8 component in path")
}
fn get_absolute_rpaths(libs: &[Path]) -> ~[Path] {
fn get_absolute_rpaths(libs: &[Path]) -> ~[~str] {
libs.iter().map(|a| get_absolute_rpath(a)).collect()
}
pub fn get_absolute_rpath(lib: &Path) -> Path {
os::make_absolute(lib).dir_path()
pub fn get_absolute_rpath(lib: &Path) -> ~str {
let mut p = os::make_absolute(lib);
p.pop();
// FIXME (#9639): This needs to handle non-utf8 paths
p.as_str().expect("non-utf8 component in rpath").to_owned()
}
pub fn get_install_prefix_rpath(target_triple: &str) -> Path {
pub fn get_install_prefix_rpath(target_triple: &str) -> ~str {
let install_prefix = env!("CFG_PREFIX");
let tlib = filesearch::relative_target_lib_path(target_triple);
os::make_absolute(&Path(install_prefix).push_rel(&tlib))
let mut path = Path::from_str(install_prefix);
path.push_path(&tlib);
let path = os::make_absolute(&path);
// FIXME (#9639): This needs to handle non-utf8 paths
path.as_str().expect("non-utf8 component in rpath").to_owned()
}
pub fn minimize_rpaths(rpaths: &[Path]) -> ~[Path] {
pub fn minimize_rpaths(rpaths: &[~str]) -> ~[~str] {
let mut set = HashSet::new();
let mut minimized = ~[];
for rpath in rpaths.iter() {
if set.insert(rpath.to_str()) {
if set.insert(rpath.as_slice()) {
minimized.push(rpath.clone());
}
}
@ -162,43 +179,43 @@ mod test {
#[test]
fn test_rpaths_to_flags() {
let flags = rpaths_to_flags([Path("path1"),
Path("path2")]);
let flags = rpaths_to_flags([~"path1", ~"path2"]);
assert_eq!(flags, ~[~"-Wl,-rpath,path1", ~"-Wl,-rpath,path2"]);
}
#[test]
fn test_prefix_rpath() {
let res = get_install_prefix_rpath("triple");
let d = Path(env!("CFG_PREFIX"))
.push_rel(&Path("lib/rustc/triple/lib"));
let mut d = Path::from_str(env!("CFG_PREFIX"));
d.push_str("lib/rustc/triple/lib");
debug2!("test_prefix_path: {} vs. {}",
res.to_str(),
d.to_str());
assert!(res.to_str().ends_with(d.to_str()));
d.display());
assert!(ends_with(res.as_bytes(), d.as_vec()));
fn ends_with(v: &[u8], needle: &[u8]) -> bool {
v.len() >= needle.len() && v.slice_from(v.len()-needle.len()) == needle
}
}
#[test]
fn test_prefix_rpath_abs() {
let res = get_install_prefix_rpath("triple");
assert!(res.is_absolute);
assert!(Path::from_str(res).is_absolute());
}
#[test]
fn test_minimize1() {
let res = minimize_rpaths([Path("rpath1"),
Path("rpath2"),
Path("rpath1")]);
assert_eq!(res, ~[Path("rpath1"), Path("rpath2")]);
let res = minimize_rpaths([~"rpath1", ~"rpath2", ~"rpath1"]);
assert_eq!(res.as_slice(), [~"rpath1", ~"rpath2"]);
}
#[test]
fn test_minimize2() {
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_eq!(res, ~[Path("1a"), Path("2"), Path("4a"), Path("3")]);
let res = minimize_rpaths([~"1a", ~"2", ~"2",
~"1a", ~"4a", ~"1a",
~"2", ~"3", ~"4a",
~"3"]);
assert_eq!(res.as_slice(), [~"1a", ~"2", ~"4a", ~"3"]);
}
#[test]
@ -207,8 +224,8 @@ mod test {
fn test_rpath_relative() {
let o = session::OsLinux;
let res = get_rpath_relative_to_output(o,
&Path("bin/rustc"), &Path("lib/libstd.so"));
assert_eq!(res.to_str(), ~"$ORIGIN/../lib");
&Path::from_str("bin/rustc"), &Path::from_str("lib/libstd.so"));
assert_eq!(res.as_slice(), "$ORIGIN/../lib");
}
#[test]
@ -216,8 +233,8 @@ mod test {
fn test_rpath_relative() {
let o = session::OsFreebsd;
let res = get_rpath_relative_to_output(o,
&Path("bin/rustc"), &Path("lib/libstd.so"));
assert_eq!(res.to_str(), ~"$ORIGIN/../lib");
&Path::from_str("bin/rustc"), &Path::from_str("lib/libstd.so"));
assert_eq!(res.as_slice(), "$ORIGIN/../lib");
}
#[test]
@ -225,18 +242,19 @@ mod test {
fn test_rpath_relative() {
let o = session::OsMacos;
let res = get_rpath_relative_to_output(o,
&Path("bin/rustc"),
&Path("lib/libstd.so"));
assert_eq!(res.to_str(), ~"@executable_path/../lib");
&Path::from_str("bin/rustc"),
&Path::from_str("lib/libstd.so"));
assert_eq!(res.as_slice(), "@executable_path/../lib");
}
#[test]
fn test_get_absolute_rpath() {
let res = get_absolute_rpath(&Path("lib/libstd.so"));
let res = get_absolute_rpath(&Path::from_str("lib/libstd.so"));
let lib = os::make_absolute(&Path::from_str("lib"));
debug2!("test_get_absolute_rpath: {} vs. {}",
res.to_str(),
os::make_absolute(&Path("lib")).to_str());
res.to_str(), lib.display());
assert_eq!(res, os::make_absolute(&Path("lib")));
// FIXME (#9639): This needs to handle non-utf8 paths
assert_eq!(res.as_slice(), lib.as_str().expect("non-utf8 component in path"));
}
}

View File

@ -58,7 +58,8 @@ pub fn anon_src() -> @str { @"<anon>" }
pub fn source_name(input: &input) -> @str {
match *input {
file_input(ref ifile) => ifile.to_str().to_managed(),
// FIXME (#9639): This needs to handle non-utf8 paths
file_input(ref ifile) => ifile.as_str().unwrap().to_managed(),
str_input(_) => anon_src()
}
}
@ -352,7 +353,7 @@ pub fn phase_5_run_llvm_passes(sess: Session,
(sess.opts.output_type == link::output_type_object ||
sess.opts.output_type == link::output_type_exe) {
let output_type = link::output_type_assembly;
let asm_filename = outputs.obj_filename.with_filetype("s");
let asm_filename = outputs.obj_filename.with_extension_str("s");
time(sess.time_passes(), "LLVM passes", (), |_|
link::write::run_passes(sess,
@ -721,7 +722,7 @@ pub fn build_session_options(binary: @str,
} else if matches.opt_present("emit-llvm") {
link::output_type_bitcode
} else { link::output_type_exe };
let sysroot_opt = matches.opt_str("sysroot").map(|m| @Path(m));
let sysroot_opt = matches.opt_str("sysroot").map(|m| @Path::from_str(m));
let target = matches.opt_str("target").unwrap_or(host_triple());
let target_cpu = matches.opt_str("target-cpu").unwrap_or(~"generic");
let target_feature = matches.opt_str("target-feature").unwrap_or(~"");
@ -754,7 +755,7 @@ pub fn build_session_options(binary: @str,
let statik = debugging_opts & session::statik != 0;
let addl_lib_search_paths = matches.opt_strs("L").map(|s| Path(*s));
let addl_lib_search_paths = matches.opt_strs("L").map(|s| Path::from_str(*s));
let linker = matches.opt_str("linker");
let linker_args = matches.opt_strs("link-args").flat_map( |a| {
a.split_iter(' ').map(|arg| arg.to_owned()).collect()
@ -985,7 +986,8 @@ pub fn build_output_filenames(input: &input,
};
let mut stem = match *input {
file_input(ref ifile) => (*ifile).filestem().unwrap().to_managed(),
// FIXME (#9639): This needs to handle non-utf8 paths
file_input(ref ifile) => (*ifile).filestem_str().unwrap().to_managed(),
str_input(_) => @"rust_out"
};
@ -1003,20 +1005,24 @@ pub fn build_output_filenames(input: &input,
}
if *sess.building_library {
out_path = dirpath.push(os::dll_filename(stem));
obj_path = dirpath.push(stem).with_filetype(obj_suffix);
out_path = dirpath.join_str(os::dll_filename(stem));
obj_path = {
let mut p = dirpath.join_str(stem);
p.set_extension_str(obj_suffix);
p
};
} else {
out_path = dirpath.push(stem);
obj_path = dirpath.push(stem).with_filetype(obj_suffix);
out_path = dirpath.join_str(stem);
obj_path = out_path.with_extension_str(obj_suffix);
}
}
Some(ref out_file) => {
out_path = (*out_file).clone();
out_path = out_file.clone();
obj_path = if stop_after_codegen {
(*out_file).clone()
out_file.clone()
} else {
(*out_file).with_filetype(obj_suffix)
out_file.with_extension_str(obj_suffix)
};
if *sess.building_library {

View File

@ -143,14 +143,15 @@ fn visit_view_item(e: @mut Env, i: &ast::view_item) {
let meta_items = match path_opt {
None => meta_items.clone(),
Some((p, _path_str_style)) => {
let p_path = Path(p);
match p_path.filestem() {
let p_path = Path::from_str(p);
match p_path.filestem_str() {
None|Some("") =>
e.diag.span_bug(i.span, "Bad package path in `extern mod` item"),
Some(s) =>
vec::append(
~[attr::mk_name_value_item_str(@"package_id", p),
attr::mk_name_value_item_str(@"name", s.to_managed())],
*meta_items),
None => e.diag.span_bug(i.span, "Bad package path in `extern mod` item")
*meta_items)
}
}
};
@ -274,7 +275,7 @@ fn resolve_crate(e: @mut Env,
};
let (lident, ldata) = loader::load_library_crate(&load_ctxt);
let cfilename = Path(lident);
let cfilename = Path::from_str(lident);
let cdata = ldata;
let attrs = decoder::get_crate_attributes(cdata);

View File

@ -24,10 +24,10 @@ pub enum FileMatch { FileMatches, FileDoesntMatch }
pub type pick<'self> = &'self fn(path: &Path) -> FileMatch;
pub fn pick_file(file: Path, path: &Path) -> Option<Path> {
if path.file_path() == file {
option::Some((*path).clone())
if path.file_path() == Some(file) {
Some(path.clone())
} else {
option::None
None
}
}
@ -60,29 +60,29 @@ pub fn mk_filesearch(maybe_sysroot: &Option<@Path>,
FileMatches => found = true,
FileDoesntMatch => ()
}
visited_dirs.insert(path.to_str());
visited_dirs.insert(path.as_vec().to_owned());
}
debug2!("filesearch: searching target lib path");
let tlib_path = make_target_lib_path(self.sysroot,
self.target_triple);
if !visited_dirs.contains(&tlib_path.to_str()) {
if !visited_dirs.contains_equiv(&tlib_path.as_vec()) {
match f(&tlib_path) {
FileMatches => found = true,
FileDoesntMatch => ()
}
}
visited_dirs.insert(tlib_path.to_str());
visited_dirs.insert(tlib_path.as_vec().to_owned());
// Try RUST_PATH
if !found {
let rustpath = rust_path();
for path in rustpath.iter() {
let tlib_path = make_rustpkg_target_lib_path(path, self.target_triple);
debug2!("is {} in visited_dirs? {:?}", tlib_path.to_str(),
visited_dirs.contains(&tlib_path.to_str()));
debug2!("is {} in visited_dirs? {:?}", tlib_path.display(),
visited_dirs.contains_equiv(&tlib_path.as_vec().to_owned()));
if !visited_dirs.contains(&tlib_path.to_str()) {
visited_dirs.insert(tlib_path.to_str());
if !visited_dirs.contains_equiv(&tlib_path.as_vec()) {
visited_dirs.insert(tlib_path.as_vec().to_owned());
// Don't keep searching the RUST_PATH if one match turns up --
// if we did, we'd get a "multiple matching crates" error
match f(&tlib_path) {
@ -99,12 +99,14 @@ pub fn mk_filesearch(maybe_sysroot: &Option<@Path>,
make_target_lib_path(self.sysroot, self.target_triple)
}
fn get_target_lib_file_path(&self, file: &Path) -> Path {
self.get_target_lib_path().push_rel(file)
let mut p = self.get_target_lib_path();
p.push_path(file);
p
}
}
let sysroot = get_sysroot(maybe_sysroot);
debug2!("using sysroot = {}", sysroot.to_str());
debug2!("using sysroot = {}", sysroot.display());
@FileSearchImpl {
sysroot: sysroot,
addl_lib_search_paths: addl_lib_search_paths,
@ -114,19 +116,19 @@ pub fn mk_filesearch(maybe_sysroot: &Option<@Path>,
pub fn search(filesearch: @FileSearch, pick: pick) {
do filesearch.for_each_lib_search_path() |lib_search_path| {
debug2!("searching {}", lib_search_path.to_str());
debug2!("searching {}", lib_search_path.display());
let r = os::list_dir_path(lib_search_path);
let mut rslt = FileDoesntMatch;
for path in r.iter() {
debug2!("testing {}", path.to_str());
debug2!("testing {}", path.display());
let maybe_picked = pick(path);
match maybe_picked {
FileMatches => {
debug2!("picked {}", path.to_str());
debug2!("picked {}", path.display());
rslt = FileMatches;
}
FileDoesntMatch => {
debug2!("rejected {}", path.to_str());
debug2!("rejected {}", path.display());
}
}
}
@ -135,24 +137,30 @@ pub fn search(filesearch: @FileSearch, pick: pick) {
}
pub fn relative_target_lib_path(target_triple: &str) -> Path {
Path(libdir()).push_many([~"rustc",
target_triple.to_owned(),
libdir()])
let dir = libdir();
let mut p = Path::from_str(dir);
assert!(p.is_relative());
p.push_str("rustc");
p.push_str(target_triple);
p.push_str(dir);
p
}
fn make_target_lib_path(sysroot: &Path,
target_triple: &str) -> Path {
sysroot.push_rel(&relative_target_lib_path(target_triple))
sysroot.join_path(&relative_target_lib_path(target_triple))
}
fn make_rustpkg_target_lib_path(dir: &Path,
target_triple: &str) -> Path {
dir.push_rel(&Path(libdir()).push(target_triple.to_owned()))
let mut p = dir.join_str(libdir());
p.push_str(target_triple);
p
}
pub fn get_or_default_sysroot() -> Path {
match os::self_exe_path() {
option::Some(ref p) => (*p).pop(),
option::Some(p) => { let mut p = p; p.pop(); p }
option::None => fail2!("can't determine value for sysroot")
}
}
@ -184,13 +192,13 @@ pub fn rust_path() -> ~[Path] {
Some(env_path) => {
let env_path_components: ~[&str] =
env_path.split_str_iter(PATH_ENTRY_SEPARATOR).collect();
env_path_components.map(|&s| Path(s))
env_path_components.map(|&s| Path::from_str(s))
}
None => ~[]
};
let cwd = os::getcwd();
// now add in default entries
let cwd_dot_rust = cwd.push(".rust");
let cwd_dot_rust = cwd.join_str(".rust");
if !env_rust_path.contains(&cwd_dot_rust) {
env_rust_path.push(cwd_dot_rust);
}
@ -198,13 +206,14 @@ pub fn rust_path() -> ~[Path] {
env_rust_path.push(cwd.clone());
}
do cwd.each_parent() |p| {
if !env_rust_path.contains(&p.push(".rust")) {
if !env_rust_path.contains(&p.join_str(".rust")) {
push_if_exists(&mut env_rust_path, p);
}
}
true
};
let h = os::homedir();
for h in h.iter() {
if !env_rust_path.contains(&h.push(".rust")) {
if !env_rust_path.contains(&h.join_str(".rust")) {
push_if_exists(&mut env_rust_path, h);
}
}
@ -214,7 +223,7 @@ pub fn rust_path() -> ~[Path] {
/// Adds p/.rust into vec, only if it exists
fn push_if_exists(vec: &mut ~[Path], p: &Path) {
let maybe_dir = p.push(".rust");
let maybe_dir = p.join_str(".rust");
if os::path_exists(&maybe_dir) {
vec.push(maybe_dir);
}

View File

@ -93,25 +93,27 @@ fn find_library_crate_aux(
let prefix = format!("{}{}-", prefix, crate_name);
let mut matches = ~[];
filesearch::search(filesearch, |path| -> FileMatch {
let path_str = path.filename();
// FIXME (#9639): This needs to handle non-utf8 paths
let path_str = path.filename_str();
match path_str {
None => FileDoesntMatch,
Some(path_str) =>
if path_str.starts_with(prefix) && path_str.ends_with(suffix) {
debug2!("{} is a candidate", path.to_str());
debug2!("{} is a candidate", path.display());
match get_metadata_section(cx.os, path) {
Some(cvec) =>
if !crate_matches(cvec, cx.metas, cx.hash) {
debug2!("skipping {}, metadata doesn't match",
path.to_str());
path.display());
FileDoesntMatch
} else {
debug2!("found {} with matching metadata", path.to_str());
matches.push((path.to_str(), cvec));
debug2!("found {} with matching metadata", path.display());
// FIXME (#9639): This needs to handle non-utf8 paths
matches.push((path.as_str().unwrap().to_owned(), cvec));
FileMatches
},
_ => {
debug2!("could not load metadata for {}", path.to_str());
debug2!("could not load metadata for {}", path.display());
FileDoesntMatch
}
}
@ -273,7 +275,7 @@ pub fn list_file_metadata(intr: @ident_interner,
match get_metadata_section(os, path) {
option::Some(bytes) => decoder::list_crate_metadata(intr, bytes, out),
option::None => {
out.write_str(format!("could not find metadata in {}.\n", path.to_str()))
out.write_str(format!("could not find metadata in {}.\n", path.display()))
}
}
}

View File

@ -859,7 +859,8 @@ fn compile_unit_metadata(cx: @mut CrateContext) {
debug2!("compile_unit_metadata: {:?}", crate_name);
let work_dir = cx.sess.working_dir.to_str();
// FIXME (#9639): This needs to handle non-utf8 paths
let work_dir = cx.sess.working_dir.as_str().unwrap();
let producer = format!("rustc version {}", env!("CFG_VERSION"));
do crate_name.with_c_str |crate_name| {
@ -969,7 +970,8 @@ fn file_metadata(cx: &mut CrateContext, full_path: &str) -> DIFile {
debug2!("file_metadata: {}", full_path);
let work_dir = cx.sess.working_dir.to_str();
// FIXME (#9639): This needs to handle non-utf8 paths
let work_dir = cx.sess.working_dir.as_str().unwrap();
let file_name =
if full_path.starts_with(work_dir) {
full_path.slice(work_dir.len() + 1u, full_path.len())

View File

@ -250,7 +250,7 @@ pub fn run_compiler(args: &[~str], demitter: @diagnostic::Emitter) {
let src = str::from_utf8(io::stdin().read_whole_stream());
str_input(src.to_managed())
} else {
file_input(Path(ifile))
file_input(Path::from_str(ifile))
}
}
_ => early_error(demitter, "multiple input filenames provided")
@ -258,8 +258,8 @@ pub fn run_compiler(args: &[~str], demitter: @diagnostic::Emitter) {
let sopts = build_session_options(binary, matches, demitter);
let sess = build_session(sopts, demitter);
let odir = matches.opt_str("out-dir").map(|o| Path(o));
let ofile = matches.opt_str("o").map(|o| Path(o));
let odir = matches.opt_str("out-dir").map(|o| Path::from_str(o));
let ofile = matches.opt_str("o").map(|o| Path::from_str(o));
let cfg = build_configuration(sess);
let pretty = do matches.opt_default("pretty", "normal").map |a| {
parse_pretty(sess, a)

View File

@ -39,7 +39,7 @@ fn get_ast_and_resolve(cpath: &Path, libs: ~[Path]) -> DocContext {
let sessopts = @driver::session::options {
binary: @"rustdoc",
maybe_sysroot: Some(@os::self_exe_path().unwrap().pop()),
maybe_sysroot: Some(@os::self_exe_path().unwrap().dir_path()),
addl_lib_search_paths: @mut libs,
.. (*rustc::driver::session::basic_options()).clone()
};

View File

@ -47,7 +47,6 @@ use std::rt::io::Reader;
use std::str;
use std::task;
use std::unstable::finally::Finally;
use std::util;
use std::vec;
use extra::arc::RWArc;
@ -256,16 +255,16 @@ pub fn run(mut crate: clean::Crate, dst: Path) {
crate = cache.fold_crate(crate);
// Add all the static files
let dst = cx.dst.push(crate.name);
let mut dst = cx.dst.join_str(crate.name);
mkdir(&dst);
write(dst.push("jquery.js"), include_str!("static/jquery-2.0.3.min.js"));
write(dst.push("main.js"), include_str!("static/main.js"));
write(dst.push("main.css"), include_str!("static/main.css"));
write(dst.push("normalize.css"), include_str!("static/normalize.css"));
write(dst.join_str("jquery.js"), include_str!("static/jquery-2.0.3.min.js"));
write(dst.join_str("main.js"), include_str!("static/main.js"));
write(dst.join_str("main.css"), include_str!("static/main.css"));
write(dst.join_str("normalize.css"), include_str!("static/normalize.css"));
// Publish the search index
{
let dst = dst.push("search-index.js");
dst.push_str("search-index.js");
let mut w = BufferedWriter::new(dst.open_writer(io::CreateOrTruncate));
let w = &mut w as &mut io::Writer;
write!(w, "var searchIndex = [");
@ -293,9 +292,9 @@ pub fn run(mut crate: clean::Crate, dst: Path) {
// Render all source files (this may turn into a giant no-op)
{
info2!("emitting source files");
let dst = cx.dst.push("src");
let dst = cx.dst.join_str("src");
mkdir(&dst);
let dst = dst.push(crate.name);
let dst = dst.join_str(crate.name);
mkdir(&dst);
let mut folder = SourceCollector {
dst: dst,
@ -325,7 +324,7 @@ fn write(dst: Path, contents: &str) {
fn mkdir(path: &Path) {
do io::io_error::cond.trap(|err| {
error2!("Couldn't create directory `{}`: {}",
path.to_str(), err.desc);
path.display(), err.desc);
fail2!()
}).inside {
if !path.is_dir() {
@ -335,18 +334,18 @@ fn mkdir(path: &Path) {
}
/// Takes a path to a source file and cleans the path to it. This canonicalizes
/// things like "." and ".." to components which preserve the "top down"
/// hierarchy of a static HTML tree.
fn clean_srcpath(src: &str, f: &fn(&str)) {
let p = Path(src);
for c in p.components.iter() {
if "." == *c {
continue
}
if ".." == *c {
f("up");
} else {
f(c.as_slice())
/// things like ".." to components which preserve the "top down" hierarchy of a
/// static HTML tree.
// FIXME (#9639): The closure should deal with &[u8] instead of &str
fn clean_srcpath(src: &[u8], f: &fn(&str)) {
let p = Path::from_vec(src);
if p.as_vec() != bytes!(".") {
for c in p.str_component_iter().map(|x|x.unwrap()) {
if ".." == c {
f("up");
} else {
f(c.as_slice())
}
}
}
}
@ -355,7 +354,7 @@ fn clean_srcpath(src: &str, f: &fn(&str)) {
/// rendering in to the specified source destination.
fn extern_location(e: &clean::ExternalCrate, dst: &Path) -> ExternalLocation {
// See if there's documentation generated into the local directory
let local_location = dst.push(e.name);
let local_location = dst.join_str(e.name);
if local_location.is_dir() {
return Local;
}
@ -414,7 +413,7 @@ impl<'self> DocFolder for SourceCollector<'self> {
impl<'self> SourceCollector<'self> {
/// Renders the given filename into its corresponding HTML source file.
fn emit_source(&mut self, filename: &str) -> bool {
let p = Path(filename);
let p = Path::from_str(filename);
// Read the contents of the file
let mut contents = ~[];
@ -445,17 +444,17 @@ impl<'self> SourceCollector<'self> {
// Create the intermediate directories
let mut cur = self.dst.clone();
let mut root_path = ~"../../";
do clean_srcpath(p.pop().to_str()) |component| {
cur = cur.push(component);
do clean_srcpath(p.dirname()) |component| {
cur.push_str(component);
mkdir(&cur);
root_path.push_str("../");
}
let dst = cur.push(*p.components.last() + ".html");
let w = dst.open_writer(io::CreateOrTruncate);
cur.push(p.filename().expect("source has no filename") + bytes!(".html"));
let w = cur.open_writer(io::CreateOrTruncate);
let mut w = BufferedWriter::new(w);
let title = format!("{} -- source", *dst.components.last());
let title = cur.with_filename_display_str(|s| format!("{} -- source", s.unwrap()));
let page = layout::Page {
title: title,
ty: "source",
@ -661,8 +660,8 @@ impl Context {
if s.len() == 0 {
fail2!("what {:?}", self);
}
let next = self.dst.push(s);
let prev = util::replace(&mut self.dst, next);
let prev = self.dst.clone();
self.dst.push_str(s);
self.root_path.push_str("../");
self.current.push(s);
@ -809,7 +808,7 @@ impl Context {
let item = Cell::new(item);
do self.recurse(name) |this| {
let item = item.take();
let dst = this.dst.push("index.html");
let dst = this.dst.join_str("index.html");
let writer = dst.open_writer(io::CreateOrTruncate);
render(writer.unwrap(), this, &item, false);
@ -827,7 +826,7 @@ impl Context {
// Things which don't have names (like impls) don't get special
// pages dedicated to them.
_ if item.name.is_some() => {
let dst = self.dst.push(item_path(&item));
let dst = self.dst.join_str(item_path(&item));
let writer = dst.open_writer(io::CreateOrTruncate);
render(writer.unwrap(), self, &item, true);
}
@ -881,7 +880,7 @@ impl<'self> fmt::Default for Item<'self> {
if it.cx.include_sources {
let mut path = ~[];
do clean_srcpath(it.item.source.filename) |component| {
do clean_srcpath(it.item.source.filename.as_bytes()) |component| {
path.push(component.to_owned());
}
let href = if it.item.source.loline == it.item.source.hiline {

View File

@ -41,7 +41,7 @@ impl PluginManager {
/// platform. On windows, it turns into name.dll, on OS X, name.dylib, and
/// elsewhere, libname.so.
pub fn load_plugin(&mut self, name: ~str) {
let x = self.prefix.push(libname(name));
let x = self.prefix.join_str(libname(name));
let lib_result = dl::DynamicLibrary::open(Some(&x));
let lib = lib_result.unwrap();
let plugin = unsafe { lib.symbol("rustdoc_plugin_entrypoint") }.unwrap();

View File

@ -134,13 +134,13 @@ pub fn main_args(args: &[~str]) -> int {
info2!("going to format");
let started = time::precise_time_ns();
let output = matches.opt_str("o").map(|s| Path(s));
let output = matches.opt_str("o").map(|s| Path::from_str(s));
match matches.opt_str("w") {
Some(~"html") | None => {
html::render::run(crate, output.unwrap_or(Path("doc")))
html::render::run(crate, output.unwrap_or(Path::from_str("doc")))
}
Some(~"json") => {
json_output(crate, res, output.unwrap_or(Path("doc.json")))
json_output(crate, res, output.unwrap_or(Path::from_str("doc.json")))
}
Some(s) => {
println!("unknown output format: {}", s);
@ -188,8 +188,8 @@ fn rust_input(cratefile: &str, matches: &getopts::Matches) -> Output {
let mut plugins = matches.opt_strs("plugins");
// First, parse the crate and extract all relevant information.
let libs = Cell::new(matches.opt_strs("L").map(|s| Path(*s)));
let cr = Cell::new(Path(cratefile));
let libs = Cell::new(matches.opt_strs("L").map(|s| Path::from_str(*s)));
let cr = Cell::new(Path::from_str(cratefile));
info2!("starting to run rustc");
let crate = do std::task::try {
let cr = cr.take();
@ -230,7 +230,7 @@ fn rust_input(cratefile: &str, matches: &getopts::Matches) -> Output {
// Load all plugins/passes into a PluginManager
let path = matches.opt_str("plugin-path").unwrap_or(~"/tmp/rustdoc_ng/plugins");
let mut pm = plugins::PluginManager::new(Path(path));
let mut pm = plugins::PluginManager::new(Path::from_str(path));
for pass in passes.iter() {
let plugin = match PASSES.iter().position(|&(p, _, _)| p == *pass) {
Some(i) => PASSES[i].n1(),
@ -254,7 +254,7 @@ fn rust_input(cratefile: &str, matches: &getopts::Matches) -> Output {
/// This input format purely deserializes the json output file. No passes are
/// run over the deserialized output.
fn json_input(input: &str) -> Result<Output, ~str> {
let input = match ::std::io::file_reader(&Path(input)) {
let input = match ::std::io::file_reader(&Path::from_str(input)) {
Ok(i) => i,
Err(s) => return Err(s),
};

View File

@ -142,7 +142,7 @@ fn run(mut program: ~Program, binary: ~str, lib_search_paths: ~[~str],
let options = @session::options {
crate_type: session::unknown_crate,
binary: binary,
addl_lib_search_paths: @mut lib_search_paths.map(|p| Path(*p)),
addl_lib_search_paths: @mut lib_search_paths.map(|p| Path::from_str(*p)),
jit: true,
.. (*session::basic_options()).clone()
};
@ -315,8 +315,20 @@ fn run(mut program: ~Program, binary: ~str, lib_search_paths: ~[~str],
// because it already exists and is newer than the source file, or
// None if there were compile errors.
fn compile_crate(src_filename: ~str, binary: ~str) -> Option<bool> {
fn has_prefix(v: &[u8], pref: &[u8]) -> bool {
v.len() >= pref.len() && v.slice_to(pref.len()) == pref
}
fn has_extension(v: &[u8], ext: Option<&[u8]>) -> bool {
match ext {
None => true,
Some(ext) => {
v.len() > ext.len() && v[v.len()-ext.len()-1] == '.' as u8 &&
v.slice_from(v.len()-ext.len()) == ext
}
}
}
match do task::try {
let src_path = Path(src_filename);
let src_path = Path::from_str(src_filename);
let binary = binary.to_managed();
let options = @session::options {
binary: binary,
@ -334,7 +346,7 @@ fn compile_crate(src_filename: ~str, binary: ~str) -> Option<bool> {
// If the library already exists and is newer than the source
// file, skip compilation and return None.
let mut should_compile = true;
let dir = os::list_dir_path(&Path(outputs.out_filename.dirname()));
let dir = os::list_dir_path(&outputs.out_filename.dir_path());
let maybe_lib_path = do dir.iter().find |file| {
// The actual file's name has a hash value and version
// number in it which is unknown at this time, so looking
@ -342,9 +354,9 @@ fn compile_crate(src_filename: ~str, binary: ~str) -> Option<bool> {
// instead we guess which file is the library by matching
// the prefix and suffix of out_filename to files in the
// directory.
let file_str = file.filename().unwrap();
file_str.starts_with(outputs.out_filename.filestem().unwrap())
&& file_str.ends_with(outputs.out_filename.filetype().unwrap())
let file_vec = file.filename().unwrap();
has_prefix(file_vec, outputs.out_filename.filestem().unwrap()) &&
has_extension(file_vec, outputs.out_filename.extension())
};
match maybe_lib_path {
Some(lib_path) => {
@ -429,11 +441,12 @@ fn run_cmd(repl: &mut Repl, _in: @io::Reader, _out: @io::Writer,
}
}
for crate in loaded_crates.iter() {
let crate_path = Path(*crate);
let crate_dir = crate_path.dirname();
let crate_path = Path::from_str(*crate);
// FIXME (#9639): This needs to handle non-utf8 paths
let crate_dir = crate_path.dirname_str().unwrap();
repl.program.record_extern(format!("extern mod {};", *crate));
if !repl.lib_search_paths.iter().any(|x| x == &crate_dir) {
repl.lib_search_paths.push(crate_dir);
if !repl.lib_search_paths.iter().any(|x| crate_dir == *x) {
repl.lib_search_paths.push(crate_dir.to_owned());
}
}
if loaded_crates.is_empty() {

View File

@ -43,18 +43,18 @@ pub fn new_default_context(c: workcache::Context, p: Path) -> BuildContext {
}
fn file_is_fresh(path: &str, in_hash: &str) -> bool {
let path = Path(path);
let path = Path::from_str(path);
os::path_exists(&path) && in_hash == digest_file_with_date(&path)
}
fn binary_is_fresh(path: &str, in_hash: &str) -> bool {
let path = Path(path);
let path = Path::from_str(path);
os::path_exists(&path) && in_hash == digest_only_date(&path)
}
pub fn new_workcache_context(p: &Path) -> workcache::Context {
let db_file = p.push("rustpkg_db.json"); // ??? probably wrong
debug2!("Workcache database file: {}", db_file.to_str());
let db_file = p.join_str("rustpkg_db.json"); // ??? probably wrong
debug2!("Workcache database file: {}", db_file.display());
let db = RWArc::new(Database::new(db_file));
let lg = RWArc::new(Logger::new());
let cfg = Arc::new(TreeMap::new());
@ -73,7 +73,7 @@ pub fn build_lib(sysroot: Path, root: Path, name: ~str, version: Version,
source_workspace: root.clone(),
build_in_destination: false,
destination_workspace: root.clone(),
start_dir: root.push("src").push(name),
start_dir: root.join_many_str(["src", name.as_slice()]),
id: PkgId{ version: version, ..PkgId::new(name)},
// n.b. This assumes the package only has one crate
libs: ~[mk_crate(lib)],
@ -91,7 +91,7 @@ pub fn build_exe(sysroot: Path, root: Path, name: ~str, version: Version,
source_workspace: root.clone(),
build_in_destination: false,
destination_workspace: root.clone(),
start_dir: root.push("src").push(name),
start_dir: root.join_many_str(["src", name.as_slice()]),
id: PkgId{ version: version, ..PkgId::new(name)},
libs: ~[],
// n.b. This assumes the package only has one crate

View File

@ -123,7 +123,7 @@ impl Context {
/// Debugging
pub fn sysroot_str(&self) -> ~str {
self.sysroot.to_str()
self.sysroot.as_str().unwrap().to_owned()
}
// Hack so that rustpkg can run either out of a rustc target dir,
@ -132,7 +132,11 @@ impl Context {
if !in_target(&self.sysroot) {
self.sysroot.clone()
} else {
self.sysroot.pop().pop().pop()
let mut p = self.sysroot.clone();
p.pop();
p.pop();
p.pop();
p
}
}
@ -150,8 +154,10 @@ impl Context {
/// rustpkg from a Rust target directory. This is part of a
/// kludgy hack used to adjust the sysroot.
pub fn in_target(sysroot: &Path) -> bool {
debug2!("Checking whether {} is in target", sysroot.to_str());
os::path_is_dir(&sysroot.pop().pop().push("rustc"))
debug2!("Checking whether {} is in target", sysroot.display());
let mut p = sysroot.dir_path();
p.set_filename_str("rustc");
os::path_is_dir(&p)
}
impl RustcFlags {

View File

@ -17,27 +17,33 @@ use std::os;
pub fn list_installed_packages(f: &fn(&PkgId) -> bool) -> bool {
let workspaces = rust_path();
for p in workspaces.iter() {
let binfiles = os::list_dir(&p.push("bin"));
let binfiles = os::list_dir(&p.join_str("bin"));
for exec in binfiles.iter() {
let p = Path(*exec);
let exec_path = p.filestem();
do exec_path.iter().advance |s| {
f(&PkgId::new(*s))
};
// FIXME (#9639): This needs to handle non-utf8 paths
match exec.filestem_str() {
None => (),
Some(exec_path) => {
if !f(&PkgId::new(exec_path)) {
return false;
}
}
}
}
let libfiles = os::list_dir(&p.push("lib"));
let libfiles = os::list_dir(&p.join_str("lib"));
for lib in libfiles.iter() {
let lib = Path(*lib);
debug2!("Full name: {}", lib.to_str());
match has_library(&lib) {
debug2!("Full name: {}", lib.display());
match has_library(lib) {
Some(basename) => {
let parent = p.join_str("lib");
debug2!("parent = {}, child = {}",
p.push("lib").to_str(), lib.to_str());
let rel_p = p.push("lib/").get_relative_to(&lib);
debug2!("Rel: {}", rel_p.to_str());
let rel_path = rel_p.push(basename).to_str();
debug2!("Rel name: {}", rel_path);
f(&PkgId::new(rel_path));
parent.display(), lib.display());
let rel_p = lib.path_relative_from(&parent).unwrap();
debug2!("Rel: {}", rel_p.display());
let rel_path = rel_p.join_str(basename);
do rel_path.with_display_str |s| {
debug2!("Rel name: {}", s);
f(&PkgId::new(s));
}
}
None => ()
}
@ -48,10 +54,9 @@ pub fn list_installed_packages(f: &fn(&PkgId) -> bool) -> bool {
pub fn has_library(p: &Path) -> Option<~str> {
let files = os::list_dir(p);
for q in files.iter() {
let as_path = Path(*q);
if as_path.filetype() == Some(os::consts::DLL_SUFFIX) {
let stuff : &str = as_path.filestem().expect("has_library: weird path");
for path in files.iter() {
if path.extension_str() == Some(os::consts::DLL_EXTENSION) {
let stuff : &str = path.filestem_str().expect("has_library: weird path");
let mut stuff2 = stuff.split_str_iter(&"-");
let stuff3: ~[&str] = stuff2.collect();
// argh
@ -67,8 +72,10 @@ pub fn package_is_installed(p: &PkgId) -> bool {
do list_installed_packages() |installed| {
if installed == p {
is_installed = true;
false
} else {
true
}
false
};
is_installed
}

View File

@ -59,14 +59,14 @@ impl PkgId {
}
};
let path = Path(s);
if path.is_absolute {
let path = Path::from_str(s);
if !path.is_relative() {
return cond.raise((path, ~"absolute pkgid"));
}
if path.components.len() < 1 {
if path.filename().is_none() {
return cond.raise((path, ~"0-length pkgid"));
}
let short_name = path.filestem().expect(format!("Strange path! {}", s));
let short_name = path.filestem_str().expect(format!("Strange path! {}", s));
let version = match given_version {
Some(v) => v,
@ -87,9 +87,11 @@ impl PkgId {
}
pub fn hash(&self) -> ~str {
format!("{}-{}-{}", self.path.to_str(),
hash(self.path.to_str() + self.version.to_str()),
self.version.to_str())
// FIXME (#9639): hash should take a &[u8] so we can hash the real path
do self.path.with_display_str |s| {
let vers = self.version.to_str();
format!("{}-{}-{}", s, hash(s + vers), vers)
}
}
pub fn short_name_with_version(&self) -> ~str {
@ -98,7 +100,7 @@ impl PkgId {
/// True if the ID has multiple components
pub fn is_complex(&self) -> bool {
self.short_name != self.path.to_str()
self.short_name.as_bytes() != self.path.as_vec()
}
pub fn prefixes_iter(&self) -> Prefixes {
@ -115,7 +117,7 @@ impl PkgId {
pub fn prefixes_iter(p: &Path) -> Prefixes {
Prefixes {
components: p.components().to_owned(),
components: p.str_component_iter().map(|x|x.unwrap().to_owned()).to_owned_vec(),
remaining: ~[]
}
}
@ -133,9 +135,10 @@ impl Iterator<(Path, Path)> for Prefixes {
}
else {
let last = self.components.pop();
self.remaining.push(last);
self.remaining.unshift(last);
// converting to str and then back is a little unfortunate
Some((Path(self.components.to_str()), Path(self.remaining.to_str())))
Some((Path::from_str(self.components.connect("/")),
Path::from_str(self.remaining.connect("/"))))
}
}
}
@ -143,7 +146,7 @@ impl Iterator<(Path, Path)> for Prefixes {
impl ToStr for PkgId {
fn to_str(&self) -> ~str {
// should probably use the filestem and not the whole path
format!("{}-{}", self.path.to_str(), self.version.to_str())
format!("{}-{}", self.path.as_str().unwrap(), self.version.to_str())
}
}

View File

@ -58,9 +58,9 @@ impl ToStr for PkgSrc {
fn to_str(&self) -> ~str {
format!("Package ID {} in start dir {} [workspaces = {} -> {}]",
self.id.to_str(),
self.start_dir.to_str(),
self.source_workspace.to_str(),
self.destination_workspace.to_str())
self.start_dir.display(),
self.source_workspace.display(),
self.destination_workspace.display())
}
}
condition! {
@ -79,8 +79,8 @@ impl PkgSrc {
debug2!("Checking package source for package ID {}, \
workspace = {} -> {}, use_rust_path_hack = {:?}",
id.to_str(),
source_workspace.to_str(),
destination_workspace.to_str(),
source_workspace.display(),
destination_workspace.display(),
use_rust_path_hack);
let mut destination_workspace = destination_workspace.clone();
@ -94,22 +94,27 @@ impl PkgSrc {
} else {
// We search for sources under both src/ and build/ , because build/ is where
// automatically-checked-out sources go.
let result = source_workspace.push("src").push_rel(&id.path.pop()).push(format!("{}-{}",
id.short_name, id.version.to_str()));
let mut result = source_workspace.join_str("src");
result.push_path(&id.path.dir_path());
result.push_str(format!("{}-{}", id.short_name, id.version.to_str()));
to_try.push(result);
let mut result = source_workspace.join_str("src");
result.push_path(&id.path);
to_try.push(result);
to_try.push(source_workspace.push("src").push_rel(&id.path));
let result = build_dir.push("src").push_rel(&id.path.pop()).push(format!("{}-{}",
id.short_name, id.version.to_str()));
let mut result = build_dir.join_str("src");
result.push_path(&id.path.dir_path());
result.push_str(format!("{}-{}", id.short_name, id.version.to_str()));
to_try.push(result.clone());
output_names.push(result);
let other_result = build_dir.push("src").push_rel(&id.path);
let mut other_result = build_dir.join_str("src");
other_result.push_path(&id.path);
to_try.push(other_result.clone());
output_names.push(other_result);
}
debug2!("Checking dirs: {:?}", to_try.map(|s| s.to_str()).connect(":"));
debug2!("Checking dirs: {:?}", to_try.map(|p| p.to_display_str()).connect(":"));
let path = to_try.iter().find(|&d| os::path_exists(d));
@ -123,14 +128,14 @@ impl PkgSrc {
// See if any of the prefixes of this package ID form a valid package ID
// That is, is this a package ID that points into the middle of a workspace?
for (prefix, suffix) in id.prefixes_iter() {
let package_id = PkgId::new(prefix.to_str());
let path = build_dir.push_rel(&package_id.path);
debug2!("in loop: checking if {} is a directory", path.to_str());
let package_id = PkgId::new(prefix.as_str().unwrap());
let path = build_dir.join_path(&package_id.path);
debug2!("in loop: checking if {} is a directory", path.display());
if os::path_is_dir(&path) {
let ps = PkgSrc::new(source_workspace,
destination_workspace,
use_rust_path_hack,
PkgId::new(prefix.to_str()));
package_id);
match ps {
PkgSrc {
source_workspace: source,
@ -141,7 +146,7 @@ impl PkgSrc {
source_workspace: source.clone(),
build_in_destination: build_in_destination,
destination_workspace: destination,
start_dir: start.push_rel(&suffix),
start_dir: start.join_path(&suffix),
id: id,
libs: ~[],
mains: ~[],
@ -159,7 +164,7 @@ impl PkgSrc {
// Ok, no prefixes work, so try fetching from git
let mut ok_d = None;
for w in output_names.iter() {
debug2!("Calling fetch_git on {}", w.to_str());
debug2!("Calling fetch_git on {}", w.display());
let target_dir_opt = PkgSrc::fetch_git(w, &id);
for p in target_dir_opt.iter() {
ok_d = Some(p.clone());
@ -209,9 +214,9 @@ impl PkgSrc {
}
};
debug2!("3. build_in_destination = {:?}", build_in_destination);
debug2!("source: {} dest: {}", source_workspace.to_str(), destination_workspace.to_str());
debug2!("source: {} dest: {}", source_workspace.display(), destination_workspace.display());
debug2!("For package id {}, returning {}", id.to_str(), dir.to_str());
debug2!("For package id {}, returning {}", id.to_str(), dir.display());
if !os::path_is_dir(&dir) {
cond.raise((id.clone(), ~"supplied path for package dir is a \
@ -240,8 +245,8 @@ impl PkgSrc {
use conditions::git_checkout_failed::cond;
debug2!("Checking whether {} (path = {}) exists locally. Cwd = {}, does it? {:?}",
pkgid.to_str(), pkgid.path.to_str(),
os::getcwd().to_str(),
pkgid.to_str(), pkgid.path.display(),
os::getcwd().display(),
os::path_exists(&pkgid.path));
match safe_git_clone(&pkgid.path, &pkgid.version, local) {
@ -250,14 +255,14 @@ impl PkgSrc {
Some(local.clone())
}
DirToUse(clone_target) => {
if pkgid.path.components().len() < 2 {
if pkgid.path.component_iter().nth(1).is_none() {
// If a non-URL, don't bother trying to fetch
return None;
}
let url = format!("https://{}", pkgid.path.to_str());
let url = format!("https://{}", pkgid.path.as_str().unwrap());
debug2!("Fetching package: git clone {} {} [version={}]",
url, clone_target.to_str(), pkgid.version.to_str());
url, clone_target.display(), pkgid.version.to_str());
let mut failed = false;
@ -273,7 +278,7 @@ impl PkgSrc {
// Move clone_target to local.
// First, create all ancestor directories.
let moved = make_dir_rwx_recursive(&local.pop())
let moved = make_dir_rwx_recursive(&local.dir_path())
&& os::rename_file(&clone_target, local);
if moved { Some(local.clone()) }
else { None }
@ -284,28 +289,31 @@ impl PkgSrc {
// If a file named "pkg.rs" in the start directory exists,
// return the path for it. Otherwise, None
pub fn package_script_option(&self) -> Option<Path> {
let maybe_path = self.start_dir.push("pkg.rs");
debug2!("package_script_option: checking whether {} exists", maybe_path.to_str());
let maybe_path = self.start_dir.join_str("pkg.rs");
debug2!("package_script_option: checking whether {} exists", maybe_path.display());
if os::path_exists(&maybe_path) {
Some(maybe_path)
}
else {
} else {
None
}
}
/// True if the given path's stem is self's pkg ID's stem
fn stem_matches(&self, p: &Path) -> bool {
p.filestem().map_default(false, |p| { p == self.id.short_name.as_slice() })
p.filestem().map_default(false, |p| { p == self.id.short_name.as_bytes() })
}
pub fn push_crate(cs: &mut ~[Crate], prefix: uint, p: &Path) {
assert!(p.components.len() > prefix);
let mut sub = Path("");
for c in p.components.slice(prefix, p.components.len()).iter() {
sub = sub.push(*c);
let mut it = p.component_iter().peekable();
if prefix > 0 {
it.nth(prefix-1); // skip elements
}
debug2!("Will compile crate {}", sub.to_str());
assert!(it.peek().is_some());
let mut sub = Path::from_str(".");
for c in it {
sub.push(c);
}
debug2!("Will compile crate {}", sub.display());
cs.push(Crate::new(&sub));
}
@ -318,10 +326,10 @@ impl PkgSrc {
pub fn find_crates_with_filter(&mut self, filter: &fn(&str) -> bool) {
use conditions::missing_pkg_files::cond;
let prefix = self.start_dir.components.len();
let prefix = self.start_dir.component_iter().len();
debug2!("Matching against {}", self.id.short_name);
do os::walk_dir(&self.start_dir) |pth| {
let maybe_known_crate_set = match pth.filename() {
let maybe_known_crate_set = match pth.filename_str() {
Some(filename) if filter(filename) => match filename {
"lib.rs" => Some(&mut self.libs),
"main.rs" => Some(&mut self.mains),
@ -349,7 +357,7 @@ impl PkgSrc {
}
debug2!("In {}, found {} libs, {} mains, {} tests, {} benchs",
self.start_dir.to_str(),
self.start_dir.display(),
self.libs.len(),
self.mains.len(),
self.tests.len(),
@ -362,18 +370,17 @@ impl PkgSrc {
cfgs: &[~str],
what: OutputType) {
for crate in crates.iter() {
let path = self.start_dir.push_rel(&crate.file).normalize();
debug2!("build_crates: compiling {}", path.to_str());
let path_str = path.to_str();
let path = self.start_dir.join_path(&crate.file);
debug2!("build_crates: compiling {}", path.display());
let cfgs = crate.cfgs + cfgs;
do ctx.workcache_context.with_prep(crate_tag(&path)) |prep| {
debug2!("Building crate {}, declaring it as an input", path.to_str());
prep.declare_input("file", path.to_str(),
debug2!("Building crate {}, declaring it as an input", path.display());
// FIXME (#9639): This needs to handle non-utf8 paths
prep.declare_input("file", path.as_str().unwrap(),
workcache_support::digest_file_with_date(&path));
let subpath = path.clone();
let subcfgs = cfgs.clone();
let subpath_str = path_str.clone();
let subcx = ctx.clone();
let id = self.id.clone();
let sub_dir = self.build_workspace().clone();
@ -387,9 +394,14 @@ impl PkgSrc {
sub_flags,
subcfgs,
false,
what).to_str();
debug2!("Result of compiling {} was {}", subpath_str, result);
result
what);
// XXX: result is an Option<Path>. The following code did not take that
// into account. I'm not sure if the workcache really likes seeing the
// output as "Some(\"path\")". But I don't know what to do about it.
// FIXME (#9639): This needs to handle non-utf8 paths
let result = result.map(|p|p.as_str().unwrap());
debug2!("Result of compiling {} was {}", subpath.display(), result.to_str());
result.to_str()
}
};
}
@ -403,10 +415,10 @@ impl PkgSrc {
debug2!("In declare inputs, self = {}", self.to_str());
for cs in to_do.iter() {
for c in cs.iter() {
let path = self.start_dir.push_rel(&c.file).normalize();
debug2!("Declaring input: {}", path.to_str());
prep.declare_input("file",
path.to_str(),
let path = self.start_dir.join_path(&c.file);
debug2!("Declaring input: {}", path.display());
// FIXME (#9639): This needs to handle non-utf8 paths
prep.declare_input("file", path.as_str().unwrap(),
workcache_support::digest_file_with_date(&path.clone()));
}
}
@ -422,7 +434,7 @@ impl PkgSrc {
let tests = self.tests.clone();
let benchs = self.benchs.clone();
debug2!("Building libs in {}, destination = {}",
self.source_workspace.to_str(), self.build_workspace().to_str());
self.source_workspace.display(), self.build_workspace().display());
self.build_crates(build_context, libs, cfgs, Lib);
debug2!("Building mains");
self.build_crates(build_context, mains, cfgs, Main);
@ -447,7 +459,7 @@ impl PkgSrc {
let crate_sets = [&self.libs, &self.mains, &self.tests, &self.benchs];
for crate_set in crate_sets.iter() {
for c in crate_set.iter() {
debug2!("Built crate: {}", c.file.to_str())
debug2!("Built crate: {}", c.file.display())
}
}
}

View File

@ -53,7 +53,7 @@ pub fn make_dir_rwx_recursive(p: &Path) -> bool { os::mkdir_recursive(p, U_RWX)
/// True if there's a directory in <workspace> with
/// pkgid's short name
pub fn workspace_contains_package_id(pkgid: &PkgId, workspace: &Path) -> bool {
workspace_contains_package_id_(pkgid, workspace, |p| { p.push("src") }).is_some()
workspace_contains_package_id_(pkgid, workspace, |p| p.join_str("src")).is_some()
}
pub fn workspace_contains_package_id_(pkgid: &PkgId, workspace: &Path,
@ -68,10 +68,9 @@ pub fn workspace_contains_package_id_(pkgid: &PkgId, workspace: &Path,
let mut found = None;
do os::walk_dir(&src_dir) |p| {
if os::path_is_dir(p) {
if *p == src_dir.push_rel(&pkgid.path) || {
let pf = p.filename();
do pf.iter().any |pf| {
let g = pf.to_str();
if *p == src_dir.join_path(&pkgid.path) || {
let pf = p.filename_str();
do pf.iter().any |&g| {
match split_version_general(g, '-') {
None => false,
Some((ref might_match, ref vers)) => {
@ -89,9 +88,9 @@ pub fn workspace_contains_package_id_(pkgid: &PkgId, workspace: &Path,
};
if found.is_some() {
debug2!("Found {} in {}", pkgid.to_str(), workspace.to_str());
debug2!("Found {} in {}", pkgid.to_str(), workspace.display());
} else {
debug2!("Didn't find {} in {}", pkgid.to_str(), workspace.to_str());
debug2!("Didn't find {} in {}", pkgid.to_str(), workspace.display());
}
found
}
@ -99,20 +98,24 @@ pub fn workspace_contains_package_id_(pkgid: &PkgId, workspace: &Path,
/// Return the target-specific build subdirectory, pushed onto `base`;
/// doesn't check that it exists or create it
pub fn target_build_dir(workspace: &Path) -> Path {
workspace.push("build").push(host_triple())
let mut dir = workspace.join_str("build");
dir.push_str(host_triple());
dir
}
/// Return the target-specific lib subdirectory, pushed onto `base`;
/// doesn't check that it exists or create it
fn target_lib_dir(workspace: &Path) -> Path {
workspace.push("lib").push(host_triple())
let mut dir = workspace.join_str("lib");
dir.push_str(host_triple());
dir
}
/// Return the bin subdirectory, pushed onto `base`;
/// doesn't check that it exists or create it
/// note: this isn't target-specific
fn target_bin_dir(workspace: &Path) -> Path {
workspace.push("bin")
workspace.join_str("bin")
}
/// Figure out what the executable name for <pkgid> in <workspace>'s build
@ -121,12 +124,12 @@ pub fn built_executable_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<
let mut result = target_build_dir(workspace);
result = mk_output_path(Main, Build, pkgid, result);
debug2!("built_executable_in_workspace: checking whether {} exists",
result.to_str());
result.display());
if os::path_exists(&result) {
Some(result)
}
else {
debug2!("built_executable_in_workspace: {} does not exist", result.to_str());
debug2!("built_executable_in_workspace: {} does not exist", result.display());
None
}
}
@ -148,12 +151,12 @@ fn output_in_workspace(pkgid: &PkgId, workspace: &Path, what: OutputType) -> Opt
// should use a target-specific subdirectory
result = mk_output_path(what, Build, pkgid, result);
debug2!("output_in_workspace: checking whether {} exists",
result.to_str());
result.display());
if os::path_exists(&result) {
Some(result)
}
else {
error2!("output_in_workspace: {} does not exist", result.to_str());
error2!("output_in_workspace: {} does not exist", result.display());
None
}
}
@ -167,7 +170,8 @@ pub fn built_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<Pat
/// Does the actual searching stuff
pub fn installed_library_in_workspace(pkg_path: &Path, workspace: &Path) -> Option<Path> {
// This could break once we're handling multiple versions better -- I should add a test for it
match pkg_path.filename() {
// FIXME (#9639): This needs to handle non-utf8 paths
match pkg_path.filename_str() {
None => None,
Some(short_name) => library_in_workspace(pkg_path,
short_name,
@ -189,10 +193,10 @@ pub fn library_in_workspace(path: &Path, short_name: &str, where: Target,
// contents
debug2!("short_name = {} where = {:?} workspace = {} \
prefix = {}", short_name, where, workspace.to_str(), prefix);
prefix = {}", short_name, where, workspace.display(), prefix);
let dir_to_search = match where {
Build => target_build_dir(workspace).push_rel(path),
Build => target_build_dir(workspace).join_path(path),
Install => target_lib_dir(workspace)
};
@ -201,28 +205,24 @@ pub fn library_in_workspace(path: &Path, short_name: &str, where: Target,
// rustc doesn't use target-specific subdirectories
pub fn system_library(sysroot: &Path, lib_name: &str) -> Option<Path> {
library_in(lib_name, &NoVersion, &sysroot.push("lib"))
library_in(lib_name, &NoVersion, &sysroot.join_str("lib"))
}
fn library_in(short_name: &str, version: &Version, dir_to_search: &Path) -> Option<Path> {
debug2!("Listing directory {}", dir_to_search.to_str());
debug2!("Listing directory {}", dir_to_search.display());
let dir_contents = os::list_dir(dir_to_search);
debug2!("dir has {:?} entries", dir_contents.len());
let lib_prefix = format!("{}{}", os::consts::DLL_PREFIX, short_name);
let lib_filetype = os::consts::DLL_SUFFIX;
let lib_filetype = os::consts::DLL_EXTENSION;
debug2!("lib_prefix = {} and lib_filetype = {}", lib_prefix, lib_filetype);
// Find a filename that matches the pattern:
// (lib_prefix)-hash-(version)(lib_suffix)
let paths = do dir_contents.iter().map |p| {
Path((*p).clone())
};
let mut libraries = do paths.filter |p| {
let extension = p.filetype();
debug2!("p = {}, p's extension is {:?}", p.to_str(), extension);
let mut libraries = do dir_contents.iter().filter |p| {
let extension = p.extension_str();
debug2!("p = {}, p's extension is {:?}", p.display(), extension);
match extension {
None => false,
Some(ref s) => lib_filetype == *s
@ -233,7 +233,7 @@ fn library_in(short_name: &str, version: &Version, dir_to_search: &Path) -> Opti
for p_path in libraries {
// Find a filename that matches the pattern: (lib_prefix)-hash-(version)(lib_suffix)
// and remember what the hash was
let mut f_name = match p_path.filestem() {
let mut f_name = match p_path.filestem_str() {
Some(s) => s, None => continue
};
// Already checked the filetype above
@ -267,14 +267,14 @@ fn library_in(short_name: &str, version: &Version, dir_to_search: &Path) -> Opti
if result_filename.is_none() {
debug2!("warning: library_in_workspace didn't find a library in {} for {}",
dir_to_search.to_str(), short_name);
dir_to_search.display(), short_name);
}
// Return the filename that matches, which we now know exists
// (if result_filename != None)
let abs_path = do result_filename.map |result_filename| {
let absolute_path = dir_to_search.push_rel(&result_filename);
debug2!("result_filename = {}", absolute_path.to_str());
let absolute_path = dir_to_search.join_path(&result_filename);
debug2!("result_filename = {}", absolute_path.display());
absolute_path
};
@ -297,7 +297,7 @@ pub fn target_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
if !os::path_is_dir(workspace) {
cond.raise(((*workspace).clone(),
format!("Workspace supplied to target_library_in_workspace \
is not a directory! {}", workspace.to_str())));
is not a directory! {}", workspace.display())));
}
target_file_in_workspace(pkgid, workspace, Lib, Install)
}
@ -329,14 +329,14 @@ fn target_file_in_workspace(pkgid: &PkgId, workspace: &Path,
// Artifacts in the build directory live in a package-ID-specific subdirectory,
// but installed ones don't.
let result = match (where, what) {
(Build, _) => target_build_dir(workspace).push_rel(&pkgid.path),
(Install, Lib) => target_lib_dir(workspace),
(Build, _) => target_build_dir(workspace).join_path(&pkgid.path),
(Install, Lib) => target_lib_dir(workspace),
(Install, _) => target_bin_dir(workspace)
};
if !os::path_exists(&result) && !mkdir_recursive(&result, U_RWX) {
cond.raise((result.clone(), format!("target_file_in_workspace couldn't \
create the {} dir (pkgid={}, workspace={}, what={:?}, where={:?}",
subdir, pkgid.to_str(), workspace.to_str(), what, where)));
subdir, pkgid.to_str(), workspace.display(), what, where)));
}
mk_output_path(what, where, pkgid, result)
}
@ -347,8 +347,8 @@ pub fn build_pkg_id_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path {
use conditions::bad_path::cond;
let mut result = target_build_dir(workspace);
result = result.push_rel(&pkgid.path);
debug2!("Creating build dir {} for package id {}", result.to_str(),
result.push_path(&pkgid.path);
debug2!("Creating build dir {} for package id {}", result.display(),
pkgid.to_str());
if os::path_exists(&result) || os::mkdir_recursive(&result, U_RWX) {
result
@ -370,16 +370,16 @@ pub fn mk_output_path(what: OutputType, where: Target,
// If we're installing, it just goes under <workspace>...
Install => workspace,
// and if we're just building, it goes in a package-specific subdir
Build => workspace.push_rel(&pkg_id.path)
Build => workspace.join_path(&pkg_id.path)
};
debug2!("[{:?}:{:?}] mk_output_path: short_name = {}, path = {}", what, where,
if what == Lib { short_name_with_version.clone() } else { pkg_id.short_name.clone() },
dir.to_str());
dir.display());
let mut output_path = match what {
// this code is duplicated from elsewhere; fix this
Lib => dir.push(os::dll_filename(short_name_with_version)),
Lib => dir.join_str(os::dll_filename(short_name_with_version)),
// executable names *aren't* versioned
_ => dir.push(format!("{}{}{}", pkg_id.short_name,
_ => dir.join_str(format!("{}{}{}", pkg_id.short_name,
match what {
Test => "test",
Bench => "bench",
@ -388,9 +388,9 @@ pub fn mk_output_path(what: OutputType, where: Target,
os::EXE_SUFFIX))
};
if !output_path.is_absolute() {
output_path = os::getcwd().push_rel(&output_path).normalize();
output_path = os::getcwd().join_path(&output_path);
}
debug2!("mk_output_path: returning {}", output_path.to_str());
debug2!("mk_output_path: returning {}", output_path.display());
output_path
}
@ -409,14 +409,14 @@ pub fn uninstall_package_from(workspace: &Path, pkgid: &PkgId) {
}
if !did_something {
warn(format!("Warning: there don't seem to be any files for {} installed in {}",
pkgid.to_str(), workspace.to_str()));
pkgid.to_str(), workspace.display()));
}
}
fn dir_has_file(dir: &Path, file: &str) -> bool {
assert!(dir.is_absolute());
os::path_exists(&dir.push(file))
os::path_exists(&dir.join_str(file))
}
pub fn find_dir_using_rust_path_hack(p: &PkgId) -> Option<Path> {
@ -425,15 +425,15 @@ pub fn find_dir_using_rust_path_hack(p: &PkgId) -> Option<Path> {
// Require that the parent directory match the package ID
// Note that this only matches if the package ID being searched for
// has a name that's a single component
if dir.is_parent_of(&p.path) || dir.is_parent_of(&versionize(&p.path, &p.version)) {
debug2!("In find_dir_using_rust_path_hack: checking dir {}", dir.to_str());
if dir.ends_with_path(&p.path) || dir.ends_with_path(&versionize(&p.path, &p.version)) {
debug2!("In find_dir_using_rust_path_hack: checking dir {}", dir.display());
if dir_has_file(dir, "lib.rs") || dir_has_file(dir, "main.rs")
|| dir_has_file(dir, "test.rs") || dir_has_file(dir, "bench.rs") {
debug2!("Did find id {} in dir {}", p.to_str(), dir.to_str());
debug2!("Did find id {} in dir {}", p.to_str(), dir.display());
return Some(dir.clone());
}
}
debug2!("Didn't find id {} in dir {}", p.to_str(), dir.to_str())
debug2!("Didn't find id {} in dir {}", p.to_str(), dir.display())
}
None
}
@ -449,8 +449,12 @@ pub fn user_set_rust_path() -> bool {
/// Append the version string onto the end of the path's filename
pub fn versionize(p: &Path, v: &Version) -> Path {
let q = p.file_path().to_str();
p.with_filename(format!("{}-{}", q, v.to_str()))
let q = p.file_path().expect("path is a directory");
let mut q = q.as_vec().to_owned();
q.push('-' as u8);
let vs = v.to_str();
q.push_all(vs.as_bytes());
p.with_filename(q)
}

View File

@ -105,7 +105,7 @@ impl<'self> PkgScript<'self> {
let binary = os::args()[0].to_managed();
// Build the rustc session data structures to pass
// to the compiler
debug2!("pkgscript parse: {}", sysroot.to_str());
debug2!("pkgscript parse: {}", sysroot.display());
let options = @session::options {
binary: binary,
maybe_sysroot: Some(sysroot),
@ -141,31 +141,36 @@ impl<'self> PkgScript<'self> {
sysroot: &Path) -> (~[~str], ExitCode) {
let sess = self.sess;
debug2!("Working directory = {}", self.build_dir.to_str());
debug2!("Working directory = {}", self.build_dir.display());
// Collect together any user-defined commands in the package script
let crate = util::ready_crate(sess, self.crate.take_unwrap());
debug2!("Building output filenames with script name {}",
driver::source_name(&driver::file_input(self.input.clone())));
let exe = self.build_dir.push(~"pkg" + util::exe_suffix());
let exe = self.build_dir.join_str("pkg" + util::exe_suffix());
util::compile_crate_from_input(&self.input,
exec,
Nothing,
&self.build_dir,
sess,
crate);
debug2!("Running program: {} {} {}", exe.to_str(),
sysroot.to_str(), "install");
debug2!("Running program: {} {} {}", exe.display(),
sysroot.display(), "install");
// Discover the output
exec.discover_output("binary", exe.to_str(), digest_only_date(&exe));
// FIXME (#9639): This needs to handle non-utf8 paths
exec.discover_output("binary", exe.as_str().unwrap(), digest_only_date(&exe));
// FIXME #7401 should support commands besides `install`
let status = run::process_status(exe.to_str(), [sysroot.to_str(), ~"install"]);
// FIXME (#9639): This needs to handle non-utf8 paths
let status = run::process_status(exe.as_str().unwrap(),
[sysroot.as_str().unwrap().to_owned(), ~"install"]);
if status != 0 {
return (~[], status);
}
else {
debug2!("Running program (configs): {} {} {}",
exe.to_str(), sysroot.to_str(), "configs");
let output = run::process_output(exe.to_str(), [sysroot.to_str(), ~"configs"]);
exe.display(), sysroot.display(), "configs");
// FIXME (#9639): This needs to handle non-utf8 paths
let output = run::process_output(exe.as_str().unwrap(),
[sysroot.as_str().unwrap().to_owned(), ~"configs"]);
// Run the configs() function to get the configs
let cfgs = str::from_utf8_slice(output.output).word_iter()
.map(|w| w.to_owned()).collect();
@ -208,7 +213,8 @@ impl CtxMethods for BuildContext {
match cwd_to_workspace() {
None if self.context.use_rust_path_hack => {
let cwd = os::getcwd();
let pkgid = PkgId::new(cwd.components[cwd.components.len() - 1]);
// FIXME (#9639): This needs to handle non-utf8 paths
let pkgid = PkgId::new(cwd.filename_str().unwrap());
let mut pkg_src = PkgSrc::new(cwd, default_workspace(), true, pkgid);
self.build(&mut pkg_src, what);
match pkg_src {
@ -237,13 +243,12 @@ impl CtxMethods for BuildContext {
let mut dest_ws = default_workspace();
do each_pkg_parent_workspace(&self.context, &pkgid) |workspace| {
debug2!("found pkg {} in workspace {}, trying to build",
pkgid.to_str(), workspace.to_str());
pkgid.to_str(), workspace.display());
dest_ws = determine_destination(os::getcwd(),
self.context.use_rust_path_hack,
workspace);
let mut pkg_src = PkgSrc::new(workspace.clone(), dest_ws.clone(),
false, pkgid.clone());
self.build(&mut pkg_src, what);
let mut pkg_src = PkgSrc::new(workspace.clone(), false, pkgid.clone());
dest_ws = Some(self.build(&mut pkg_src, what));
true
};
// n.b. If this builds multiple packages, it only returns the workspace for
@ -290,8 +295,9 @@ impl CtxMethods for BuildContext {
match cwd_to_workspace() {
None if self.context.use_rust_path_hack => {
let cwd = os::getcwd();
// FIXME (#9639): This needs to handle non-utf8 paths
let inferred_pkgid =
PkgId::new(cwd.components[cwd.components.len() - 1]);
PkgId::new(cwd.filename_str().unwrap());
self.install(PkgSrc::new(cwd, default_workspace(),
true, inferred_pkgid), &Everything);
}
@ -331,7 +337,9 @@ impl CtxMethods for BuildContext {
"list" => {
io::println("Installed packages:");
do installed_packages::list_installed_packages |pkg_id| {
println(pkg_id.path.to_str());
do pkg_id.path.with_display_str |s| {
println(s);
}
true
};
}
@ -379,7 +387,7 @@ impl CtxMethods for BuildContext {
do each_pkg_parent_workspace(&self.context, &pkgid) |workspace| {
path_util::uninstall_package_from(workspace, &pkgid);
note(format!("Uninstalled package {} (was installed in {})",
pkgid.to_str(), workspace.to_str()));
pkgid.to_str(), workspace.display()));
true
};
}
@ -407,23 +415,25 @@ impl CtxMethods for BuildContext {
let pkgid = pkg_src.id.clone();
debug2!("build: workspace = {} (in Rust path? {:?} is git dir? {:?} \
pkgid = {} pkgsrc start_dir = {}", workspace.to_str(),
in_rust_path(&workspace), is_git_dir(&workspace.push_rel(&pkgid.path)),
pkgid.to_str(), pkg_src.start_dir.to_str());
pkgid = {} pkgsrc start_dir = {}", workspace.display(),
in_rust_path(&workspace), is_git_dir(&workspace.join_path(&pkgid.path)),
pkgid.to_str(), pkg_src.start_dir.display());
// If workspace isn't in the RUST_PATH, and it's a git repo,
// then clone it into the first entry in RUST_PATH, and repeat
if !in_rust_path(&workspace) && is_git_dir(&workspace.push_rel(&pkgid.path)) {
let out_dir = default_workspace().push("src").push_rel(&pkgid.path);
let git_result = source_control::safe_git_clone(&workspace.push_rel(&pkgid.path),
if !in_rust_path(&workspace) && is_git_dir(&workspace.join_path(&pkgid.path)) {
let mut out_dir = default_workspace().join_str("src");
out_dir.push_path(&pkgid.path);
let git_result = source_control::safe_git_clone(&workspace.join_path(&pkgid.path),
&pkgid.version,
&out_dir);
match git_result {
CheckedOutSources => make_read_only(&out_dir),
_ => cond.raise((pkgid.path.to_str(), out_dir.clone()))
// FIXME (#9639): This needs to handle non-utf8 paths
_ => cond.raise((pkgid.path.as_str().unwrap(), out_dir.clone()))
};
let default_ws = default_workspace();
debug2!("Calling build recursively with {:?} and {:?}", default_ws.to_str(),
debug2!("Calling build recursively with {:?} and {:?}", default_ws.display(),
pkgid.to_str());
return self.build(&mut PkgSrc::new(default_ws.clone(),
default_ws,
@ -439,8 +449,10 @@ impl CtxMethods for BuildContext {
let cfgs = match pkg_src.package_script_option() {
Some(package_script_path) => {
let sysroot = self.sysroot_to_use();
// FIXME (#9639): This needs to handle non-utf8 paths
let pkg_script_path_str = package_script_path.as_str().unwrap();
let (cfgs, hook_result) =
do self.workcache_context.with_prep(package_script_path.to_str()) |prep| {
do self.workcache_context.with_prep(pkg_script_path_str) |prep| {
let sub_sysroot = sysroot.clone();
let package_script_path_clone = package_script_path.clone();
let sub_ws = workspace.clone();
@ -476,13 +488,13 @@ impl CtxMethods for BuildContext {
// Find crates inside the workspace
&Everything => pkg_src.find_crates(),
// Find only tests
&Tests => pkg_src.find_crates_with_filter(|s| { is_test(&Path(s)) }),
&Tests => pkg_src.find_crates_with_filter(|s| { is_test(&Path::from_str(s)) }),
// Don't infer any crates -- just build the one that was requested
&JustOne(ref p) => {
// We expect that p is relative to the package source's start directory,
// so check that assumption
debug2!("JustOne: p = {}", p.to_str());
assert!(os::path_exists(&pkg_src.start_dir.push_rel(p)));
debug2!("JustOne: p = {}", p.display());
assert!(os::path_exists(&pkg_src.start_dir.join_path(p)));
if is_lib(p) {
PkgSrc::push_crate(&mut pkg_src.libs, 0, p);
} else if is_main(p) {
@ -492,7 +504,7 @@ impl CtxMethods for BuildContext {
} else if is_bench(p) {
PkgSrc::push_crate(&mut pkg_src.benchs, 0, p);
} else {
warn(format!("Not building any crates for dependency {}", p.to_str()));
warn(format!("Not building any crates for dependency {}", p.display()));
return;
}
}
@ -509,10 +521,10 @@ impl CtxMethods for BuildContext {
let dir = build_pkg_id_in_workspace(id, workspace);
note(format!("Cleaning package {} (removing directory {})",
id.to_str(), dir.to_str()));
id.to_str(), dir.display()));
if os::path_exists(&dir) {
os::remove_dir_recursive(&dir);
note(format!("Removed directory {}", dir.to_str()));
note(format!("Removed directory {}", dir.display()));
}
note(format!("Cleaned package {}", id.to_str()));
@ -541,21 +553,22 @@ impl CtxMethods for BuildContext {
debug2!("In declare inputs for {}", id.to_str());
for cs in to_do.iter() {
for c in cs.iter() {
let path = pkg_src.start_dir.push_rel(&c.file).normalize();
debug2!("Recording input: {}", path.to_str());
inputs.push((~"file", path.to_str()));
let path = pkg_src.start_dir.join_path(&c.file);
debug2!("Recording input: {}", path.display());
// FIXME (#9639): This needs to handle non-utf8 paths
inputs.push((~"file", path.as_str().unwrap().to_owned()));
}
}
let result = self.install_no_build(pkg_src.build_workspace(),
&pkg_src.destination_workspace,
&id).map(|s| Path(*s));
&id).map(|s| Path::from_str(*s));
debug2!("install: id = {}, about to call discover_outputs, {:?}",
id.to_str(), result.to_str());
id.to_str(), result.map(|p| p.to_display_str()));
installed_files = installed_files + result;
note(format!("Installed package {} to {}",
id.to_str(),
pkg_src.destination_workspace.to_str()));
pkg_src.destination_workspace.display()));
(installed_files, inputs)
}
@ -578,18 +591,20 @@ impl CtxMethods for BuildContext {
debug2!("target_exec = {} target_lib = {:?} \
maybe_executable = {:?} maybe_library = {:?}",
target_exec.to_str(), target_lib,
target_exec.display(), target_lib,
maybe_executable, maybe_library);
do self.workcache_context.with_prep(id.install_tag()) |prep| {
for ee in maybe_executable.iter() {
// FIXME (#9639): This needs to handle non-utf8 paths
prep.declare_input("binary",
ee.to_str(),
ee.as_str().unwrap(),
workcache_support::digest_only_date(ee));
}
for ll in maybe_library.iter() {
// FIXME (#9639): This needs to handle non-utf8 paths
prep.declare_input("binary",
ll.to_str(),
ll.as_str().unwrap(),
workcache_support::digest_only_date(ll));
}
let subex = maybe_executable.clone();
@ -601,31 +616,32 @@ impl CtxMethods for BuildContext {
let mut outputs = ~[];
for exec in subex.iter() {
debug2!("Copying: {} -> {}", exec.to_str(), sub_target_ex.to_str());
debug2!("Copying: {} -> {}", exec.display(), sub_target_ex.display());
if !(os::mkdir_recursive(&sub_target_ex.dir_path(), U_RWX) &&
os::copy_file(exec, &sub_target_ex)) {
cond.raise(((*exec).clone(), sub_target_ex.clone()));
}
// FIXME (#9639): This needs to handle non-utf8 paths
exe_thing.discover_output("binary",
sub_target_ex.to_str(),
sub_target_ex.as_str().unwrap(),
workcache_support::digest_only_date(&sub_target_ex));
outputs.push(sub_target_ex.to_str());
outputs.push(sub_target_ex.as_str().unwrap().to_owned());
}
for lib in sublib.iter() {
let target_lib = sub_target_lib
let mut target_lib = sub_target_lib
.clone().expect(format!("I built {} but apparently \
didn't install it!", lib.to_str()));
didn't install it!", lib.display()));
let target_lib = target_lib
.pop().push(lib.filename().expect("weird target lib"));
.set_filename(lib.filename().expect("weird target lib"));
if !(os::mkdir_recursive(&target_lib.dir_path(), U_RWX) &&
os::copy_file(lib, &target_lib)) {
cond.raise(((*lib).clone(), target_lib.clone()));
}
debug2!("3. discovering output {}", target_lib.to_str());
debug2!("3. discovering output {}", target_lib.display());
exe_thing.discover_output("binary",
target_lib.to_str(),
target_lib.as_str().unwrap(),
workcache_support::digest_only_date(&target_lib));
outputs.push(target_lib.to_str());
outputs.push(target_lib.as_str().unwrap().to_owned());
}
outputs
}
@ -639,23 +655,24 @@ impl CtxMethods for BuildContext {
fn test(&self, pkgid: &PkgId, workspace: &Path) {
match built_test_in_workspace(pkgid, workspace) {
Some(test_exec) => {
debug2!("test: test_exec = {}", test_exec.to_str());
let status = run::process_status(test_exec.to_str(), [~"--test"]);
debug2!("test: test_exec = {}", test_exec.display());
// FIXME (#9639): This needs to handle non-utf8 paths
let status = run::process_status(test_exec.as_str().unwrap(), [~"--test"]);
os::set_exit_status(status);
}
None => {
error(format!("Internal error: test executable for package ID {} in workspace {} \
wasn't built! Please report this as a bug.",
pkgid.to_str(), workspace.to_str()));
pkgid.to_str(), workspace.display()));
}
}
}
fn init(&self) {
os::mkdir_recursive(&Path("src"), U_RWX);
os::mkdir_recursive(&Path("lib"), U_RWX);
os::mkdir_recursive(&Path("bin"), U_RWX);
os::mkdir_recursive(&Path("build"), U_RWX);
os::mkdir_recursive(&Path::from_str("src"), U_RWX);
os::mkdir_recursive(&Path::from_str("lib"), U_RWX);
os::mkdir_recursive(&Path::from_str("bin"), U_RWX);
os::mkdir_recursive(&Path::from_str("build"), U_RWX);
}
fn uninstall(&self, _id: &str, _vers: Option<~str>) {
@ -835,12 +852,13 @@ pub fn main_args(args: &[~str]) -> int {
let mut remaining_args: ~[~str] = remaining_args.map(|s| (*s).clone()).collect();
remaining_args.shift();
let sroot = match supplied_sysroot {
Some(getopts::Val(s)) => Path(s),
Some(getopts::Val(s)) => Path::from_str(s),
_ => filesearch::get_or_default_sysroot()
};
debug2!("Using sysroot: {}", sroot.to_str());
debug2!("Will store workcache in {}", default_workspace().to_str());
debug2!("Using sysroot: {}", sroot.display());
let ws = default_workspace();
debug2!("Will store workcache in {}", ws.display());
let rm_args = remaining_args.clone();
let sub_cmd = cmd.clone();
@ -866,7 +884,8 @@ pub fn main_args(args: &[~str]) -> int {
fn declare_package_script_dependency(prep: &mut workcache::Prep, pkg_src: &PkgSrc) {
match pkg_src.package_script_option() {
Some(ref p) => prep.declare_input("file", p.to_str(),
// FIXME (#9639): This needs to handle non-utf8 paths
Some(ref p) => prep.declare_input("file", p.as_str().unwrap(),
workcache_support::digest_file_with_date(p)),
None => ()
}

View File

@ -18,7 +18,7 @@ use version::Version;
pub fn find_installed_library_in_rust_path(pkg_path: &Path, _version: &Version) -> Option<Path> {
let rp = rust_path();
debug2!("find_installed_library_in_rust_path: looking for path {}",
pkg_path.to_str());
pkg_path.display());
for p in rp.iter() {
match installed_library_in_workspace(pkg_path, p) {
Some(path) => return Some(path),

View File

@ -24,14 +24,17 @@ use path_util::chmod_read_only;
pub fn safe_git_clone(source: &Path, v: &Version, target: &Path) -> CloneResult {
if os::path_exists(source) {
debug2!("{} exists locally! Cloning it into {}",
source.to_str(), target.to_str());
source.display(), target.display());
// Ok to use target here; we know it will succeed
assert!(os::path_is_dir(source));
assert!(is_git_dir(source));
if !os::path_exists(target) {
debug2!("Running: git clone {} {}", source.to_str(), target.to_str());
let outp = run::process_output("git", [~"clone", source.to_str(), target.to_str()]);
debug2!("Running: git clone {} {}", source.display(), target.display());
// FIXME (#9639): This needs to handle non-utf8 paths
let outp = run::process_output("git", [~"clone",
source.as_str().unwrap().to_owned(),
target.as_str().unwrap().to_owned()]);
if outp.status != 0 {
io::println(str::from_utf8_owned(outp.output.clone()));
io::println(str::from_utf8_owned(outp.error));
@ -40,11 +43,13 @@ pub fn safe_git_clone(source: &Path, v: &Version, target: &Path) -> CloneResult
else {
match v {
&ExactRevision(ref s) => {
let git_dir = target.join_str(".git");
debug2!("`Running: git --work-tree={} --git-dir={} checkout {}",
*s, target.to_str(), target.push(".git").to_str());
*s, target.display(), git_dir.display());
// FIXME (#9639: This needs to handle non-utf8 paths
let outp = run::process_output("git",
[format!("--work-tree={}", target.to_str()),
format!("--git-dir={}", target.push(".git").to_str()),
[format!("--work-tree={}", target.as_str().unwrap().to_owned()),
format!("--git-dir={}", git_dir.as_str().unwrap().to_owned()),
~"checkout", format!("{}", *s)]);
if outp.status != 0 {
io::println(str::from_utf8_owned(outp.output.clone()));
@ -59,11 +64,13 @@ pub fn safe_git_clone(source: &Path, v: &Version, target: &Path) -> CloneResult
// Check that no version was specified. There's no reason to not handle the
// case where a version was requested, but I haven't implemented it.
assert!(*v == NoVersion);
let git_dir = target.join_str(".git");
debug2!("Running: git --work-tree={} --git-dir={} pull --no-edit {}",
target.to_str(), target.push(".git").to_str(), source.to_str());
let args = [format!("--work-tree={}", target.to_str()),
format!("--git-dir={}", target.push(".git").to_str()),
~"pull", ~"--no-edit", source.to_str()];
target.display(), git_dir.display(), source.display());
// FIXME (#9639: This needs to handle non-utf8 paths
let args = [format!("--work-tree={}", target.as_str().unwrap().to_owned()),
format!("--git-dir={}", git_dir.as_str().unwrap().to_owned()),
~"pull", ~"--no-edit", source.as_str().unwrap().to_owned()];
let outp = run::process_output("git", args);
assert!(outp.status == 0);
}
@ -73,7 +80,7 @@ pub fn safe_git_clone(source: &Path, v: &Version, target: &Path) -> CloneResult
let scratch_dir = TempDir::new("rustpkg");
let clone_target = match scratch_dir {
Some(d) => d.unwrap().push("rustpkg_temp"),
Some(d) => d.unwrap().join_str("rustpkg_temp"),
None => cond.raise(~"Failed to create temporary directory for fetching git sources")
};
@ -109,7 +116,7 @@ pub fn git_clone_url(source: &str, target: &Path, v: &Version) {
else {
match v {
&ExactRevision(ref s) | &Tagged(ref s) => {
let outp = process_output_in_cwd("git", [~"checkout", format!("{}", *s)],
let outp = process_output_in_cwd("git", [~"checkout", s.to_owned()],
target);
if outp.status != 0 {
debug2!("{}", str::from_utf8_owned(outp.output.clone()));
@ -129,5 +136,5 @@ fn process_output_in_cwd(prog: &str, args: &[~str], cwd: &Path) -> ProcessOutput
}
pub fn is_git_dir(p: &Path) -> bool {
os::path_is_dir(&p.push(".git"))
os::path_is_dir(&p.join_str(".git"))
}

View File

@ -50,13 +50,13 @@ pub fn is_bench(p: &Path) -> bool {
fn file_is(p: &Path, stem: &str) -> bool {
match p.filestem() {
Some(s) if s == stem => true,
Some(s) if s == stem.as_bytes() => true,
_ => false
}
}
pub fn lib_name_of(p: &Path) -> Path {
p.push("lib.rs")
p.join_str("lib.rs")
}
pub static lib_crate_filename: &'static str = "lib.rs";

File diff suppressed because it is too large Load Diff

View File

@ -170,13 +170,14 @@ pub fn compile_input(context: &BuildContext,
cfgs: &[~str],
opt: bool,
what: OutputType) -> Option<Path> {
assert!(in_file.components.len() > 1);
let input = driver::file_input((*in_file).clone());
debug2!("compile_input: {} / {:?}", in_file.to_str(), what);
assert!(in_file.component_iter().nth(1).is_some());
let input = driver::file_input(in_file.clone());
debug2!("compile_input: {} / {:?}", in_file.display(), what);
// tjc: by default, use the package ID name as the link name
// not sure if we should support anything else
let out_dir = target_build_dir(workspace).push_rel(&pkg_id.path);
let mut out_dir = target_build_dir(workspace);
out_dir.push_path(&pkg_id.path);
// Make the output directory if it doesn't exist already
assert!(os::mkdir_recursive(&out_dir, U_RWX));
@ -184,7 +185,8 @@ pub fn compile_input(context: &BuildContext,
debug2!("flags: {}", flags.connect(" "));
debug2!("cfgs: {}", cfgs.connect(" "));
debug2!("compile_input's sysroot = {}", context.sysroot().to_str());
let csysroot = context.sysroot();
debug2!("compile_input's sysroot = {}", csysroot.display());
let crate_type = match what {
Lib => lib_crate,
@ -209,10 +211,15 @@ pub fn compile_input(context: &BuildContext,
context.sysroot()
}
else {
context.sysroot().pop().pop().pop()
let mut p = context.sysroot().clone();
p.pop();
p.pop();
p.pop();
p
};
debug2!("compile_input's sysroot = {}", context.sysroot().to_str());
debug2!("sysroot_to_use = {}", sysroot_to_use.to_str());
let csysroot = context.sysroot();
debug2!("compile_input's sysroot = {}", csysroot.display());
debug2!("sysroot_to_use = {}", sysroot_to_use.display());
let output_type = match context.compile_upto() {
Assemble => link::output_type_assembly,
@ -260,7 +267,7 @@ pub fn compile_input(context: &BuildContext,
find_and_install_dependencies(context, pkg_id, sess, exec, &crate,
|p| {
debug2!("a dependency: {}", p.to_str());
debug2!("a dependency: {}", p.display());
// Pass the directory containing a dependency
// as an additional lib search path
if !addl_lib_search_paths.contains(&p) {
@ -278,18 +285,19 @@ pub fn compile_input(context: &BuildContext,
_ => pkg_id.short_name.to_managed()
};
debug2!("Injecting link name: {}", name_to_use);
// FIXME (#9639): This needs to handle non-utf8 paths
let link_options =
~[attr::mk_name_value_item_str(@"name", name_to_use),
attr::mk_name_value_item_str(@"vers", pkg_id.version.to_str().to_managed())] +
~[attr::mk_name_value_item_str(@"package_id",
pkg_id.path.to_str().to_managed())];
pkg_id.path.as_str().unwrap().to_managed())];
debug2!("link options: {:?}", link_options);
crate.attrs = ~[attr::mk_attr(attr::mk_list_item(@"link", link_options))];
}
debug2!("calling compile_crate_from_input, workspace = {},
building_library = {:?}", out_dir.to_str(), sess.building_library);
building_library = {:?}", out_dir.display(), sess.building_library);
let result = compile_crate_from_input(in_file,
exec,
context.compile_upto(),
@ -303,11 +311,12 @@ pub fn compile_input(context: &BuildContext,
else {
result
};
debug2!("About to discover output {}", discovered_output.to_str());
for p in discovered_output.iter() {
debug2!("About to discover output {}", p.display());
if os::path_exists(p) {
debug2!("4. discovering output {}", p.to_str());
exec.discover_output("binary", p.to_str(), digest_only_date(p));
debug2!("4. discovering output {}", p.display());
// FIXME (#9639): This needs to handle non-utf8 paths
exec.discover_output("binary", p.as_str().unwrap(), digest_only_date(p));
}
// Nothing to do if it doesn't exist -- that could happen if we had the
// -S or -emit-llvm flags, etc.
@ -330,21 +339,21 @@ pub fn compile_crate_from_input(input: &Path,
// given
crate: ast::Crate) -> Option<Path> {
debug2!("Calling build_output_filenames with {}, building library? {:?}",
out_dir.to_str(), sess.building_library);
out_dir.display(), sess.building_library);
// bad copy
debug2!("out_dir = {}", out_dir.to_str());
debug2!("out_dir = {}", out_dir.display());
let outputs = driver::build_output_filenames(&driver::file_input(input.clone()),
&Some(out_dir.clone()), &None,
crate.attrs, sess);
debug2!("Outputs are out_filename: {} and obj_filename: {} and output type = {:?}",
outputs.out_filename.to_str(),
outputs.obj_filename.to_str(),
outputs.out_filename.display(),
outputs.obj_filename.display(),
sess.opts.output_type);
debug2!("additional libraries:");
for lib in sess.opts.addl_lib_search_paths.iter() {
debug2!("an additional library: {}", lib.to_str());
debug2!("an additional library: {}", lib.display());
}
let analysis = driver::phase_3_run_analysis_passes(sess, &crate);
if driver::stop_after_phase_3(sess) { return None; }
@ -359,9 +368,10 @@ pub fn compile_crate_from_input(input: &Path,
driver::phase_6_link_output(sess, &translation, outputs);
// Register dependency on the source file
exec.discover_input("file", input.to_str(), digest_file_with_date(input));
// FIXME (#9639): This needs to handle non-utf8 paths
exec.discover_input("file", input.as_str().unwrap(), digest_file_with_date(input));
debug2!("Built {}, date = {:?}", outputs.out_filename.to_str(),
debug2!("Built {}, date = {:?}", outputs.out_filename.display(),
datestamp(&outputs.out_filename));
Some(outputs.out_filename)
@ -383,7 +393,7 @@ pub fn compile_crate(ctxt: &BuildContext,
crate: &Path, workspace: &Path,
flags: &[~str], cfgs: &[~str], opt: bool,
what: OutputType) -> Option<Path> {
debug2!("compile_crate: crate={}, workspace={}", crate.to_str(), workspace.to_str());
debug2!("compile_crate: crate={}, workspace={}", crate.display(), workspace.display());
debug2!("compile_crate: short_name = {}, flags =...", pkg_id.to_str());
for fl in flags.iter() {
debug2!("+++ {}", *fl);
@ -414,15 +424,16 @@ impl<'self> Visitor<()> for ViewItemVisitor<'self> {
// Check standard Rust library path first
match system_library(&self.context.sysroot(), lib_name) {
Some(ref installed_path) => {
debug2!("It exists: {}", installed_path.to_str());
debug2!("It exists: {}", installed_path.display());
// Say that [path for c] has a discovered dependency on
// installed_path
// For binary files, we only hash the datestamp, not the contents.
// I'm not sure what the right thing is.
// Now we know that this crate has a discovered dependency on
// installed_path
// FIXME (#9639): This needs to handle non-utf8 paths
self.exec.discover_input("binary",
installed_path.to_str(),
installed_path.as_str().unwrap(),
digest_only_date(installed_path));
}
None => {
@ -456,7 +467,8 @@ impl<'self> Visitor<()> for ViewItemVisitor<'self> {
self.context.context.use_rust_path_hack,
pkg_id);
let (outputs_disc, inputs_disc) =
self.context.install(pkg_src, &JustOne(Path(lib_crate_filename)));
self.context.install(pkg_src,
&JustOne(Path::from_str(lib_crate_filename)));
debug2!("Installed {}, returned {:?} dependencies and \
{:?} transitive dependencies",
lib_name, outputs_disc.len(), inputs_disc.len());
@ -465,24 +477,27 @@ impl<'self> Visitor<()> for ViewItemVisitor<'self> {
// It must have installed *something*...
assert!(!outputs_disc.is_empty());
for dep in outputs_disc.iter() {
debug2!("Discovering a binary input: {}", dep.to_str());
debug2!("Discovering a binary input: {}", dep.display());
// FIXME (#9639): This needs to handle non-utf8 paths
self.exec.discover_input("binary",
dep.to_str(),
dep.as_str().unwrap(),
digest_only_date(dep));
// Also, add an additional search path
debug2!("Installed {} into {}", dep.to_str(), dep.pop().to_str());
(self.save)(dep.pop());
debug2!("Installed {} into {}", dep.display(),
dep.dir_path().display());
(self.save)(dep.dir_path());
}
for &(ref what, ref dep) in inputs_disc.iter() {
if *what == ~"file" {
self.exec.discover_input(*what,
*dep,
digest_file_with_date(&Path(*dep)));
digest_file_with_date(
&Path::from_str(*dep)));
}
else if *what == ~"binary" {
self.exec.discover_input(*what,
*dep,
digest_only_date(&Path(*dep)));
digest_only_date(&Path::from_str(*dep)));
}
else {
fail2!("Bad kind: {}", *what);
@ -559,7 +574,7 @@ fn debug_flags() -> ~[~str] { ~[] }
/// Returns the last-modified date as an Option
pub fn datestamp(p: &Path) -> Option<libc::time_t> {
debug2!("Scrutinizing datestamp for {} - does it exist? {:?}", p.to_str(), os::path_exists(p));
debug2!("Scrutinizing datestamp for {} - does it exist? {:?}", p.display(), os::path_exists(p));
let out = p.stat().map(|stat| stat.st_mtime);
debug2!("Date = {:?}", out);
out.map(|t| { t as libc::time_t })

View File

@ -98,15 +98,16 @@ pub fn parse_vers(vers: ~str) -> result::Result<semver::Version, ~str> {
pub fn try_getting_local_version(local_path: &Path) -> Option<Version> {
let rustpath = rust_path();
for rp in rustpath.iter() {
let local_path = rp.push_rel(local_path);
let git_dir = local_path.push(".git");
let local_path = rp.join_path(local_path);
let git_dir = local_path.join_str(".git");
if !os::path_is_dir(&git_dir) {
continue;
}
// FIXME (#9639): This needs to handle non-utf8 paths
let outp = run::process_output("git",
[format!("--git-dir={}", git_dir.to_str()), ~"tag", ~"-l"]);
["--git-dir=" + git_dir.as_str().unwrap(), ~"tag", ~"-l"]);
debug2!("git --git-dir={} tag -l ~~~> {:?}", git_dir.to_str(), outp.status);
debug2!("git --git-dir={} tag -l ~~~> {:?}", git_dir.display(), outp.status);
if outp.status != 0 {
continue;
@ -136,21 +137,23 @@ pub fn try_getting_version(remote_path: &Path) -> Option<Version> {
let tmp_dir = tmp_dir.expect("try_getting_version: couldn't create temp dir");
let tmp_dir = tmp_dir.path();
debug2!("(to get version) executing \\{git clone https://{} {}\\}",
remote_path.to_str(),
tmp_dir.to_str());
let outp = run::process_output("git", [~"clone",
format!("https://{}",
remote_path.to_str()),
tmp_dir.to_str()]);
remote_path.display(),
tmp_dir.display());
// FIXME (#9639): This needs to handle non-utf8 paths
let outp = run::process_output("git", [~"clone", format!("https://{}",
remote_path.as_str().unwrap()),
tmp_dir.as_str().unwrap().to_owned()]);
if outp.status == 0 {
debug2!("Cloned it... ( {}, {} )",
str::from_utf8(outp.output),
str::from_utf8(outp.error));
let mut output = None;
let git_dir = tmp_dir.join_str(".git");
debug2!("(getting version, now getting tags) executing \\{git --git-dir={} tag -l\\}",
tmp_dir.push(".git").to_str());
git_dir.display());
// FIXME (#9639): This needs to handle non-utf8 paths
let outp = run::process_output("git",
[format!("--git-dir={}", tmp_dir.push(".git").to_str()),
["--git-dir=" + git_dir.as_str().unwrap(),
~"tag", ~"-l"]);
let output_text = str::from_utf8(outp.output);
debug2!("Full output: ( {} ) [{:?}]", output_text, outp.status);
@ -203,8 +206,8 @@ pub fn try_parsing_version(s: &str) -> Option<Version> {
/// Just an approximation
fn is_url_like(p: &Path) -> bool {
let str = p.to_str();
str.split_iter('/').len() > 2
// check if there are more than 2 /-separated components
p.as_vec().split_iter(|b| *b == '/' as u8).nth(2).is_some()
}
/// If s is of the form foo#bar, where bar is a valid version

View File

@ -30,7 +30,12 @@ pub fn digest_file_with_date(path: &Path) -> ~str {
(*sha).input_str(st.st_mtime.to_str());
(*sha).result_str()
}
Err(e) => cond.raise((path.clone(), format!("Couldn't read file: {}", e))).to_str()
Err(e) => {
let path = cond.raise((path.clone(), format!("Couldn't read file: {}", e)));
// FIXME (#9639): This needs to handle non-utf8 paths
// XXX: I'm pretty sure this is the wrong return value
path.as_str().unwrap().to_owned()
}
}
}
@ -51,13 +56,15 @@ pub fn digest_only_date(path: &Path) -> ~str {
pub fn discover_outputs(e: &mut workcache::Exec, outputs: ~[Path]) {
debug2!("Discovering {:?} outputs", outputs.len());
for p in outputs.iter() {
debug2!("Discovering output! {}", p.to_str());
debug2!("Discovering output! {}", p.display());
// For now, assume that all discovered outputs are binaries
e.discover_output("binary", p.to_str(), digest_only_date(p));
// FIXME (#9639): This needs to handle non-utf8 paths
e.discover_output("binary", p.as_str().unwrap(), digest_only_date(p));
}
}
/// Returns the function name for building a crate
pub fn crate_tag(p: &Path) -> ~str {
p.to_str() // implicitly, it's "build(p)"...
// FIXME (#9639): This needs to handle non-utf8 paths
p.as_str().unwrap().to_owned() // implicitly, it's "build(p)"...
}

View File

@ -10,7 +10,7 @@
// rustpkg utilities having to do with workspaces
use std::{os,util};
use std::os;
use std::path::Path;
use context::Context;
use path_util::{workspace_contains_package_id, find_dir_using_rust_path_hack, default_workspace};
@ -26,8 +26,8 @@ pub fn each_pkg_parent_workspace(cx: &Context, pkgid: &PkgId, action: &fn(&Path)
// tjc: make this a condition
fail2!("Package {} not found in any of \
the following workspaces: {}",
pkgid.path.to_str(),
rust_path().to_str());
pkgid.path.display(),
rust_path().map(|p| p.to_display_str()).to_str());
}
for ws in workspaces.iter() {
if action(ws) {
@ -52,7 +52,7 @@ pub fn pkg_parent_workspaces(cx: &Context, pkgid: &PkgId) -> ~[Path] {
}
pub fn is_workspace(p: &Path) -> bool {
os::path_is_dir(&p.push("src"))
os::path_is_dir(&p.join_str("src"))
}
/// Construct a workspace and package-ID name based on the current directory.
@ -60,16 +60,13 @@ pub fn is_workspace(p: &Path) -> bool {
pub fn cwd_to_workspace() -> Option<(Path, PkgId)> {
let cwd = os::getcwd();
for path in rust_path().move_iter() {
let srcpath = path.push("src");
let srcpath = path.join_str("src");
if srcpath.is_ancestor_of(&cwd) {
// I'd love to use srcpath.get_relative_to(cwd) but it behaves wrong
// I'd say broken, but it has tests enforcing the wrong behavior.
// instead, just hack up the components vec
let mut pkgid = cwd;
pkgid.is_absolute = false;
let comps = util::replace(&mut pkgid.components, ~[]);
pkgid.components = comps.move_iter().skip(srcpath.components.len()).collect();
return Some((path, PkgId::new(pkgid.components.connect("/"))))
let rel = cwd.path_relative_from(&srcpath);
let rel_s = rel.and_then_ref(|p|p.as_str());
if rel_s.is_some() {
return Some((path, PkgId::new(rel_s.unwrap())));
}
}
}
None

View File

@ -60,12 +60,11 @@ use num;
use ops::Drop;
use option::{Some, None};
use os;
use path::Path;
use path::{Path,GenericPath};
use ptr;
use result::{Result, Ok, Err};
use str::{StrSlice, OwnedStr};
use str;
use to_str::ToStr;
use uint;
use vec::{MutableVector, ImmutableVector, OwnedVector, OwnedCopyableVector, CopyableVector};
use vec;
@ -1069,7 +1068,9 @@ pub fn file_reader(path: &Path) -> Result<@Reader, ~str> {
};
if f as uint == 0u {
Err(~"error opening " + path.to_str())
do path.with_display_str |p| {
Err(~"error opening " + p)
}
} else {
Ok(FILE_reader(f, true))
}
@ -1335,7 +1336,7 @@ pub fn mk_file_writer(path: &Path, flags: &[FileFlag])
}
};
if fd < (0 as c_int) {
Err(format!("error opening {}: {}", path.to_str(), os::last_os_error()))
Err(format!("error opening {}: {}", path.display(), os::last_os_error()))
} else {
Ok(fd_writer(fd, true))
}
@ -1752,7 +1753,7 @@ pub fn read_whole_file_str(file: &Path) -> Result<~str, ~str> {
if str::is_utf8(bytes) {
Ok(str::from_utf8(bytes))
} else {
Err(file.to_str() + " is not UTF-8")
Err(file.to_display_str() + " is not UTF-8")
}
}
}
@ -1892,8 +1893,8 @@ mod tests {
#[test]
fn test_simple() {
let tmpfile = &Path("tmp/lib-io-test-simple.tmp");
debug2!("{:?}", tmpfile);
let tmpfile = &Path::from_str("tmp/lib-io-test-simple.tmp");
debug2!("{}", tmpfile.display());
let frood: ~str =
~"A hoopy frood who really knows where his towel is.";
debug2!("{}", frood.clone());
@ -1910,7 +1911,7 @@ mod tests {
#[test]
fn test_each_byte_each_char_file() {
// Issue #5056 -- shouldn't include trailing EOF.
let path = Path("tmp/lib-io-test-each-byte-each-char-file.tmp");
let path = Path::from_str("tmp/lib-io-test-each-byte-each-char-file.tmp");
{
// create empty, enough to reproduce a problem
@ -2010,7 +2011,7 @@ mod tests {
#[test]
fn file_reader_not_exist() {
match io::file_reader(&Path("not a file")) {
match io::file_reader(&Path::from_str("not a file")) {
Err(e) => {
assert_eq!(e, ~"error opening not a file");
}
@ -2021,7 +2022,7 @@ mod tests {
#[test]
#[should_fail]
fn test_read_buffer_too_small() {
let path = &Path("tmp/lib-io-test-read-buffer-too-small.tmp");
let path = &Path::from_str("tmp/lib-io-test-read-buffer-too-small.tmp");
// ensure the file exists
io::file_writer(path, [io::Create]).unwrap();
@ -2032,7 +2033,7 @@ mod tests {
#[test]
fn test_read_buffer_big_enough() {
let path = &Path("tmp/lib-io-test-read-buffer-big-enough.tmp");
let path = &Path::from_str("tmp/lib-io-test-read-buffer-big-enough.tmp");
// ensure the file exists
io::file_writer(path, [io::Create]).unwrap();
@ -2043,7 +2044,7 @@ mod tests {
#[test]
fn test_write_empty() {
let file = io::file_writer(&Path("tmp/lib-io-test-write-empty.tmp"),
let file = io::file_writer(&Path::from_str("tmp/lib-io-test-write-empty.tmp"),
[io::Create]).unwrap();
file.write([]);
}
@ -2075,7 +2076,7 @@ mod tests {
#[test]
fn test_read_write_le() {
let path = Path("tmp/lib-io-test-read-write-le.tmp");
let path = Path::from_str("tmp/lib-io-test-read-write-le.tmp");
let uints = [0, 1, 2, 42, 10_123, 100_123_456, u64::max_value];
// write the ints to the file
@ -2097,7 +2098,7 @@ mod tests {
#[test]
fn test_read_write_be() {
let path = Path("tmp/lib-io-test-read-write-be.tmp");
let path = Path::from_str("tmp/lib-io-test-read-write-be.tmp");
let uints = [0, 1, 2, 42, 10_123, 100_123_456, u64::max_value];
// write the ints to the file
@ -2119,7 +2120,7 @@ mod tests {
#[test]
fn test_read_be_int_n() {
let path = Path("tmp/lib-io-test-read-be-int-n.tmp");
let path = Path::from_str("tmp/lib-io-test-read-be-int-n.tmp");
let ints = [i32::min_value, -123456, -42, -5, 0, 1, i32::max_value];
// write the ints to the file
@ -2143,7 +2144,7 @@ mod tests {
#[test]
fn test_read_f32() {
let path = Path("tmp/lib-io-test-read-f32.tmp");
let path = Path::from_str("tmp/lib-io-test-read-f32.tmp");
//big-endian floating-point 8.1250
let buf = ~[0x41, 0x02, 0x00, 0x00];
@ -2161,7 +2162,7 @@ mod tests {
#[test]
fn test_read_write_f32() {
let path = Path("tmp/lib-io-test-read-write-f32.tmp");
let path = Path::from_str("tmp/lib-io-test-read-write-f32.tmp");
let f:f32 = 8.1250;
{

View File

@ -28,7 +28,7 @@
#[allow(missing_doc)];
use c_str::ToCStr;
use c_str::{CString, ToCStr};
use clone::Clone;
use container::Container;
use io;
@ -78,22 +78,7 @@ pub fn getcwd() -> Path {
fail2!()
}
Path(str::raw::from_c_str(buf as *c_char))
}
}
}
// FIXME: move these to str perhaps? #2620
pub fn fill_charp_buf(f: &fn(*mut c_char, size_t) -> bool) -> Option<~str> {
let mut buf = [0 as c_char, .. TMPBUF_SZ];
do buf.as_mut_buf |b, sz| {
if f(b, sz as size_t) {
unsafe {
Some(str::raw::from_c_str(b as *c_char))
}
} else {
None
GenericPath::from_c_str(CString::new(buf as *c_char, false))
}
}
}
@ -451,70 +436,89 @@ pub fn dll_filename(base: &str) -> ~str {
pub fn self_exe_path() -> Option<Path> {
#[cfg(target_os = "freebsd")]
fn load_self() -> Option<~str> {
fn load_self() -> Option<~[u8]> {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
use libc::funcs::bsd44::*;
use libc::consts::os::extra::*;
do fill_charp_buf() |buf, sz| {
let mib = ~[CTL_KERN as c_int,
KERN_PROC as c_int,
KERN_PROC_PATHNAME as c_int, -1 as c_int];
let mut sz = sz;
let mib = ~[CTL_KERN as c_int,
KERN_PROC as c_int,
KERN_PROC_PATHNAME as c_int, -1 as c_int];
let mut sz: size_t = 0;
let err = sysctl(vec::raw::to_ptr(mib), mib.len() as ::libc::c_uint,
ptr::mut_null(), &mut sz, ptr::null(), 0u as size_t);
if err != 0 { return None; }
if sz == 0 { return None; }
let mut v: ~[u8] = vec::with_capacity(sz as uint);
let err = do v.as_mut_buf |buf,_| {
sysctl(vec::raw::to_ptr(mib), mib.len() as ::libc::c_uint,
buf as *mut c_void, &mut sz, ptr::null(),
0u as size_t) == (0 as c_int)
}
buf as *mut c_void, &mut sz, ptr::null(), 0u as size_t)
};
if err != 0 { return None; }
if sz == 0 { return None; }
vec::raw::set_len(&mut v, sz as uint - 1); // chop off trailing NUL
Some(v)
}
}
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
fn load_self() -> Option<~str> {
fn load_self() -> Option<~[u8]> {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
use libc::funcs::posix01::unistd::readlink;
let mut path = [0 as c_char, .. TMPBUF_SZ];
let mut path: ~[u8] = vec::with_capacity(TMPBUF_SZ);
do path.as_mut_buf |buf, len| {
let len = do "/proc/self/exe".with_c_str |proc_self_buf| {
readlink(proc_self_buf, buf, len as size_t) as uint
};
if len == -1 {
None
} else {
Some(str::raw::from_buf_len(buf as *u8, len))
let len = do path.as_mut_buf |buf, _| {
do "/proc/self/exe".with_c_str |proc_self_buf| {
readlink(proc_self_buf, buf as *mut c_char, TMPBUF_SZ as size_t) as uint
}
};
if len == -1 {
None
} else {
vec::raw::set_len(&mut path, len as uint);
Some(path)
}
}
}
#[cfg(target_os = "macos")]
fn load_self() -> Option<~str> {
fn load_self() -> Option<~[u8]> {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
do fill_charp_buf() |buf, sz| {
let mut sz = sz as u32;
libc::funcs::extra::_NSGetExecutablePath(
buf, &mut sz) == (0 as c_int)
}
use libc::funcs::extra::_NSGetExecutablePath;
let mut sz: u32 = 0;
_NSGetExecutablePath(ptr::mut_null(), &mut sz);
if sz == 0 { return None; }
let mut v: ~[u8] = vec::with_capacity(sz as uint);
let err = do v.as_mut_buf |buf,_| {
_NSGetExecutablePath(buf as *mut i8, &mut sz)
};
if err != 0 { return None; }
vec::raw::set_len(&mut v, sz as uint - 1); // chop off trailing NUL
Some(v)
}
}
#[cfg(windows)]
fn load_self() -> Option<~str> {
fn load_self() -> Option<~[u8]> {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
use os::win32::fill_utf16_buf_and_decode;
do fill_utf16_buf_and_decode() |buf, sz| {
libc::GetModuleFileNameW(0u as libc::DWORD, buf, sz)
}
}.map_move(|s| s.into_bytes())
}
}
load_self().map(|path| Path(path).dir_path())
load_self().and_then(|path| Path::from_vec_opt(path).map(|p| p.dir_path()))
}
/**
* Returns the path to the user's home directory, if known.
}
@ -532,13 +536,10 @@ pub fn self_exe_path() -> Option<Path> {
* Otherwise, homedir returns option::none.
*/
pub fn homedir() -> Option<Path> {
// FIXME (#7188): getenv needs a ~[u8] variant
return match getenv("HOME") {
Some(ref p) => if !p.is_empty() {
Some(Path(*p))
} else {
secondary()
},
None => secondary()
Some(ref p) if !p.is_empty() => Path::from_str_opt(*p),
_ => secondary()
};
#[cfg(unix)]
@ -550,7 +551,7 @@ pub fn homedir() -> Option<Path> {
fn secondary() -> Option<Path> {
do getenv("USERPROFILE").and_then |p| {
if !p.is_empty() {
Some(Path(p))
Path::from_str_opt(p)
} else {
None
}
@ -579,7 +580,7 @@ pub fn tmpdir() -> Path {
if x.is_empty() {
None
} else {
Some(Path(x))
Path::from_str_opt(x)
},
_ => None
}
@ -588,9 +589,9 @@ pub fn tmpdir() -> Path {
#[cfg(unix)]
fn lookup() -> Path {
if cfg!(target_os = "android") {
Path("/data/tmp")
Path::from_str("/data/tmp")
} else {
getenv_nonempty("TMPDIR").unwrap_or(Path("/tmp"))
getenv_nonempty("TMPDIR").unwrap_or(Path::from_str("/tmp"))
}
}
@ -599,7 +600,7 @@ pub fn tmpdir() -> Path {
getenv_nonempty("TMP").or(
getenv_nonempty("TEMP").or(
getenv_nonempty("USERPROFILE").or(
getenv_nonempty("WINDIR")))).unwrap_or(Path("C:\\Windows"))
getenv_nonempty("WINDIR")))).unwrap_or(Path::from_str("C:\\Windows"))
}
}
@ -607,7 +608,7 @@ pub fn tmpdir() -> Path {
pub fn walk_dir(p: &Path, f: &fn(&Path) -> bool) -> bool {
let r = list_dir(p);
r.iter().advance(|q| {
let path = &p.push(*q);
let path = &p.join_path(q);
f(path) && (!path_is_dir(path) || walk_dir(path, |p| f(p)))
})
}
@ -643,10 +644,12 @@ pub fn path_exists(p: &Path) -> bool {
// querying; what it does depends on the process working directory, not just
// the input paths.
pub fn make_absolute(p: &Path) -> Path {
if p.is_absolute {
(*p).clone()
if p.is_absolute() {
p.clone()
} else {
getcwd().push_many(p.components)
let mut ret = getcwd();
ret.push_path(p);
ret
}
}
@ -661,7 +664,7 @@ pub fn make_dir(p: &Path, mode: c_int) -> bool {
unsafe {
use os::win32::as_utf16_p;
// FIXME: turn mode into something useful? #2623
do as_utf16_p(p.to_str()) |buf| {
do as_utf16_p(p.as_str().unwrap()) |buf| {
libc::CreateDirectoryW(buf, ptr::mut_null())
!= (0 as libc::BOOL)
}
@ -690,38 +693,32 @@ pub fn mkdir_recursive(p: &Path, mode: c_int) -> bool {
if path_is_dir(p) {
return true;
}
else if p.components.is_empty() {
return false;
}
else if p.components.len() == 1 {
// No parent directories to create
path_is_dir(p) || make_dir(p, mode)
}
else {
mkdir_recursive(&p.pop(), mode) && make_dir(p, mode)
let mut p_ = p.clone();
if p_.pop().is_some() {
if !mkdir_recursive(&p_, mode) {
return false;
}
}
return make_dir(p, mode);
}
/// Lists the contents of a directory
pub fn list_dir(p: &Path) -> ~[~str] {
if p.components.is_empty() && !p.is_absolute() {
// Not sure what the right behavior is here, but this
// prevents a bounds check failure later
return ~[];
}
///
/// Each resulting Path is a relative path with no directory component.
pub fn list_dir(p: &Path) -> ~[Path] {
unsafe {
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "macos")]
unsafe fn get_list(p: &Path) -> ~[~str] {
unsafe fn get_list(p: &Path) -> ~[Path] {
#[fixed_stack_segment]; #[inline(never)];
use libc::{dirent_t};
use libc::{opendir, readdir, closedir};
extern {
fn rust_list_dir_val(ptr: *dirent_t) -> *libc::c_char;
}
let mut strings = ~[];
let mut paths = ~[];
debug2!("os::list_dir -- BEFORE OPENDIR");
let dir_ptr = do p.with_c_str |buf| {
@ -732,8 +729,8 @@ pub fn list_dir(p: &Path) -> ~[~str] {
debug2!("os::list_dir -- opendir() SUCCESS");
let mut entry_ptr = readdir(dir_ptr);
while (entry_ptr as uint != 0) {
strings.push(str::raw::from_c_str(rust_list_dir_val(
entry_ptr)));
let cstr = CString::new(rust_list_dir_val(entry_ptr), false);
paths.push(GenericPath::from_c_str(cstr));
entry_ptr = readdir(dir_ptr);
}
closedir(dir_ptr);
@ -741,11 +738,11 @@ pub fn list_dir(p: &Path) -> ~[~str] {
else {
debug2!("os::list_dir -- opendir() FAILURE");
}
debug2!("os::list_dir -- AFTER -- \\#: {}", strings.len());
strings
debug2!("os::list_dir -- AFTER -- \\#: {}", paths.len());
paths
}
#[cfg(windows)]
unsafe fn get_list(p: &Path) -> ~[~str] {
unsafe fn get_list(p: &Path) -> ~[Path] {
#[fixed_stack_segment]; #[inline(never)];
use libc::consts::os::extra::INVALID_HANDLE_VALUE;
use libc::{wcslen, free};
@ -765,9 +762,9 @@ pub fn list_dir(p: &Path) -> ~[~str] {
fn rust_list_dir_wfd_size() -> libc::size_t;
fn rust_list_dir_wfd_fp_buf(wfd: *libc::c_void) -> *u16;
}
fn star(p: &Path) -> Path { p.push("*") }
do as_utf16_p(star(p).to_str()) |path_ptr| {
let mut strings = ~[];
let star = p.join_str("*");
do as_utf16_p(star.as_str().unwrap()) |path_ptr| {
let mut paths = ~[];
let wfd_ptr = malloc_raw(rust_list_dir_wfd_size() as uint);
let find_handle = FindFirstFileW(path_ptr, wfd_ptr as HANDLE);
if find_handle as libc::c_int != INVALID_HANDLE_VALUE {
@ -781,18 +778,18 @@ pub fn list_dir(p: &Path) -> ~[~str] {
let fp_vec = vec::from_buf(
fp_buf, wcslen(fp_buf) as uint);
let fp_str = str::from_utf16(fp_vec);
strings.push(fp_str);
paths.push(Path::from_str(fp_str));
}
more_files = FindNextFileW(find_handle, wfd_ptr as HANDLE);
}
FindClose(find_handle);
free(wfd_ptr)
}
strings
paths
}
}
do get_list(p).move_iter().filter |filename| {
"." != *filename && ".." != *filename
do get_list(p).move_iter().filter |path| {
path.as_vec() != bytes!(".") && path.as_vec() != bytes!("..")
}.collect()
}
}
@ -803,7 +800,7 @@ pub fn list_dir(p: &Path) -> ~[~str] {
* This version prepends each entry with the directory.
*/
pub fn list_dir_path(p: &Path) -> ~[Path] {
list_dir(p).map(|f| p.push(*f))
list_dir(p).map(|f| p.join_path(f))
}
/// Removes a directory at the specified path, after removing
@ -838,7 +835,7 @@ pub fn remove_dir(p: &Path) -> bool {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
use os::win32::as_utf16_p;
return do as_utf16_p(p.to_str()) |buf| {
return do as_utf16_p(p.as_str().unwrap()) |buf| {
libc::RemoveDirectoryW(buf) != (0 as libc::BOOL)
};
}
@ -865,7 +862,7 @@ pub fn change_dir(p: &Path) -> bool {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
use os::win32::as_utf16_p;
return do as_utf16_p(p.to_str()) |buf| {
return do as_utf16_p(p.as_str().unwrap()) |buf| {
libc::SetCurrentDirectoryW(buf) != (0 as libc::BOOL)
};
}
@ -891,8 +888,8 @@ pub fn copy_file(from: &Path, to: &Path) -> bool {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
use os::win32::as_utf16_p;
return do as_utf16_p(from.to_str()) |fromp| {
do as_utf16_p(to.to_str()) |top| {
return do as_utf16_p(from.as_str().unwrap()) |fromp| {
do as_utf16_p(to.as_str().unwrap()) |top| {
libc::CopyFileW(fromp, top, (0 as libc::BOOL)) !=
(0 as libc::BOOL)
}
@ -968,7 +965,7 @@ pub fn remove_file(p: &Path) -> bool {
#[fixed_stack_segment]; #[inline(never)];
unsafe {
use os::win32::as_utf16_p;
return do as_utf16_p(p.to_str()) |buf| {
return do as_utf16_p(p.as_str().unwrap()) |buf| {
libc::DeleteFileW(buf) != (0 as libc::BOOL)
};
}
@ -1657,35 +1654,45 @@ pub mod consts {
pub static SYSNAME: &'static str = "macos";
pub static DLL_PREFIX: &'static str = "lib";
pub static DLL_SUFFIX: &'static str = ".dylib";
pub static DLL_EXTENSION: &'static str = "dylib";
pub static EXE_SUFFIX: &'static str = "";
pub static EXE_EXTENSION: &'static str = "";
}
pub mod freebsd {
pub static SYSNAME: &'static str = "freebsd";
pub static DLL_PREFIX: &'static str = "lib";
pub static DLL_SUFFIX: &'static str = ".so";
pub static DLL_EXTENSION: &'static str = "so";
pub static EXE_SUFFIX: &'static str = "";
pub static EXE_EXTENSION: &'static str = "";
}
pub mod linux {
pub static SYSNAME: &'static str = "linux";
pub static DLL_PREFIX: &'static str = "lib";
pub static DLL_SUFFIX: &'static str = ".so";
pub static DLL_EXTENSION: &'static str = "so";
pub static EXE_SUFFIX: &'static str = "";
pub static EXE_EXTENSION: &'static str = "";
}
pub mod android {
pub static SYSNAME: &'static str = "android";
pub static DLL_PREFIX: &'static str = "lib";
pub static DLL_SUFFIX: &'static str = ".so";
pub static DLL_EXTENSION: &'static str = "so";
pub static EXE_SUFFIX: &'static str = "";
pub static EXE_EXTENSION: &'static str = "";
}
pub mod win32 {
pub static SYSNAME: &'static str = "win32";
pub static DLL_PREFIX: &'static str = "";
pub static DLL_SUFFIX: &'static str = ".dll";
pub static DLL_EXTENSION: &'static str = "dll";
pub static EXE_SUFFIX: &'static str = ".exe";
pub static EXE_EXTENSION: &'static str = "exe";
}
@ -1790,7 +1797,7 @@ mod tests {
debug2!("{:?}", path.clone());
// Hard to test this function
assert!(path.is_absolute);
assert!(path.is_absolute());
}
#[test]
@ -1823,12 +1830,13 @@ mod tests {
#[test]
fn test() {
assert!((!Path("test-path").is_absolute));
assert!((!Path::from_str("test-path").is_absolute()));
debug2!("Current working directory: {}", getcwd().to_str());
let cwd = getcwd();
debug2!("Current working directory: {}", cwd.display());
debug2!("{:?}", make_absolute(&Path("test-path")));
debug2!("{:?}", make_absolute(&Path("/usr/bin")));
debug2!("{:?}", make_absolute(&Path::from_str("test-path")));
debug2!("{:?}", make_absolute(&Path::from_str("/usr/bin")));
}
#[test]
@ -1837,7 +1845,7 @@ mod tests {
let oldhome = getenv("HOME");
setenv("HOME", "/home/MountainView");
assert_eq!(os::homedir(), Some(Path("/home/MountainView")));
assert_eq!(os::homedir(), Some(Path::from_str("/home/MountainView")));
setenv("HOME", "");
assert!(os::homedir().is_none());
@ -1858,16 +1866,16 @@ mod tests {
assert!(os::homedir().is_none());
setenv("HOME", "/home/MountainView");
assert_eq!(os::homedir(), Some(Path("/home/MountainView")));
assert_eq!(os::homedir(), Some(Path::from_str("/home/MountainView")));
setenv("HOME", "");
setenv("USERPROFILE", "/home/MountainView");
assert_eq!(os::homedir(), Some(Path("/home/MountainView")));
assert_eq!(os::homedir(), Some(Path::from_str("/home/MountainView")));
setenv("HOME", "/home/MountainView");
setenv("USERPROFILE", "/home/PaloAlto");
assert_eq!(os::homedir(), Some(Path("/home/MountainView")));
assert_eq!(os::homedir(), Some(Path::from_str("/home/MountainView")));
for s in oldhome.iter() { setenv("HOME", *s) }
for s in olduserprofile.iter() { setenv("USERPROFILE", *s) }
@ -1875,18 +1883,20 @@ mod tests {
#[test]
fn tmpdir() {
assert!(!os::tmpdir().to_str().is_empty());
let p = os::tmpdir();
let s = p.as_str();
assert!(s.is_some() && s.unwrap() != ".");
}
// Issue #712
#[test]
fn test_list_dir_no_invalid_memory_access() {
os::list_dir(&Path("."));
os::list_dir(&Path::from_str("."));
}
#[test]
fn list_dir() {
let dirs = os::list_dir(&Path("."));
let dirs = os::list_dir(&Path::from_str("."));
// Just assuming that we've got some contents in the current directory
assert!(dirs.len() > 0u);
@ -1895,44 +1905,38 @@ mod tests {
}
}
#[test]
fn list_dir_empty_path() {
let dirs = os::list_dir(&Path(""));
assert!(dirs.is_empty());
}
#[test]
#[cfg(not(windows))]
fn list_dir_root() {
let dirs = os::list_dir(&Path("/"));
let dirs = os::list_dir(&Path::from_str("/"));
assert!(dirs.len() > 1);
}
#[test]
#[cfg(windows)]
fn list_dir_root() {
let dirs = os::list_dir(&Path("C:\\"));
let dirs = os::list_dir(&Path::from_str("C:\\"));
assert!(dirs.len() > 1);
}
#[test]
fn path_is_dir() {
assert!((os::path_is_dir(&Path("."))));
assert!((!os::path_is_dir(&Path("test/stdtest/fs.rs"))));
assert!((os::path_is_dir(&Path::from_str("."))));
assert!((!os::path_is_dir(&Path::from_str("test/stdtest/fs.rs"))));
}
#[test]
fn path_exists() {
assert!((os::path_exists(&Path("."))));
assert!((!os::path_exists(&Path(
assert!((os::path_exists(&Path::from_str("."))));
assert!((!os::path_exists(&Path::from_str(
"test/nonexistent-bogus-path"))));
}
#[test]
fn copy_file_does_not_exist() {
assert!(!os::copy_file(&Path("test/nonexistent-bogus-path"),
&Path("test/other-bogus-path")));
assert!(!os::path_exists(&Path("test/other-bogus-path")));
assert!(!os::copy_file(&Path::from_str("test/nonexistent-bogus-path"),
&Path::from_str("test/other-bogus-path")));
assert!(!os::path_exists(&Path::from_str("test/other-bogus-path")));
}
#[test]
@ -1942,9 +1946,8 @@ mod tests {
unsafe {
let tempdir = getcwd(); // would like to use $TMPDIR,
// doesn't seem to work on Linux
assert!((tempdir.to_str().len() > 0u));
let input = tempdir.push("in.txt");
let out = tempdir.push("out.txt");
let input = tempdir.join_str("in.txt");
let out = tempdir.join_str("out.txt");
/* Write the temp input file */
let ostream = do input.with_c_str |fromp| {
@ -1965,10 +1968,12 @@ mod tests {
let in_mode = input.get_mode();
let rs = os::copy_file(&input, &out);
if (!os::path_exists(&input)) {
fail2!("{} doesn't exist", input.to_str());
fail2!("{} doesn't exist", input.display());
}
assert!((rs));
let rslt = run::process_status("diff", [input.to_str(), out.to_str()]);
// FIXME (#9639): This needs to handle non-utf8 paths
let rslt = run::process_status("diff", [input.as_str().unwrap().to_owned(),
out.as_str().unwrap().to_owned()]);
assert_eq!(rslt, 0);
assert_eq!(out.get_mode(), in_mode);
assert!((remove_file(&input)));
@ -1978,16 +1983,10 @@ mod tests {
#[test]
fn recursive_mkdir_slash() {
let path = Path("/");
let path = Path::from_str("/");
assert!(os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
}
#[test]
fn recursive_mkdir_empty() {
let path = Path("");
assert!(!os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
}
#[test]
fn memory_map_rw() {
use result::{Ok, Err};
@ -2032,7 +2031,8 @@ mod tests {
}
}
let path = tmpdir().push("mmap_file.tmp");
let mut path = tmpdir();
path.push_str("mmap_file.tmp");
let size = MemoryMap::granularity() * 2;
remove_file(&path);

File diff suppressed because it is too large Load Diff

View File

@ -19,7 +19,7 @@ use option::{Option, None, Some};
use str;
use str::{OwnedStr, Str, StrSlice};
use vec;
use vec::{CopyableVector, OwnedCopyableVector, OwnedVector};
use vec::{CopyableVector, OwnedCopyableVector, OwnedVector, Vector};
use vec::{ImmutableEqVector, ImmutableVector};
/// Typedef for POSIX file paths.
@ -37,20 +37,31 @@ pub use Path = self::posix::Path;
#[cfg(windows)]
pub use Path = self::windows::Path;
/// Typedef for the POSIX path component iterator.
/// See `posix::ComponentIter` for more info.
pub use PosixComponentIter = self::posix::ComponentIter;
/// Typedef for the Windows path component iterator.
/// See `windows::ComponentIter` for more info.
pub use WindowsComponentIter = self::windows::ComponentIter;
/// Typedef for the platform-native component iterator
#[cfg(unix)]
pub use ComponentIter = self::posix::ComponentIter;
/// Typedef for the platform-native reverse component iterator
#[cfg(unix)]
pub use RevComponentIter = self::posix::RevComponentIter;
/// Typedef for the platform-native component iterator
#[cfg(windows)]
pub use ComponentIter = self::windows::ComponentIter;
/// Typedef for the platform-native reverse component iterator
#[cfg(windows)]
pub use RevComponentIter = self::windows::RevComponentIter;
/// Typedef for the platform-native str component iterator
#[cfg(unix)]
pub use StrComponentIter = self::posix::StrComponentIter;
/// Typedef for the platform-native reverse str component iterator
#[cfg(unix)]
pub use RevStrComponentIter = self::posix::RevStrComponentIter;
/// Typedef for the platform-native str component iterator
#[cfg(windows)]
pub use StrComponentIter = self::windows::StrComponentIter;
/// Typedef for the platform-native reverse str component iterator
#[cfg(windows)]
pub use RevStrComponentIter = self::windows::RevStrComponentIter;
pub mod posix;
pub mod windows;
@ -128,7 +139,10 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
#[inline]
fn from_c_str(path: CString) -> Self {
// CStrings can't contain NULs
unsafe { GenericPathUnsafe::from_vec_unchecked(path.as_bytes()) }
let v = path.as_bytes();
// v is NUL-terminated. Strip it off
let v = v.slice_to(v.len()-1);
unsafe { GenericPathUnsafe::from_vec_unchecked(v) }
}
/// Returns the path as a string, if possible.
@ -146,7 +160,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
/// If the path is not UTF-8, invalid sequences will be replaced with the unicode
/// replacement char. This involves allocation.
#[inline]
fn as_display_str<T>(&self, f: &fn(&str) -> T) -> T {
fn with_display_str<T>(&self, f: &fn(&str) -> T) -> T {
match self.as_str() {
Some(s) => f(s),
None => {
@ -161,29 +175,37 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
/// If the path is not UTF-8, invalid sequences will be replaced with the unicode
/// replacement char. This involves allocation.
///
/// This is similar to `as_display_str()` except it will always allocate a new ~str.
/// This is similar to `with_display_str()` except it will always allocate a new ~str.
fn to_display_str(&self) -> ~str {
// FIXME (#9516): Don't decode utf-8 manually here once we have a good way to do it in str
// This is a truly horrifically bad implementation, done as a functionality stopgap until
// we have a proper utf-8 decoder. I don't really want to write one here.
static REPLACEMENT_CHAR: char = '\uFFFD';
from_utf8_with_replacement(self.as_vec())
}
let mut v = self.as_vec();
let mut s = str::with_capacity(v.len());
while !v.is_empty() {
let w = str::utf8_char_width(v[0]);
if w == 0u {
s.push_char(REPLACEMENT_CHAR);
v = v.slice_from(1);
} else if v.len() < w || !str::is_utf8(v.slice_to(w)) {
s.push_char(REPLACEMENT_CHAR);
v = v.slice_from(1);
} else {
s.push_str(unsafe { ::cast::transmute(v.slice_to(w)) });
v = v.slice_from(w);
/// Provides the filename as a string
///
/// If the filename is not UTF-8, invalid sequences will be replaced with the unicode
/// replacement char. This involves allocation.
#[inline]
fn with_filename_display_str<T>(&self, f: &fn(Option<&str>) -> T) -> T {
match self.filename_str() {
s@Some(_) => f(s),
None => {
let o = self.to_filename_display_str();
f(o.map(|s|s.as_slice()))
}
}
s
}
/// Returns the filename as a string
///
/// If the filename is not UTF-8, invalid sequences will be replaced with the unicode
/// replacement char. This involves allocation.
///
/// This is similar to `to_filename_display_str` except it will always allocate a new ~str.
fn to_filename_display_str(&self) -> Option<~str> {
match self.filename() {
None => None,
Some(v) => Some(from_utf8_with_replacement(v))
}
}
/// Returns an object that implements `fmt::Default` for printing paths
@ -211,51 +233,59 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
str::from_utf8_slice_opt(self.dirname())
}
/// Returns the file component of `self`, as a byte vector.
/// If `self` represents the root of the file hierarchy, returns the empty vector.
/// If `self` is ".", returns the empty vector.
fn filename<'a>(&'a self) -> &'a [u8];
/// If `self` represents the root of the file hierarchy, returns None.
/// If `self` is "." or "..", returns None.
fn filename<'a>(&'a self) -> Option<&'a [u8]>;
/// Returns the file component of `self`, as a string, if possible.
/// See `filename` for details.
#[inline]
fn filename_str<'a>(&'a self) -> Option<&'a str> {
str::from_utf8_slice_opt(self.filename())
self.filename().and_then(str::from_utf8_slice_opt)
}
/// Returns the stem of the filename of `self`, as a byte vector.
/// The stem is the portion of the filename just before the last '.'.
/// If there is no '.', the entire filename is returned.
fn filestem<'a>(&'a self) -> &'a [u8] {
let name = self.filename();
let dot = '.' as u8;
match name.rposition_elem(&dot) {
None | Some(0) => name,
Some(1) if name == bytes!("..") => name,
Some(pos) => name.slice_to(pos)
fn filestem<'a>(&'a self) -> Option<&'a [u8]> {
match self.filename() {
None => None,
Some(name) => Some({
let dot = '.' as u8;
match name.rposition_elem(&dot) {
None | Some(0) => name,
Some(1) if name == bytes!("..") => name,
Some(pos) => name.slice_to(pos)
}
})
}
}
/// Returns the stem of the filename of `self`, as a string, if possible.
/// See `filestem` for details.
#[inline]
fn filestem_str<'a>(&'a self) -> Option<&'a str> {
str::from_utf8_slice_opt(self.filestem())
self.filestem().and_then(str::from_utf8_slice_opt)
}
/// Returns the extension of the filename of `self`, as an optional byte vector.
/// The extension is the portion of the filename just after the last '.'.
/// If there is no extension, None is returned.
/// If the filename ends in '.', the empty vector is returned.
fn extension<'a>(&'a self) -> Option<&'a [u8]> {
let name = self.filename();
let dot = '.' as u8;
match name.rposition_elem(&dot) {
None | Some(0) => None,
Some(1) if name == bytes!("..") => None,
Some(pos) => Some(name.slice_from(pos+1))
match self.filename() {
None => None,
Some(name) => {
let dot = '.' as u8;
match name.rposition_elem(&dot) {
None | Some(0) => None,
Some(1) if name == bytes!("..") => None,
Some(pos) => Some(name.slice_from(pos+1))
}
}
}
}
/// Returns the extension of the filename of `self`, as a string, if possible.
/// See `extension` for details.
#[inline]
fn extension_str<'a>(&'a self) -> Option<&'a str> {
self.extension().and_then(|v| str::from_utf8_slice_opt(v))
self.extension().and_then(str::from_utf8_slice_opt)
}
/// Replaces the directory portion of the path with the given byte vector.
@ -322,27 +352,30 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
fn set_filestem(&mut self, filestem: &[u8]) {
// borrowck is being a pain here
let val = {
let name = self.filename();
if !name.is_empty() {
let dot = '.' as u8;
match name.rposition_elem(&dot) {
None | Some(0) => None,
Some(idx) => {
let mut v;
if contains_nul(filestem) {
let filestem = self::null_byte::cond.raise(filestem.to_owned());
assert!(!contains_nul(filestem));
v = vec::with_capacity(filestem.len() + name.len() - idx);
v.push_all(filestem);
} else {
v = vec::with_capacity(filestem.len() + name.len() - idx);
v.push_all(filestem);
match self.filename() {
None => None,
Some(name) => {
let dot = '.' as u8;
match name.rposition_elem(&dot) {
None | Some(0) => None,
Some(idx) => {
let mut v;
if contains_nul(filestem) {
let filestem = self::null_byte::cond.raise(filestem.to_owned());
assert!(!contains_nul(filestem));
v = filestem;
let n = v.len();
v.reserve(n + name.len() - idx);
} else {
v = vec::with_capacity(filestem.len() + name.len() - idx);
v.push_all(filestem);
}
v.push_all(name.slice_from(idx));
Some(v)
}
v.push_all(name.slice_from(idx));
Some(v)
}
}
} else { None }
}
};
match val {
None => self.set_filename(filestem),
@ -366,52 +399,56 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
fn set_extension(&mut self, extension: &[u8]) {
// borrowck causes problems here too
let val = {
let name = self.filename();
if !name.is_empty() {
let dot = '.' as u8;
match name.rposition_elem(&dot) {
None | Some(0) => {
if extension.is_empty() {
None
} else {
let mut v;
if contains_nul(extension) {
let extension = self::null_byte::cond.raise(extension.to_owned());
assert!(!contains_nul(extension));
v = vec::with_capacity(name.len() + extension.len() + 1);
v.push_all(name);
v.push(dot);
v.push_all(extension);
match self.filename() {
None => None,
Some(name) => {
let dot = '.' as u8;
match name.rposition_elem(&dot) {
None | Some(0) => {
if extension.is_empty() {
None
} else {
v = vec::with_capacity(name.len() + extension.len() + 1);
v.push_all(name);
v.push(dot);
v.push_all(extension);
let mut v;
if contains_nul(extension) {
let ext = extension.to_owned();
let extension = self::null_byte::cond.raise(ext);
assert!(!contains_nul(extension));
v = vec::with_capacity(name.len() + extension.len() + 1);
v.push_all(name);
v.push(dot);
v.push_all(extension);
} else {
v = vec::with_capacity(name.len() + extension.len() + 1);
v.push_all(name);
v.push(dot);
v.push_all(extension);
}
Some(v)
}
Some(v)
}
}
Some(idx) => {
if extension.is_empty() {
Some(name.slice_to(idx).to_owned())
} else {
let mut v;
if contains_nul(extension) {
let extension = self::null_byte::cond.raise(extension.to_owned());
assert!(!contains_nul(extension));
v = vec::with_capacity(idx + extension.len() + 1);
v.push_all(name.slice_to(idx+1));
v.push_all(extension);
Some(idx) => {
if extension.is_empty() {
Some(name.slice_to(idx).to_owned())
} else {
v = vec::with_capacity(idx + extension.len() + 1);
v.push_all(name.slice_to(idx+1));
v.push_all(extension);
let mut v;
if contains_nul(extension) {
let ext = extension.to_owned();
let extension = self::null_byte::cond.raise(ext);
assert!(!contains_nul(extension));
v = vec::with_capacity(idx + extension.len() + 1);
v.push_all(name.slice_to(idx+1));
v.push_all(extension);
} else {
v = vec::with_capacity(idx + extension.len() + 1);
v.push_all(name.slice_to(idx+1));
v.push_all(extension);
}
Some(v)
}
Some(v)
}
}
}
} else { None }
}
};
match val {
None => (),
@ -424,6 +461,52 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
fn set_extension_str(&mut self, extension: &str) {
self.set_extension(extension.as_bytes())
}
/// Adds the given extension (as a byte vector) to the file.
/// This does not remove any existing extension.
/// `foo.bar`.add_extension(`baz`) becomes `foo.bar.baz`.
/// If `self` has no filename, this is a no-op.
/// If the given byte vector is [], this is a no-op.
///
/// # Failure
///
/// Raises the `null_byte` condition if the extension contains a NUL.
fn add_extension(&mut self, extension: &[u8]) {
if extension.is_empty() { return; }
// appease borrowck
let val = {
match self.filename() {
None => None,
Some(name) => {
let mut v;
if contains_nul(extension) {
let ext = extension.to_owned();
let extension = self::null_byte::cond.raise(ext);
assert!(!contains_nul(extension));
v = vec::with_capacity(name.len() + 1 + extension.len());
v.push_all(name);
v.push('.' as u8);
v.push_all(extension);
} else {
v = vec::with_capacity(name.len() + 1 + extension.len());
v.push_all(name);
v.push('.' as u8);
v.push_all(extension);
}
Some(v)
}
}
};
match val {
None => (),
Some(v) => unsafe { self.set_filename_unchecked(v) }
}
}
/// Adds the given extension (as a string) to the file.
/// See `add_extension` for details.
#[inline]
fn add_extension_str(&mut self, extension: &str) {
self.add_extension(extension.as_bytes())
}
/// Returns a new Path constructed by replacing the dirname with the given byte vector.
/// See `set_dirname` for details.
@ -516,12 +599,14 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
/// If `self` represents the root of the filesystem hierarchy, returns None.
fn file_path(&self) -> Option<Self> {
// self.filename() returns a NUL-free vector
match self.filename() {
[] => None,
v => Some(unsafe { GenericPathUnsafe::from_vec_unchecked(v) })
}
self.filename().map_move(|v| unsafe { GenericPathUnsafe::from_vec_unchecked(v) })
}
/// Returns a Path that represents the filesystem root that `self` is rooted in.
///
/// If `self` is not absolute, or vol-relative in the case of Windows, this returns None.
fn root_path(&self) -> Option<Self>;
/// Pushes a path (as a byte vector) onto `self`.
/// If the argument represents an absolute path, it replaces `self`.
///
@ -554,6 +639,21 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
fn push_path(&mut self, path: &Self) {
self.push(path.as_vec())
}
/// Pushes multiple paths (as byte vectors) onto `self`.
/// See `push` for details.
#[inline]
fn push_many<V: Vector<u8>>(&mut self, paths: &[V]) {
for p in paths.iter() {
self.push(p.as_slice());
}
}
/// Pushes multiple paths (as strings) onto `self`.
#[inline]
fn push_many_str<S: Str>(&mut self, paths: &[S]) {
for p in paths.iter() {
self.push_str(p.as_slice());
}
}
/// Pops the last path component off of `self` and returns it.
/// If `self` represents the root of the file hierarchy, None is returned.
fn pop(&mut self) -> Option<~[u8]>;
@ -593,12 +693,36 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
p.push_path(path);
p
}
/// Returns a new Path constructed by joining `self` with the given paths (as byte vectors).
/// See `join` for details.
#[inline]
fn join_many<V: Vector<u8>>(&self, paths: &[V]) -> Self {
let mut p = self.clone();
p.push_many(paths);
p
}
/// Returns a new Path constructed by joining `self` with the given paths (as strings).
/// See `join` for details.
#[inline]
fn join_many_str<S: Str>(&self, paths: &[S]) -> Self {
let mut p = self.clone();
p.push_many_str(paths);
p
}
/// Returns whether `self` represents an absolute path.
/// An absolute path is defined as one that, when joined to another path, will
/// yield back the same absolute path.
fn is_absolute(&self) -> bool;
/// Returns whether `self` represents a relative path.
/// Typically this is the inverse of `is_absolute`.
/// But for Windows paths, it also means the path is not volume-relative or
/// relative to the current working directory.
fn is_relative(&self) -> bool {
!self.is_absolute()
}
/// Returns whether `self` is equal to, or is an ancestor of, the given path.
/// If both paths are relative, they are compared as though they are relative
/// to the same parent path.
@ -707,6 +831,30 @@ fn contains_nul(v: &[u8]) -> bool {
v.iter().any(|&x| x == 0)
}
#[inline(always)]
fn from_utf8_with_replacement(mut v: &[u8]) -> ~str {
// FIXME (#9516): Don't decode utf-8 manually here once we have a good way to do it in str
// This is a truly horrifically bad implementation, done as a functionality stopgap until
// we have a proper utf-8 decoder. I don't really want to write one here.
static REPLACEMENT_CHAR: char = '\uFFFD';
let mut s = str::with_capacity(v.len());
while !v.is_empty() {
let w = str::utf8_char_width(v[0]);
if w == 0u {
s.push_char(REPLACEMENT_CHAR);
v = v.slice_from(1);
} else if v.len() < w || !str::is_utf8(v.slice_to(w)) {
s.push_char(REPLACEMENT_CHAR);
v = v.slice_from(1);
} else {
s.push_str(unsafe { ::cast::transmute(v.slice_to(w)) });
v = v.slice_from(w);
}
}
s
}
// FIXME (#9537): libc::stat should derive Default
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
@ -927,3 +1075,20 @@ mod stat {
}
}
}
#[cfg(test)]
mod tests {
use super::{GenericPath, PosixPath, WindowsPath};
use c_str::ToCStr;
#[test]
fn test_from_c_str() {
let input = "/foo/bar/baz";
let path: PosixPath = GenericPath::from_c_str(input.to_c_str());
assert_eq!(path.as_vec(), input.as_bytes());
let input = "\\foo\\bar\\baz";
let path: WindowsPath = GenericPath::from_c_str(input.to_c_str());
assert_eq!(path.as_str().unwrap(), input);
}
}

View File

@ -15,22 +15,30 @@ use c_str::{CString, ToCStr};
use clone::Clone;
use cmp::Eq;
use from_str::FromStr;
use iter::{AdditiveIterator, Extendable, Iterator};
use iter::{AdditiveIterator, Extendable, Iterator, Map};
use option::{Option, None, Some};
use str;
use str::Str;
use to_bytes::IterBytes;
use util;
use vec;
use vec::CopyableVector;
use vec::{Vector, VectorVector};
use vec::{CopyableVector, RSplitIterator, SplitIterator, Vector, VectorVector};
use super::{GenericPath, GenericPathUnsafe};
#[cfg(not(target_os = "win32"))]
use libc;
/// Iterator that yields successive components of a Path
pub type ComponentIter<'self> = vec::SplitIterator<'self, u8>;
/// Iterator that yields successive components of a Path as &[u8]
pub type ComponentIter<'self> = SplitIterator<'self, u8>;
/// Iterator that yields components of a Path in reverse as &[u8]
pub type RevComponentIter<'self> = RSplitIterator<'self, u8>;
/// Iterator that yields successive components of a Path as Option<&str>
pub type StrComponentIter<'self> = Map<'self, &'self [u8], Option<&'self str>,
ComponentIter<'self>>;
/// Iterator that yields components of a Path in reverse as Option<&str>
pub type RevStrComponentIter<'self> = Map<'self, &'self [u8], Option<&'self str>,
RevComponentIter<'self>>;
/// Represents a POSIX file path
#[deriving(Clone, DeepClone)]
@ -187,12 +195,13 @@ impl GenericPath for Path {
}
}
fn filename<'a>(&'a self) -> &'a [u8] {
fn filename<'a>(&'a self) -> Option<&'a [u8]> {
match self.sepidx {
None if bytes!(".") == self.repr || bytes!("..") == self.repr => &[],
None => self.repr.as_slice(),
Some(idx) if self.repr.slice_from(idx+1) == bytes!("..") => &[],
Some(idx) => self.repr.slice_from(idx+1)
None if bytes!(".") == self.repr || bytes!("..") == self.repr => None,
None => Some(self.repr.as_slice()),
Some(idx) if self.repr.slice_from(idx+1) == bytes!("..") => None,
Some(0) if self.repr.slice_from(1).is_empty() => None,
Some(idx) => Some(self.repr.slice_from(idx+1))
}
}
@ -219,6 +228,14 @@ impl GenericPath for Path {
}
}
fn root_path(&self) -> Option<Path> {
if self.is_absolute() {
Some(Path::from_str("/"))
} else {
None
}
}
#[inline]
fn is_absolute(&self) -> bool {
self.repr[0] == sep
@ -384,6 +401,48 @@ impl Path {
}
ret
}
/// Returns an iterator that yields each component of the path in reverse.
/// See component_iter() for details.
pub fn rev_component_iter<'a>(&'a self) -> RevComponentIter<'a> {
let v = if self.repr[0] == sep {
self.repr.slice_from(1)
} else { self.repr.as_slice() };
let mut ret = v.rsplit_iter(is_sep);
if v.is_empty() {
// consume the empty "" component
ret.next();
}
ret
}
/// Returns an iterator that yields each component of the path as Option<&str>.
/// See component_iter() for details.
pub fn str_component_iter<'a>(&'a self) -> StrComponentIter<'a> {
self.component_iter().map(str::from_utf8_slice_opt)
}
/// Returns an iterator that yields each component of the path in reverse as Option<&str>.
/// See component_iter() for details.
pub fn rev_str_component_iter<'a>(&'a self) -> RevStrComponentIter<'a> {
self.rev_component_iter().map(str::from_utf8_slice_opt)
}
/// Returns whether the relative path `child` is a suffix of `self`.
pub fn ends_with_path(&self, child: &Path) -> bool {
if !child.is_relative() { return false; }
let mut selfit = self.rev_component_iter();
let mut childit = child.rev_component_iter();
loop {
match (selfit.next(), childit.next()) {
(Some(a), Some(b)) => if a != b { return false; },
(Some(_), None) => break,
(None, Some(_)) => return false,
(None, None) => break
}
}
true
}
}
// None result means the byte vector didn't need normalizing
@ -422,8 +481,8 @@ fn contains_nul(v: &[u8]) -> bool {
v.iter().any(|&x| x == 0)
}
static dot_static: &'static [u8] = &'static ['.' as u8];
static dot_dot_static: &'static [u8] = &'static ['.' as u8, '.' as u8];
static dot_static: &'static [u8] = bytes!(".");
static dot_dot_static: &'static [u8] = bytes!("..");
// Stat support
#[cfg(not(target_os = "win32"))]
@ -524,7 +583,7 @@ impl Path {
#[cfg(test)]
mod tests {
use super::*;
use option::{Some, None};
use option::{Option, Some, None};
use iter::Iterator;
use str;
use vec::Vector;
@ -604,7 +663,7 @@ mod tests {
#[test]
fn test_null_byte() {
use path2::null_byte::cond;
use path::null_byte::cond;
let mut handled = false;
let mut p = do cond.trap(|v| {
@ -653,7 +712,7 @@ mod tests {
#[test]
fn test_null_byte_fail() {
use path2::null_byte::cond;
use path::null_byte::cond;
use task;
macro_rules! t(
@ -709,25 +768,47 @@ mod tests {
assert_eq!(Path::from_str("foo").to_display_str(), ~"foo");
assert_eq!(Path::from_vec(b!("foo", 0x80)).to_display_str(), ~"foo\uFFFD");
assert_eq!(Path::from_vec(b!("foo", 0xff, "bar")).to_display_str(), ~"foo\uFFFDbar");
assert_eq!(Path::from_vec(b!("foo", 0xff, "/bar")).to_filename_display_str(), Some(~"bar"));
assert_eq!(Path::from_vec(b!("foo/", 0xff, "bar")).to_filename_display_str(),
Some(~"\uFFFDbar"));
assert_eq!(Path::from_vec(b!("/")).to_filename_display_str(), None);
let mut called = false;
do Path::from_str("foo").as_display_str |s| {
do Path::from_str("foo").with_display_str |s| {
assert_eq!(s, "foo");
called = true;
};
assert!(called);
called = false;
do Path::from_vec(b!("foo", 0x80)).as_display_str |s| {
do Path::from_vec(b!("foo", 0x80)).with_display_str |s| {
assert_eq!(s, "foo\uFFFD");
called = true;
};
assert!(called);
called = false;
do Path::from_vec(b!("foo", 0xff, "bar")).as_display_str |s| {
do Path::from_vec(b!("foo", 0xff, "bar")).with_display_str |s| {
assert_eq!(s, "foo\uFFFDbar");
called = true;
};
assert!(called);
called = false;
do Path::from_vec(b!("foo", 0xff, "/bar")).with_filename_display_str |s| {
assert_eq!(s, Some("bar"));
called = true;
}
assert!(called);
called = false;
do Path::from_vec(b!("foo/", 0xff, "bar")).with_filename_display_str |s| {
assert_eq!(s, Some("\uFFFDbar"));
called = true;
}
assert!(called);
called = false;
do Path::from_vec(b!("/")).with_filename_display_str |s| {
assert!(s.is_none());
called = true;
}
assert!(called);
}
#[test]
@ -774,20 +855,20 @@ mod tests {
let path = Path::from_vec($path);
assert_eq!(path.$op(), $exp);
}
)
);
)
t!(v: b!("a/b/c"), filename, b!("c"));
t!(v: b!("a/b/c", 0xff), filename, b!("c", 0xff));
t!(v: b!("a/b", 0xff, "/c"), filename, b!("c"));
t!(s: "a/b/c", filename, "c");
t!(s: "/a/b/c", filename, "c");
t!(s: "a", filename, "a");
t!(s: "/a", filename, "a");
t!(s: ".", filename, "");
t!(s: "/", filename, "");
t!(s: "..", filename, "");
t!(s: "../..", filename, "");
t!(v: b!("a/b/c"), filename, Some(b!("c")));
t!(v: b!("a/b/c", 0xff), filename, Some(b!("c", 0xff)));
t!(v: b!("a/b", 0xff, "/c"), filename, Some(b!("c")));
t!(s: "a/b/c", filename, Some("c"), opt);
t!(s: "/a/b/c", filename, Some("c"), opt);
t!(s: "a", filename, Some("a"), opt);
t!(s: "/a", filename, Some("a"), opt);
t!(s: ".", filename, None, opt);
t!(s: "/", filename, None, opt);
t!(s: "..", filename, None, opt);
t!(s: "../..", filename, None, opt);
t!(v: b!("a/b/c"), dirname, b!("a/b"));
t!(v: b!("a/b/c", 0xff), dirname, b!("a/b"));
@ -801,21 +882,21 @@ mod tests {
t!(s: "..", dirname, "..");
t!(s: "../..", dirname, "../..");
t!(v: b!("hi/there.txt"), filestem, b!("there"));
t!(v: b!("hi/there", 0x80, ".txt"), filestem, b!("there", 0x80));
t!(v: b!("hi/there.t", 0x80, "xt"), filestem, b!("there"));
t!(s: "hi/there.txt", filestem, "there");
t!(s: "hi/there", filestem, "there");
t!(s: "there.txt", filestem, "there");
t!(s: "there", filestem, "there");
t!(s: ".", filestem, "");
t!(s: "/", filestem, "");
t!(s: "foo/.bar", filestem, ".bar");
t!(s: ".bar", filestem, ".bar");
t!(s: "..bar", filestem, ".");
t!(s: "hi/there..txt", filestem, "there.");
t!(s: "..", filestem, "");
t!(s: "../..", filestem, "");
t!(v: b!("hi/there.txt"), filestem, Some(b!("there")));
t!(v: b!("hi/there", 0x80, ".txt"), filestem, Some(b!("there", 0x80)));
t!(v: b!("hi/there.t", 0x80, "xt"), filestem, Some(b!("there")));
t!(s: "hi/there.txt", filestem, Some("there"), opt);
t!(s: "hi/there", filestem, Some("there"), opt);
t!(s: "there.txt", filestem, Some("there"), opt);
t!(s: "there", filestem, Some("there"), opt);
t!(s: ".", filestem, None, opt);
t!(s: "/", filestem, None, opt);
t!(s: "foo/.bar", filestem, Some(".bar"), opt);
t!(s: ".bar", filestem, Some(".bar"), opt);
t!(s: "..bar", filestem, Some("."), opt);
t!(s: "hi/there..txt", filestem, Some("there."), opt);
t!(s: "..", filestem, None, opt);
t!(s: "../..", filestem, None, opt);
t!(v: b!("hi/there.txt"), extension, Some(b!("txt")));
t!(v: b!("hi/there", 0x80, ".txt"), extension, Some(b!("txt")));
@ -878,6 +959,39 @@ mod tests {
t!(s: "a/b", "../c", "a/c");
}
#[test]
fn test_push_many() {
use to_man = at_vec::to_managed_move;
macro_rules! t(
(s: $path:expr, $push:expr, $exp:expr) => (
{
let mut p = Path::from_str($path);
p.push_many_str($push);
assert_eq!(p.as_str(), Some($exp));
}
);
(v: $path:expr, $push:expr, $exp:expr) => (
{
let mut p = Path::from_vec($path);
p.push_many($push);
assert_eq!(p.as_vec(), $exp);
}
)
)
t!(s: "a/b/c", ["d", "e"], "a/b/c/d/e");
t!(s: "a/b/c", ["d", "/e"], "/e");
t!(s: "a/b/c", ["d", "/e", "f"], "/e/f");
t!(s: "a/b/c", [~"d", ~"e"], "a/b/c/d/e");
t!(s: "a/b/c", [@"d", @"e"], "a/b/c/d/e");
t!(v: b!("a/b/c"), [b!("d"), b!("e")], b!("a/b/c/d/e"));
t!(v: b!("a/b/c"), [b!("d"), b!("/e"), b!("f")], b!("/e/f"));
t!(v: b!("a/b/c"), [b!("d").to_owned(), b!("e").to_owned()], b!("a/b/c/d/e"));
t!(v: b!("a/b/c"), [to_man(b!("d").to_owned()), to_man(b!("e").to_owned())],
b!("a/b/c/d/e"));
}
#[test]
fn test_pop() {
macro_rules! t(
@ -926,6 +1040,12 @@ mod tests {
assert_eq!(Path::from_vec(b!("foo", 0x80, "/bar")).pop_str(), Some(~"bar"));
}
#[test]
fn test_root_path() {
assert_eq!(Path::from_vec(b!("a/b/c")).root_path(), None);
assert_eq!(Path::from_vec(b!("/a/b/c")).root_path(), Some(Path::from_str("/")));
}
#[test]
fn test_join() {
t!(v: Path::from_vec(b!("a/b/c")).join(b!("..")), b!("a/b"));
@ -960,6 +1080,38 @@ mod tests {
t!(s: "/", "a/b", "/a/b");
}
#[test]
fn test_join_many() {
use to_man = at_vec::to_managed_move;
macro_rules! t(
(s: $path:expr, $join:expr, $exp:expr) => (
{
let path = Path::from_str($path);
let res = path.join_many_str($join);
assert_eq!(res.as_str(), Some($exp));
}
);
(v: $path:expr, $join:expr, $exp:expr) => (
{
let path = Path::from_vec($path);
let res = path.join_many($join);
assert_eq!(res.as_vec(), $exp);
}
)
)
t!(s: "a/b/c", ["d", "e"], "a/b/c/d/e");
t!(s: "a/b/c", ["..", "d"], "a/b/d");
t!(s: "a/b/c", ["d", "/e", "f"], "/e/f");
t!(s: "a/b/c", [~"d", ~"e"], "a/b/c/d/e");
t!(s: "a/b/c", [@"d", @"e"], "a/b/c/d/e");
t!(v: b!("a/b/c"), [b!("d"), b!("e")], b!("a/b/c/d/e"));
t!(v: b!("a/b/c"), [b!("d").to_owned(), b!("e").to_owned()], b!("a/b/c/d/e"));
t!(v: b!("a/b/c"), [to_man(b!("d").to_owned()), to_man(b!("e").to_owned())],
b!("a/b/c/d/e"));
}
#[test]
fn test_with_helpers() {
t!(v: Path::from_vec(b!("a/b/c")).with_dirname(b!("d")), b!("d/c"));
@ -1121,16 +1273,58 @@ mod tests {
t!(s: ".", set_extension_str, with_extension_str, "txt");
}
#[test]
fn test_add_extension() {
macro_rules! t(
(s: $path:expr, $ext:expr, $exp:expr) => (
{
let mut path = Path::from_str($path);
path.add_extension_str($ext);
assert_eq!(path.as_str(), Some($exp));
}
);
(v: $path:expr, $ext:expr, $exp:expr) => (
{
let mut path = Path::from_vec($path);
path.add_extension($ext);
assert_eq!(path.as_vec(), $exp);
}
)
)
t!(s: "hi/there.txt", "foo", "hi/there.txt.foo");
t!(s: "hi/there.", "foo", "hi/there..foo");
t!(s: "hi/there", ".foo", "hi/there..foo");
t!(s: "hi/there.txt", "", "hi/there.txt");
t!(v: b!("hi/there.txt"), b!("foo"), b!("hi/there.txt.foo"));
t!(v: b!("hi/there"), b!("bar"), b!("hi/there.bar"));
t!(v: b!("/"), b!("foo"), b!("/"));
t!(v: b!("."), b!("foo"), b!("."));
t!(v: b!("hi/there.", 0x80, "foo"), b!(0xff), b!("hi/there.", 0x80, "foo.", 0xff));
}
#[test]
fn test_getters() {
macro_rules! t(
(s: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => (
{
let path = $path;
assert_eq!(path.filename_str(), $filename);
assert_eq!(path.dirname_str(), $dirname);
assert_eq!(path.filestem_str(), $filestem);
assert_eq!(path.extension_str(), $ext);
let filename = $filename;
assert!(path.filename_str() == filename,
"`%s`.filename_str(): Expected `%?`, found `%?`",
path.as_str().unwrap(), filename, path.filename_str());
let dirname = $dirname;
assert!(path.dirname_str() == dirname,
"`%s`.dirname_str(): Expected `%?`, found `%?`",
path.as_str().unwrap(), dirname, path.dirname_str());
let filestem = $filestem;
assert!(path.filestem_str() == filestem,
"`%s`.filestem_str(): Expected `%?`, found `%?`",
path.as_str().unwrap(), filestem, path.filestem_str());
let ext = $ext;
assert!(path.extension_str() == ext,
"`%s`.extension_str(): Expected `%?`, found `%?`",
path.as_str().unwrap(), ext, path.extension_str());
}
);
(v: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => (
@ -1144,15 +1338,15 @@ mod tests {
)
)
t!(v: Path::from_vec(b!("a/b/c")), b!("c"), b!("a/b"), b!("c"), None);
t!(v: Path::from_vec(b!("a/b/", 0xff)), b!(0xff), b!("a/b"), b!(0xff), None);
t!(v: Path::from_vec(b!("hi/there.", 0xff)), b!("there.", 0xff), b!("hi"),
b!("there"), Some(b!(0xff)));
t!(v: Path::from_vec(b!("a/b/c")), Some(b!("c")), b!("a/b"), Some(b!("c")), None);
t!(v: Path::from_vec(b!("a/b/", 0xff)), Some(b!(0xff)), b!("a/b"), Some(b!(0xff)), None);
t!(v: Path::from_vec(b!("hi/there.", 0xff)), Some(b!("there.", 0xff)), b!("hi"),
Some(b!("there")), Some(b!(0xff)));
t!(s: Path::from_str("a/b/c"), Some("c"), Some("a/b"), Some("c"), None);
t!(s: Path::from_str("."), Some(""), Some("."), Some(""), None);
t!(s: Path::from_str("/"), Some(""), Some("/"), Some(""), None);
t!(s: Path::from_str(".."), Some(""), Some(".."), Some(""), None);
t!(s: Path::from_str("../.."), Some(""), Some("../.."), Some(""), None);
t!(s: Path::from_str("."), None, Some("."), None, None);
t!(s: Path::from_str("/"), None, Some("/"), None, None);
t!(s: Path::from_str(".."), None, Some(".."), None, None);
t!(s: Path::from_str("../.."), None, Some("../.."), None, None);
t!(s: Path::from_str("hi/there.txt"), Some("there.txt"), Some("hi"),
Some("there"), Some("txt"));
t!(s: Path::from_str("hi/there"), Some("there"), Some("hi"), Some("there"), None);
@ -1207,14 +1401,23 @@ mod tests {
#[test]
fn test_is_absolute() {
assert_eq!(Path::from_str("a/b/c").is_absolute(), false);
assert_eq!(Path::from_str("/a/b/c").is_absolute(), true);
assert_eq!(Path::from_str("a").is_absolute(), false);
assert_eq!(Path::from_str("/a").is_absolute(), true);
assert_eq!(Path::from_str(".").is_absolute(), false);
assert_eq!(Path::from_str("/").is_absolute(), true);
assert_eq!(Path::from_str("..").is_absolute(), false);
assert_eq!(Path::from_str("../..").is_absolute(), false);
macro_rules! t(
(s: $path:expr, $abs:expr, $rel:expr) => (
{
let path = Path::from_str($path);
assert_eq!(path.is_absolute(), $abs);
assert_eq!(path.is_relative(), $rel);
}
)
)
t!(s: "a/b/c", false, true);
t!(s: "/a/b/c", true, false);
t!(s: "a", false, true);
t!(s: "/a", true, false);
t!(s: ".", false, true);
t!(s: "/", true, false);
t!(s: "..", false, true);
t!(s: "../..", false, true);
}
#[test]
@ -1251,6 +1454,45 @@ mod tests {
t!(s: "../..", "a/b", true);
}
#[test]
fn test_ends_with_path() {
macro_rules! t(
(s: $path:expr, $child:expr, $exp:expr) => (
{
let path = Path::from_str($path);
let child = Path::from_str($child);
assert_eq!(path.ends_with_path(&child), $exp);
}
);
(v: $path:expr, $child:expr, $exp:expr) => (
{
let path = Path::from_vec($path);
let child = Path::from_vec($child);
assert_eq!(path.ends_with_path(&child), $exp);
}
)
)
t!(s: "a/b/c", "c", true);
t!(s: "a/b/c", "d", false);
t!(s: "foo/bar/quux", "bar", false);
t!(s: "foo/bar/quux", "barquux", false);
t!(s: "a/b/c", "b/c", true);
t!(s: "a/b/c", "a/b/c", true);
t!(s: "a/b/c", "foo/a/b/c", false);
t!(s: "/a/b/c", "a/b/c", true);
t!(s: "/a/b/c", "/a/b/c", false); // child must be relative
t!(s: "/a/b/c", "foo/a/b/c", false);
t!(s: "a/b/c", "", false);
t!(s: "", "", true);
t!(s: "/a/b/c", "d/e/f", false);
t!(s: "a/b/c", "a/b", false);
t!(s: "a/b/c", "b", false);
t!(v: b!("a/b/c"), b!("b/c"), true);
t!(v: b!("a/b/", 0xff), b!(0xff), true);
t!(v: b!("a/b/", 0xff), b!("b/", 0xff), true);
}
#[test]
fn test_path_relative_from() {
macro_rules! t(
@ -1305,7 +1547,12 @@ mod tests {
let comps = path.component_iter().to_owned_vec();
let exp: &[&str] = $exp;
let exps = exp.iter().map(|x| x.as_bytes()).to_owned_vec();
assert_eq!(comps, exps);
assert!(comps == exps, "component_iter: Expected %?, found %?",
comps, exps);
let comps = path.rev_component_iter().to_owned_vec();
let exps = exps.move_rev_iter().to_owned_vec();
assert!(comps == exps, "rev_component_iter: Expected %?, found %?",
comps, exps);
}
);
(v: [$($arg:expr),+], [$([$($exp:expr),*]),*]) => (
@ -1313,7 +1560,12 @@ mod tests {
let path = Path::from_vec(b!($($arg),+));
let comps = path.component_iter().to_owned_vec();
let exp: &[&[u8]] = [$(b!($($exp),*)),*];
assert_eq!(comps.as_slice(), exp);
assert!(comps.as_slice() == exp, "component_iter: Expected %?, found %?",
comps.as_slice(), exp);
let comps = path.rev_component_iter().to_owned_vec();
let exp = exp.rev_iter().map(|&x|x).to_owned_vec();
assert!(comps.as_slice() == exp, "rev_component_iter: Expected %?, found %?",
comps.as_slice(), exp);
}
)
)
@ -1334,6 +1586,32 @@ mod tests {
t!(s: "../../foo", ["..", "..", "foo"]);
}
#[test]
fn test_str_component_iter() {
macro_rules! t(
(v: [$($arg:expr),+], $exp:expr) => (
{
let path = Path::from_vec(b!($($arg),+));
let comps = path.str_component_iter().to_owned_vec();
let exp: &[Option<&str>] = $exp;
assert!(comps.as_slice() == exp, "str_component_iter: Expected %?, found %?",
comps.as_slice(), exp);
let comps = path.rev_str_component_iter().to_owned_vec();
let exp = exp.rev_iter().map(|&x|x).to_owned_vec();
assert!(comps.as_slice() == exp,
"rev_str_component_iter: Expected %?, found %?",
comps.as_slice(), exp);
}
)
)
t!(v: ["a/b/c"], [Some("a"), Some("b"), Some("c")]);
t!(v: ["/", 0xff, "/a/", 0x80], [None, Some("a"), None]);
t!(v: ["../../foo", 0xcd, "bar"], [Some(".."), Some(".."), None]);
// str_component_iter is a wrapper around component_iter, so no need to do
// the full set of tests
}
#[test]
fn test_each_parent() {
assert!(Path::from_str("/foo/bar").each_parent(|_| true));

View File

@ -15,10 +15,10 @@ use c_str::{CString, ToCStr};
use cast;
use cmp::Eq;
use from_str::FromStr;
use iter::{AdditiveIterator, Extendable, Iterator};
use iter::{AdditiveIterator, DoubleEndedIterator, Extendable, Invert, Iterator, Map};
use option::{Option, Some, None};
use str;
use str::{OwnedStr, Str, StrVector};
use str::{CharSplitIterator, OwnedStr, Str, StrVector};
use to_bytes::IterBytes;
use util;
use vec::Vector;
@ -27,8 +27,25 @@ use super::{GenericPath, GenericPathUnsafe};
#[cfg(target_os = "win32")]
use libc;
/// Iterator that yields successive components of a Path
pub type ComponentIter<'self> = str::CharSplitIterator<'self, char>;
/// Iterator that yields successive components of a Path as &str
///
/// Each component is yielded as Option<&str> for compatibility with PosixPath, but
/// every component in WindowsPath is guaranteed to be Some.
pub type StrComponentIter<'self> = Map<'self, &'self str, Option<&'self str>,
CharSplitIterator<'self, char>>;
/// Iterator that yields components of a Path in reverse as &str
///
/// Each component is yielded as Option<&str> for compatibility with PosixPath, but
/// every component in WindowsPath is guaranteed to be Some.
pub type RevStrComponentIter<'self> = Invert<Map<'self, &'self str, Option<&'self str>,
CharSplitIterator<'self, char>>>;
/// Iterator that yields successive components of a Path as &[u8]
pub type ComponentIter<'self> = Map<'self, Option<&'self str>, &'self [u8],
StrComponentIter<'self>>;
/// Iterator that yields components of a Path in reverse as &[u8]
pub type RevComponentIter<'self> = Map<'self, Option<&'self str>, &'self [u8],
RevStrComponentIter<'self>>;
/// Represents a Windows path
// Notes for Windows path impl:
@ -361,7 +378,7 @@ impl GenericPath for Path {
}
#[inline]
fn as_display_str<T>(&self, f: &fn(&str) -> T) -> T {
fn with_display_str<T>(&self, f: &fn(&str) -> T) -> T {
f(self.repr.as_slice())
}
@ -400,33 +417,34 @@ impl GenericPath for Path {
}
#[inline]
fn filename<'a>(&'a self) -> &'a [u8] {
self.filename_str().unwrap().as_bytes()
fn filename<'a>(&'a self) -> Option<&'a [u8]> {
self.filename_str().map_move(|x| x.as_bytes())
}
/// See `GenericPath::filename_str` for info.
/// Always returns a `Some` value.
/// Always returns a `Some` value if `filename` returns a `Some` value.
fn filename_str<'a>(&'a self) -> Option<&'a str> {
Some(match self.sepidx_or_prefix_len() {
None if "." == self.repr || ".." == self.repr => "",
None => self.repr.as_slice(),
Some((_,idxa,end)) if self.repr.slice(idxa, end) == ".." => "",
Some((_,idxa,end)) => self.repr.slice(idxa, end)
})
match self.sepidx_or_prefix_len() {
None if "." == self.repr || ".." == self.repr => None,
None => Some(self.repr.as_slice()),
Some((_,idxa,end)) if self.repr.slice(idxa, end) == ".." => None,
Some((_,idxa,end)) if idxa == end => None,
Some((_,idxa,end)) => Some(self.repr.slice(idxa, end))
}
}
/// See `GenericPath::filestem_str` for info.
/// Always returns a `Some` value.
/// Always returns a `Some` value if `filestem` returns a `Some` value.
#[inline]
fn filestem_str<'a>(&'a self) -> Option<&'a str> {
// filestem() returns a byte vector that's guaranteed valid UTF-8
Some(unsafe { cast::transmute(self.filestem()) })
self.filestem().map_move(cast::transmute)
}
#[inline]
fn extension_str<'a>(&'a self) -> Option<&'a str> {
// extension() returns a byte vector that's guaranteed valid UTF-8
self.extension().map_move(|v| unsafe { cast::transmute(v) })
self.extension().map_move(cast::transmute)
}
fn dir_path(&self) -> Path {
@ -434,10 +452,7 @@ impl GenericPath for Path {
}
fn file_path(&self) -> Option<Path> {
match self.filename_str() {
None | Some("") => None,
Some(s) => Some(unsafe { GenericPathUnsafe::from_str_unchecked(s) })
}
self.filename_str().map_move(|s| unsafe { GenericPathUnsafe::from_str_unchecked(s) })
}
#[inline]
@ -477,6 +492,21 @@ impl GenericPath for Path {
}
}
fn root_path(&self) -> Option<Path> {
if self.is_absolute() {
Some(Path::from_str(match self.prefix {
Some(VerbatimDiskPrefix)|Some(DiskPrefix) => {
self.repr.slice_to(self.prefix_len()+1)
}
_ => self.repr.slice_to(self.prefix_len())
}))
} else if self.is_vol_relative() {
Some(Path::from_str(self.repr.slice_to(1)))
} else {
None
}
}
/// See `GenericPath::is_absolute` for info.
///
/// A Windows Path is considered absolute only if it has a non-volume prefix,
@ -498,6 +528,11 @@ impl GenericPath for Path {
}
}
#[inline]
fn is_relative(&self) -> bool {
self.prefix.is_none() && !self.is_vol_relative()
}
fn is_ancestor_of(&self, other: &Path) -> bool {
if !self.equiv_prefix(other) {
false
@ -505,8 +540,8 @@ impl GenericPath for Path {
self.is_vol_relative() != other.is_vol_relative() {
false
} else {
let mut ita = self.component_iter();
let mut itb = other.component_iter();
let mut ita = self.str_component_iter().map(|x|x.unwrap());
let mut itb = other.str_component_iter().map(|x|x.unwrap());
if "." == self.repr {
return itb.next() != Some("..");
}
@ -553,8 +588,8 @@ impl GenericPath for Path {
None
}
} else {
let mut ita = self.component_iter();
let mut itb = base.component_iter();
let mut ita = self.str_component_iter().map(|x|x.unwrap());
let mut itb = base.str_component_iter().map(|x|x.unwrap());
let mut comps = ~[];
let a_verb = self.is_verbatim();
@ -669,13 +704,14 @@ impl Path {
path
}
/// Returns an iterator that yields each component of the path in turn.
/// Returns an iterator that yields each component of the path in turn as a Option<&str>.
/// Every component is guaranteed to be Some.
/// Does not yield the path prefix (including server/share components in UNC paths).
/// Does not distinguish between volume-relative and relative paths, e.g.
/// \a\b\c and a\b\c.
/// Does not distinguish between absolute and cwd-relative paths, e.g.
/// C:\foo and C:foo.
pub fn component_iter<'a>(&'a self) -> ComponentIter<'a> {
pub fn str_component_iter<'a>(&'a self) -> StrComponentIter<'a> {
let s = match self.prefix {
Some(_) => {
let plen = self.prefix_len();
@ -686,10 +722,52 @@ impl Path {
None if self.repr[0] == sep as u8 => self.repr.slice_from(1),
None => self.repr.as_slice()
};
let ret = s.split_terminator_iter(sep);
let ret = s.split_terminator_iter(sep).map(Some);
ret
}
/// Returns an iterator that yields each component of the path in reverse as an Option<&str>
/// See str_component_iter() for details.
pub fn rev_str_component_iter<'a>(&'a self) -> RevStrComponentIter<'a> {
self.str_component_iter().invert()
}
/// Returns an iterator that yields each component of the path in turn as a &[u8].
/// See str_component_iter() for details.
pub fn component_iter<'a>(&'a self) -> ComponentIter<'a> {
fn convert<'a>(x: Option<&'a str>) -> &'a [u8] {
#[inline];
x.unwrap().as_bytes()
}
self.str_component_iter().map(convert)
}
/// Returns an iterator that yields each component of the path in reverse as a &[u8].
/// See str_component_iter() for details.
pub fn rev_component_iter<'a>(&'a self) -> RevComponentIter<'a> {
fn convert<'a>(x: Option<&'a str>) -> &'a [u8] {
#[inline];
x.unwrap().as_bytes()
}
self.rev_str_component_iter().map(convert)
}
/// Returns whether the relative path `child` is a suffix of `self`.
pub fn ends_with_path(&self, child: &Path) -> bool {
if !child.is_relative() { return false; }
let mut selfit = self.str_component_iter().invert();
let mut childit = child.str_component_iter().invert();
loop {
match (selfit.next(), childit.next()) {
(Some(a), Some(b)) => if a != b { return false; },
(Some(_), None) => break,
(None, Some(_)) => return false,
(None, None) => break
}
}
true
}
/// Returns whether the path is considered "volume-relative", which means a path
/// that looks like "\foo". Paths of this form are relative to the current volume,
/// but absolute within that volume.
@ -1096,8 +1174,8 @@ impl Path {
/// Returns whether the represented file exists
pub fn exists(&self) -> bool {
match self.stat() {
None => None,
Some(st) => Some(st.st_size as i64)
None => false,
Some(_) => true
}
}
@ -1339,7 +1417,7 @@ mod tests {
#[test]
fn test_null_byte() {
use path2::null_byte::cond;
use path::null_byte::cond;
let mut handled = false;
let mut p = do cond.trap(|v| {
@ -1388,7 +1466,7 @@ mod tests {
#[test]
fn test_null_byte_fail() {
use path2::null_byte::cond;
use path::null_byte::cond;
use task;
macro_rules! t(
@ -1448,13 +1526,20 @@ mod tests {
#[test]
fn test_display_str() {
assert_eq!(Path::from_str("foo").to_display_str(), ~"foo");
assert_eq!(Path::from_vec(b!("\\")).to_filename_display_str(), None);
let mut called = false;
do Path::from_str("foo").as_display_str |s| {
do Path::from_str("foo").with_display_str |s| {
assert_eq!(s, "foo");
called = true;
};
assert!(called);
called = false;
do Path::from_vec(b!("\\")).with_filename_display_str |s| {
assert!(s.is_none());
called = true;
}
assert!(called);
}
#[test]
@ -1500,37 +1585,37 @@ mod tests {
)
)
t!(v: b!("a\\b\\c"), filename, b!("c"));
t!(v: b!("a\\b\\c"), filename, Some(b!("c")));
t!(s: "a\\b\\c", filename_str, "c");
t!(s: "\\a\\b\\c", filename_str, "c");
t!(s: "a", filename_str, "a");
t!(s: "\\a", filename_str, "a");
t!(s: ".", filename_str, "");
t!(s: "\\", filename_str, "");
t!(s: "..", filename_str, "");
t!(s: "..\\..", filename_str, "");
t!(s: ".", filename_str, None, opt);
t!(s: "\\", filename_str, None, opt);
t!(s: "..", filename_str, None, opt);
t!(s: "..\\..", filename_str, None, opt);
t!(s: "c:\\foo.txt", filename_str, "foo.txt");
t!(s: "C:\\", filename_str, "");
t!(s: "C:", filename_str, "");
t!(s: "C:\\", filename_str, None, opt);
t!(s: "C:", filename_str, None, opt);
t!(s: "\\\\server\\share\\foo.txt", filename_str, "foo.txt");
t!(s: "\\\\server\\share", filename_str, "");
t!(s: "\\\\server\\share", filename_str, None, opt);
t!(s: "\\\\server", filename_str, "server");
t!(s: "\\\\?\\bar\\foo.txt", filename_str, "foo.txt");
t!(s: "\\\\?\\bar", filename_str, "");
t!(s: "\\\\?\\", filename_str, "");
t!(s: "\\\\?\\bar", filename_str, None, opt);
t!(s: "\\\\?\\", filename_str, None, opt);
t!(s: "\\\\?\\UNC\\server\\share\\foo.txt", filename_str, "foo.txt");
t!(s: "\\\\?\\UNC\\server", filename_str, "");
t!(s: "\\\\?\\UNC\\", filename_str, "");
t!(s: "\\\\?\\UNC\\server", filename_str, None, opt);
t!(s: "\\\\?\\UNC\\", filename_str, None, opt);
t!(s: "\\\\?\\C:\\foo.txt", filename_str, "foo.txt");
t!(s: "\\\\?\\C:\\", filename_str, "");
t!(s: "\\\\?\\C:", filename_str, "");
t!(s: "\\\\?\\foo/bar", filename_str, "");
t!(s: "\\\\?\\C:/foo", filename_str, "");
t!(s: "\\\\?\\C:\\", filename_str, None, opt);
t!(s: "\\\\?\\C:", filename_str, None, opt);
t!(s: "\\\\?\\foo/bar", filename_str, None, opt);
t!(s: "\\\\?\\C:/foo", filename_str, None, opt);
t!(s: "\\\\.\\foo\\bar", filename_str, "bar");
t!(s: "\\\\.\\foo", filename_str, "");
t!(s: "\\\\.\\foo/bar", filename_str, "");
t!(s: "\\\\.\\foo", filename_str, None, opt);
t!(s: "\\\\.\\foo/bar", filename_str, None, opt);
t!(s: "\\\\.\\foo\\bar/baz", filename_str, "bar/baz");
t!(s: "\\\\.\\", filename_str, "");
t!(s: "\\\\.\\", filename_str, None, opt);
t!(s: "\\\\?\\a\\b\\", filename_str, "b");
t!(v: b!("a\\b\\c"), dirname, b!("a\\b"));
@ -1564,19 +1649,19 @@ mod tests {
t!(s: "\\\\.\\foo", dirname_str, "\\\\.\\foo");
t!(s: "\\\\?\\a\\b\\", dirname_str, "\\\\?\\a");
t!(v: b!("hi\\there.txt"), filestem, b!("there"));
t!(v: b!("hi\\there.txt"), filestem, Some(b!("there")));
t!(s: "hi\\there.txt", filestem_str, "there");
t!(s: "hi\\there", filestem_str, "there");
t!(s: "there.txt", filestem_str, "there");
t!(s: "there", filestem_str, "there");
t!(s: ".", filestem_str, "");
t!(s: "\\", filestem_str, "");
t!(s: ".", filestem_str, None, opt);
t!(s: "\\", filestem_str, None, opt);
t!(s: "foo\\.bar", filestem_str, ".bar");
t!(s: ".bar", filestem_str, ".bar");
t!(s: "..bar", filestem_str, ".");
t!(s: "hi\\there..txt", filestem_str, "there.");
t!(s: "..", filestem_str, "");
t!(s: "..\\..", filestem_str, "");
t!(s: "..", filestem_str, None, opt);
t!(s: "..\\..", filestem_str, None, opt);
// filestem is based on filename, so we don't need the full set of prefix tests
t!(v: b!("hi\\there.txt"), extension, Some(b!("txt")));
@ -1681,6 +1766,39 @@ mod tests {
t!(s: "\\\\?\\C:", "foo", "\\\\?\\C:\\foo"); // this is a weird one
}
#[test]
fn test_push_many() {
use to_man = at_vec::to_managed_move;
macro_rules! t(
(s: $path:expr, $push:expr, $exp:expr) => (
{
let mut p = Path::from_str($path);
p.push_many_str($push);
assert_eq!(p.as_str(), Some($exp));
}
);
(v: $path:expr, $push:expr, $exp:expr) => (
{
let mut p = Path::from_vec($path);
p.push_many($push);
assert_eq!(p.as_vec(), $exp);
}
)
)
t!(s: "a\\b\\c", ["d", "e"], "a\\b\\c\\d\\e");
t!(s: "a\\b\\c", ["d", "\\e"], "\\e");
t!(s: "a\\b\\c", ["d", "\\e", "f"], "\\e\\f");
t!(s: "a\\b\\c", [~"d", ~"e"], "a\\b\\c\\d\\e");
t!(s: "a\\b\\c", [@"d", @"e"], "a\\b\\c\\d\\e");
t!(v: b!("a\\b\\c"), [b!("d"), b!("e")], b!("a\\b\\c\\d\\e"));
t!(v: b!("a\\b\\c"), [b!("d"), b!("\\e"), b!("f")], b!("\\e\\f"));
t!(v: b!("a\\b\\c"), [b!("d").to_owned(), b!("e").to_owned()], b!("a\\b\\c\\d\\e"));
t!(v: b!("a\\b\\c"), [to_man(b!("d").to_owned()), to_man(b!("e").to_owned())],
b!("a\\b\\c\\d\\e"));
}
#[test]
fn test_pop() {
macro_rules! t(
@ -1753,6 +1871,20 @@ mod tests {
t!(s: "\\\\?\\a\\b\\", "\\\\?\\a", Some("b"));
}
#[test]
fn test_root_path() {
assert_eq!(Path::from_str("a\\b\\c").root_path(), None);
assert_eq!(Path::from_str("\\a\\b\\c").root_path(), Some(Path::from_str("\\")));
assert_eq!(Path::from_str("C:a").root_path(), None);
assert_eq!(Path::from_str("C:\\a").root_path(), Some(Path::from_str("C:\\")));
assert_eq!(Path::from_str("\\\\a\\b\\c").root_path(), Some(Path::from_str("\\\\a\\b")));
assert_eq!(Path::from_str("\\\\?\\a\\b").root_path(), Some(Path::from_str("\\\\?\\a")));
assert_eq!(Path::from_str("\\\\?\\C:\\a").root_path(), Some(Path::from_str("\\\\?\\C:\\")));
assert_eq!(Path::from_str("\\\\?\\UNC\\a\\b\\c").root_path(),
Some(Path::from_str("\\\\?\\UNC\\a\\b")));
assert_eq!(Path::from_str("\\\\.\\a\\b").root_path(), Some(Path::from_str("\\\\.\\a")));
}
#[test]
fn test_join() {
t!(s: Path::from_str("a\\b\\c").join_str(".."), "a\\b");
@ -1790,6 +1922,38 @@ mod tests {
// the full set of prefix tests
}
#[test]
fn test_join_many() {
use to_man = at_vec::to_managed_move;
macro_rules! t(
(s: $path:expr, $join:expr, $exp:expr) => (
{
let path = Path::from_str($path);
let res = path.join_many_str($join);
assert_eq!(res.as_str(), Some($exp));
}
);
(v: $path:expr, $join:expr, $exp:expr) => (
{
let path = Path::from_vec($path);
let res = path.join_many($join);
assert_eq!(res.as_vec(), $exp);
}
)
)
t!(s: "a\\b\\c", ["d", "e"], "a\\b\\c\\d\\e");
t!(s: "a\\b\\c", ["..", "d"], "a\\b\\d");
t!(s: "a\\b\\c", ["d", "\\e", "f"], "\\e\\f");
t!(s: "a\\b\\c", [~"d", ~"e"], "a\\b\\c\\d\\e");
t!(s: "a\\b\\c", [@"d", @"e"], "a\\b\\c\\d\\e");
t!(v: b!("a\\b\\c"), [b!("d"), b!("e")], b!("a\\b\\c\\d\\e"));
t!(v: b!("a\\b\\c"), [b!("d").to_owned(), b!("e").to_owned()], b!("a\\b\\c\\d\\e"));
t!(v: b!("a\\b\\c"), [to_man(b!("d").to_owned()), to_man(b!("e").to_owned())],
b!("a\\b\\c\\d\\e"));
}
#[test]
fn test_with_helpers() {
macro_rules! t(
@ -2002,16 +2166,55 @@ mod tests {
// will suffice. No need for the full set of prefix tests.
}
#[test]
fn test_add_extension() {
macro_rules! t(
(s: $path:expr, $ext:expr, $exp:expr) => (
{
let mut path = Path::from_str($path);
path.add_extension_str($ext);
assert_eq!(path.as_str(), Some($exp));
}
);
(v: $path:expr, $ext:expr, $exp:expr) => (
{
let mut path = Path::from_vec($path);
path.add_extension($ext);
assert_eq!(path.as_vec(), $exp);
}
)
)
t!(v: b!("hi\\there.txt"), b!("foo"), b!("hi\\there.txt.foo"));
t!(v: b!("hi\\there"), b!("bar"), b!("hi\\there.bar"));
t!(v: b!("\\"), b!("foo"), b!("\\"));
t!(v: b!("."), b!("foo"), b!("."));
t!(s: "hi\\there.", "foo", "hi\\there..foo");
t!(s: "hi\\there.txt", "", "hi\\there.txt");
}
#[test]
fn test_getters() {
macro_rules! t(
(s: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => (
{
let path = $path;
assert_eq!(path.filename_str(), $filename);
assert_eq!(path.dirname_str(), $dirname);
assert_eq!(path.filestem_str(), $filestem);
assert_eq!(path.extension_str(), $ext);
let filename = $filename;
assert!(path.filename_str() == filename,
"`%s`.filename_str(): Expected `%?`, found `%?`",
path.as_str().unwrap(), filename, path.filename_str());
let dirname = $dirname;
assert!(path.dirname_str() == dirname,
"`%s`.dirname_str(): Expected `%?`, found `%?`",
path.as_str().unwrap(), dirname, path.dirname_str());
let filestem = $filestem;
assert!(path.filestem_str() == filestem,
"`%s`.filestem_str(): Expected `%?`, found `%?`",
path.as_str().unwrap(), filestem, path.filestem_str());
let ext = $ext;
assert!(path.extension_str() == ext,
"`%s`.extension_str(): Expected `%?`, found `%?`",
path.as_str().unwrap(), ext, path.extension_str());
}
);
(v: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => (
@ -2025,12 +2228,12 @@ mod tests {
)
)
t!(v: Path::from_vec(b!("a\\b\\c")), b!("c"), b!("a\\b"), b!("c"), None);
t!(v: Path::from_vec(b!("a\\b\\c")), Some(b!("c")), b!("a\\b"), Some(b!("c")), None);
t!(s: Path::from_str("a\\b\\c"), Some("c"), Some("a\\b"), Some("c"), None);
t!(s: Path::from_str("."), Some(""), Some("."), Some(""), None);
t!(s: Path::from_str("\\"), Some(""), Some("\\"), Some(""), None);
t!(s: Path::from_str(".."), Some(""), Some(".."), Some(""), None);
t!(s: Path::from_str("..\\.."), Some(""), Some("..\\.."), Some(""), None);
t!(s: Path::from_str("."), None, Some("."), None, None);
t!(s: Path::from_str("\\"), None, Some("\\"), None, None);
t!(s: Path::from_str(".."), None, Some(".."), None, None);
t!(s: Path::from_str("..\\.."), None, Some("..\\.."), None, None);
t!(s: Path::from_str("hi\\there.txt"), Some("there.txt"), Some("hi"),
Some("there"), Some("txt"));
t!(s: Path::from_str("hi\\there"), Some("there"), Some("hi"), Some("there"), None);
@ -2076,10 +2279,10 @@ mod tests {
#[test]
fn test_is_absolute() {
macro_rules! t(
($path:expr, $abs:expr, $vol:expr, $cwd:expr) => (
($path:expr, $abs:expr, $vol:expr, $cwd:expr, $rel:expr) => (
{
let path = Path::from_str($path);
let (abs, vol, cwd) = ($abs, $vol, $cwd);
let (abs, vol, cwd, rel) = ($abs, $vol, $cwd, $rel);
let b = path.is_absolute();
assert!(b == abs, "Path '%s'.is_absolute(): expected %?, found %?",
path.as_str().unwrap(), abs, b);
@ -2089,25 +2292,28 @@ mod tests {
let b = path.is_cwd_relative();
assert!(b == cwd, "Path '%s'.is_cwd_relative(): expected %?, found %?",
path.as_str().unwrap(), cwd, b);
let b = path.is_relative();
assert!(b == rel, "Path '%s'.is_relativf(): expected %?, found %?",
path.as_str().unwrap(), rel, b);
}
)
)
t!("a\\b\\c", false, false, false);
t!("\\a\\b\\c", false, true, false);
t!("a", false, false, false);
t!("\\a", false, true, false);
t!(".", false, false, false);
t!("\\", false, true, false);
t!("..", false, false, false);
t!("..\\..", false, false, false);
t!("C:a\\b.txt", false, false, true);
t!("C:\\a\\b.txt", true, false, false);
t!("\\\\server\\share\\a\\b.txt", true, false, false);
t!("\\\\?\\a\\b\\c.txt", true, false, false);
t!("\\\\?\\C:\\a\\b.txt", true, false, false);
t!("\\\\?\\C:a\\b.txt", true, false, false); // NB: not equivalent to C:a\b.txt
t!("\\\\?\\UNC\\server\\share\\a\\b.txt", true, false, false);
t!("\\\\.\\a\\b", true, false, false);
t!("a\\b\\c", false, false, false, true);
t!("\\a\\b\\c", false, true, false, false);
t!("a", false, false, false, true);
t!("\\a", false, true, false, false);
t!(".", false, false, false, true);
t!("\\", false, true, false, false);
t!("..", false, false, false, true);
t!("..\\..", false, false, false, true);
t!("C:a\\b.txt", false, false, true, false);
t!("C:\\a\\b.txt", true, false, false, false);
t!("\\\\server\\share\\a\\b.txt", true, false, false, false);
t!("\\\\?\\a\\b\\c.txt", true, false, false, false);
t!("\\\\?\\C:\\a\\b.txt", true, false, false, false);
t!("\\\\?\\C:a\\b.txt", true, false, false, false); // NB: not equivalent to C:a\b.txt
t!("\\\\?\\UNC\\server\\share\\a\\b.txt", true, false, false, false);
t!("\\\\.\\a\\b", true, false, false, false);
}
#[test]
@ -2213,6 +2419,38 @@ mod tests {
t!(s: "\\\\?\\UNC\\a\\b\\c", "\\\\a\\b\\c", true);
}
#[test]
fn test_ends_with_path() {
macro_rules! t(
(s: $path:expr, $child:expr, $exp:expr) => (
{
let path = Path::from_str($path);
let child = Path::from_str($child);
assert_eq!(path.ends_with_path(&child), $exp);
}
);
)
t!(s: "a\\b\\c", "c", true);
t!(s: "a\\b\\c", "d", false);
t!(s: "foo\\bar\\quux", "bar", false);
t!(s: "foo\\bar\\quux", "barquux", false);
t!(s: "a\\b\\c", "b\\c", true);
t!(s: "a\\b\\c", "a\\b\\c", true);
t!(s: "a\\b\\c", "foo\\a\\b\\c", false);
t!(s: "\\a\\b\\c", "a\\b\\c", true);
t!(s: "\\a\\b\\c", "\\a\\b\\c", false); // child must be relative
t!(s: "\\a\\b\\c", "foo\\a\\b\\c", false);
t!(s: "a\\b\\c", "", false);
t!(s: "", "", true);
t!(s: "\\a\\b\\c", "d\\e\\f", false);
t!(s: "a\\b\\c", "a\\b", false);
t!(s: "a\\b\\c", "b", false);
t!(s: "C:\\a\\b", "b", true);
t!(s: "C:\\a\\b", "C:b", false);
t!(s: "C:\\a\\b", "C:a\\b", false);
}
#[test]
fn test_path_relative_from() {
macro_rules! t(
@ -2348,22 +2586,34 @@ mod tests {
}
#[test]
fn test_component_iter() {
fn test_str_component_iter() {
macro_rules! t(
(s: $path:expr, $exp:expr) => (
{
let path = Path::from_str($path);
let comps = path.component_iter().to_owned_vec();
let comps = path.str_component_iter().map(|x|x.unwrap()).to_owned_vec();
let exp: &[&str] = $exp;
assert_eq!(comps.as_slice(), exp);
assert!(comps.as_slice() == exp, "str_component_iter: Expected %?, found %?",
comps.as_slice(), exp);
let comps = path.rev_str_component_iter().map(|x|x.unwrap()).to_owned_vec();
let exp = exp.rev_iter().map(|&x|x).to_owned_vec();
assert!(comps.as_slice() == exp,
"rev_str_component_iter: Expected %?, found %?",
comps.as_slice(), exp);
}
);
(v: [$($arg:expr),+], $exp:expr) => (
{
let path = Path::from_vec(b!($($arg),+));
let comps = path.component_iter().to_owned_vec();
let comps = path.str_component_iter().map(|x|x.unwrap()).to_owned_vec();
let exp: &[&str] = $exp;
assert_eq!(comps.as_slice(), exp);
assert!(comps.as_slice() == exp, "str_component_iter: Expected %?, found %?",
comps.as_slice(), exp);
let comps = path.rev_str_component_iter().map(|x|x.unwrap()).to_owned_vec();
let exp = exp.rev_iter().map(|&x|x).to_owned_vec();
assert!(comps.as_slice() == exp,
"rev_str_component_iter: Expected %?, found %?",
comps.as_slice(), exp);
}
)
)
@ -2408,6 +2658,29 @@ mod tests {
t!(s: "\\\\.\\foo", []);
}
#[test]
fn test_component_iter() {
macro_rules! t(
(s: $path:expr, $exp:expr) => (
{
let path = Path::from_str($path);
let comps = path.component_iter().to_owned_vec();
let exp: &[&[u8]] = $exp;
assert!(comps.as_slice() == exp, "component_iter: Expected %?, found %?",
comps.as_slice(), exp);
let comps = path.rev_component_iter().to_owned_vec();
let exp = exp.rev_iter().map(|&x|x).to_owned_vec();
assert!(comps.as_slice() == exp, "rev_component_iter: Expected %?, found %?",
comps.as_slice(), exp);
}
)
)
t!(s: "a\\b\\c", [b!("a"), b!("b"), b!("c")]);
t!(s: ".", [b!(".")]);
// since this is really a wrapper around str_component_iter, those tests suffice
}
#[test]
fn test_each_parent() {
assert!(Path::from_str("/foo/bar").each_parent(|_| true));

View File

@ -60,10 +60,7 @@ pub use num::{Algebraic, Trigonometric, Exponential, Hyperbolic};
pub use num::{Integer, Fractional, Real, RealExt};
pub use num::{Bitwise, BitCount, Bounded};
pub use num::{Primitive, Int, Float, ToStrRadix, ToPrimitive, FromPrimitive};
pub use path::GenericPath;
pub use path::Path;
pub use path::PosixPath;
pub use path::WindowsPath;
pub use path::{GenericPath, Path, PosixPath, WindowsPath};
pub use ptr::RawPtr;
pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr, ToBytesConsume};
pub use send_str::{SendStr, SendStrOwned, SendStrStatic, IntoSendStr};

View File

@ -627,12 +627,13 @@ pub trait DirectoryInfo : FileSystemInfo {
fn mkdir(&self) {
match ignore_io_error(|| self.stat()) {
Some(_) => {
let path = self.get_path();
io_error::cond.raise(IoError {
kind: PathAlreadyExists,
desc: "Path already exists",
detail:
Some(format!("{} already exists; can't mkdir it",
self.get_path().to_str()))
path.display()))
})
},
None => mkdir(self.get_path())
@ -655,24 +656,27 @@ pub trait DirectoryInfo : FileSystemInfo {
match s.is_dir {
true => rmdir(self.get_path()),
false => {
let path = self.get_path();
let ioerr = IoError {
kind: MismatchedFileTypeForOperation,
desc: "Cannot do rmdir() on a non-directory",
detail: Some(format!(
"{} is a non-directory; can't rmdir it",
self.get_path().to_str()))
path.display()))
};
io_error::cond.raise(ioerr);
}
}
},
None =>
None => {
let path = self.get_path();
io_error::cond.raise(IoError {
kind: PathDoesntExist,
desc: "Path doesn't exist",
detail: Some(format!("{} doesn't exist; can't rmdir it",
self.get_path().to_str()))
path.display()))
})
}
}
}
@ -699,7 +703,7 @@ mod test {
fn file_test_io_smoke_test() {
do run_in_mt_newsched_task {
let message = "it's alright. have a good time";
let filename = &Path("./tmp/file_rt_io_file_test.txt");
let filename = &Path::from_str("./tmp/file_rt_io_file_test.txt");
{
let mut write_stream = open(filename, Create, ReadWrite).unwrap();
write_stream.write(message.as_bytes());
@ -721,7 +725,7 @@ mod test {
#[test]
fn file_test_io_invalid_path_opened_without_create_should_raise_condition() {
do run_in_mt_newsched_task {
let filename = &Path("./tmp/file_that_does_not_exist.txt");
let filename = &Path::from_str("./tmp/file_that_does_not_exist.txt");
let mut called = false;
do io_error::cond.trap(|_| {
called = true;
@ -736,7 +740,7 @@ mod test {
#[test]
fn file_test_iounlinking_invalid_path_should_raise_condition() {
do run_in_mt_newsched_task {
let filename = &Path("./tmp/file_another_file_that_does_not_exist.txt");
let filename = &Path::from_str("./tmp/file_another_file_that_does_not_exist.txt");
let mut called = false;
do io_error::cond.trap(|_| {
called = true;
@ -753,7 +757,7 @@ mod test {
use str;
let message = "ten-four";
let mut read_mem = [0, .. 8];
let filename = &Path("./tmp/file_rt_io_file_test_positional.txt");
let filename = &Path::from_str("./tmp/file_rt_io_file_test_positional.txt");
{
let mut rw_stream = open(filename, Create, ReadWrite).unwrap();
rw_stream.write(message.as_bytes());
@ -784,7 +788,7 @@ mod test {
let set_cursor = 4 as u64;
let mut tell_pos_pre_read;
let mut tell_pos_post_read;
let filename = &Path("./tmp/file_rt_io_file_test_seeking.txt");
let filename = &Path::from_str("./tmp/file_rt_io_file_test_seeking.txt");
{
let mut rw_stream = open(filename, Create, ReadWrite).unwrap();
rw_stream.write(message.as_bytes());
@ -813,7 +817,7 @@ mod test {
let final_msg = "foo-the-bar!!";
let seek_idx = 3;
let mut read_mem = [0, .. 13];
let filename = &Path("./tmp/file_rt_io_file_test_seek_and_write.txt");
let filename = &Path::from_str("./tmp/file_rt_io_file_test_seek_and_write.txt");
{
let mut rw_stream = open(filename, Create, ReadWrite).unwrap();
rw_stream.write(initial_msg.as_bytes());
@ -839,7 +843,7 @@ mod test {
let chunk_two = "asdf";
let chunk_three = "zxcv";
let mut read_mem = [0, .. 4];
let filename = &Path("./tmp/file_rt_io_file_test_seek_shakedown.txt");
let filename = &Path::from_str("./tmp/file_rt_io_file_test_seek_shakedown.txt");
{
let mut rw_stream = open(filename, Create, ReadWrite).unwrap();
rw_stream.write(initial_msg.as_bytes());
@ -869,7 +873,7 @@ mod test {
#[test]
fn file_test_stat_is_correct_on_is_file() {
do run_in_mt_newsched_task {
let filename = &Path("./tmp/file_stat_correct_on_is_file.txt");
let filename = &Path::from_str("./tmp/file_stat_correct_on_is_file.txt");
{
let mut fs = open(filename, Create, ReadWrite).unwrap();
let msg = "hw";
@ -887,7 +891,7 @@ mod test {
#[test]
fn file_test_stat_is_correct_on_is_dir() {
do run_in_mt_newsched_task {
let filename = &Path("./tmp/file_stat_correct_on_is_dir");
let filename = &Path::from_str("./tmp/file_stat_correct_on_is_dir");
mkdir(filename);
let stat_res = match stat(filename) {
Some(s) => s,
@ -901,7 +905,7 @@ mod test {
#[test]
fn file_test_fileinfo_false_when_checking_is_file_on_a_directory() {
do run_in_mt_newsched_task {
let dir = &Path("./tmp/fileinfo_false_on_dir");
let dir = &Path::from_str("./tmp/fileinfo_false_on_dir");
mkdir(dir);
assert!(dir.is_file() == false);
rmdir(dir);
@ -911,7 +915,7 @@ mod test {
#[test]
fn file_test_fileinfo_check_exists_before_and_after_file_creation() {
do run_in_mt_newsched_task {
let file = &Path("./tmp/fileinfo_check_exists_b_and_a.txt");
let file = &Path::from_str("./tmp/fileinfo_check_exists_b_and_a.txt");
{
let msg = "foo".as_bytes();
let mut w = file.open_writer(Create);
@ -926,7 +930,7 @@ mod test {
#[test]
fn file_test_directoryinfo_check_exists_before_and_after_mkdir() {
do run_in_mt_newsched_task {
let dir = &Path("./tmp/before_and_after_dir");
let dir = &Path::from_str("./tmp/before_and_after_dir");
assert!(!dir.exists());
dir.mkdir();
assert!(dir.exists());
@ -940,11 +944,11 @@ mod test {
fn file_test_directoryinfo_readdir() {
use str;
do run_in_mt_newsched_task {
let dir = &Path("./tmp/di_readdir");
let dir = &Path::from_str("./tmp/di_readdir");
dir.mkdir();
let prefix = "foo";
for n in range(0,3) {
let f = dir.push(format!("{}.txt", n));
let f = dir.join_str(format!("{}.txt", n));
let mut w = f.open_writer(Create);
let msg_str = (prefix + n.to_str().to_owned()).to_owned();
let msg = msg_str.as_bytes();
@ -955,13 +959,13 @@ mod test {
let mut mem = [0u8, .. 4];
for f in files.iter() {
{
let n = f.filestem();
let n = f.filestem_str();
let mut r = f.open_reader(Open);
r.read(mem);
let read_str = str::from_utf8(mem);
let expected = match n {
Some(n) => prefix+n,
None => fail2!("really shouldn't happen..")
None|Some("") => fail2!("really shouldn't happen.."),
Some(n) => prefix+n
};
assert!(expected == read_str);
}

View File

@ -22,7 +22,7 @@ impl<'self> PathLike for &'self str {
impl PathLike for Path {
fn path_as_str<T>(&self, f: &fn(&str) -> T) -> T {
let s = self.to_str();
let s = self.as_str().unwrap();
f(s)
}
}
@ -35,7 +35,7 @@ mod test {
#[test]
fn path_like_smoke_test() {
let expected = if cfg!(unix) { "/home" } else { "C:\\" };
let path = Path(expected);
let path = Path::from_str(expected);
path.path_as_str(|p| assert!(p == expected));
path.path_as_str(|p| assert!(p == expected));
}

View File

@ -16,6 +16,7 @@ use container::Container;
use iter::{Iterator, range};
use super::io::net::ip::{SocketAddr, Ipv4Addr, Ipv6Addr};
use vec::{OwnedVector, MutableVector, ImmutableVector};
use path::GenericPath;
use rt::sched::Scheduler;
use unstable::{run_in_bare_thread};
use rt::thread::Thread;
@ -346,7 +347,6 @@ it is running in and assigns a port range based on it.
fn base_port() -> uint {
use os;
use str::StrSlice;
use to_str::ToStr;
use vec::ImmutableVector;
let base = 9600u;
@ -363,12 +363,14 @@ fn base_port() -> uint {
("dist", base + range * 8)
];
let path = os::getcwd().to_str();
// FIXME (#9639): This needs to handle non-utf8 paths
let path = os::getcwd();
let path_s = path.as_str().unwrap();
let mut final_base = base;
for &(dir, base) in bases.iter() {
if path.contains(dir) {
if path_s.contains(dir) {
final_base = base;
break;
}

View File

@ -391,7 +391,7 @@ mod test {
let read_mem = vec::from_elem(read_buf_len, 0u8);
let read_buf = slice_to_uv_buf(read_mem);
let read_buf_ptr: *Buf = &read_buf;
let p = Path(path_str);
let p = Path::from_str(path_str);
let open_req = FsRequest::new();
do open_req.open(&loop_, &p, create_flags as int, mode as int)
|req, uverr| {
@ -405,7 +405,7 @@ mod test {
assert!(uverr.is_none());
let loop_ = req.get_loop();
let open_req = FsRequest::new();
do open_req.open(&loop_, &Path(path_str), read_flags as int,0)
do open_req.open(&loop_, &Path::from_str(path_str), read_flags as int,0)
|req, uverr| {
assert!(uverr.is_none());
let loop_ = req.get_loop();
@ -431,7 +431,7 @@ mod test {
assert!(uverr.is_none());
let loop_ = &req.get_loop();
let unlink_req = FsRequest::new();
do unlink_req.unlink(loop_, &Path(path_str))
do unlink_req.unlink(loop_, &Path::from_str(path_str))
|_,uverr| {
assert!(uverr.is_none());
};
@ -465,7 +465,7 @@ mod test {
let write_buf = slice_to_uv_buf(write_val);
// open/create
let open_req = FsRequest::new();
let result = open_req.open_sync(&loop_, &Path(path_str),
let result = open_req.open_sync(&loop_, &Path::from_str(path_str),
create_flags as int, mode as int);
assert!(result.is_ok());
let fd = result.unwrap();
@ -479,7 +479,7 @@ mod test {
assert!(result.is_ok());
// re-open
let open_req = FsRequest::new();
let result = open_req.open_sync(&loop_, &Path(path_str),
let result = open_req.open_sync(&loop_, &Path::from_str(path_str),
read_flags as int,0);
assert!(result.is_ok());
let len = 1028;
@ -503,7 +503,7 @@ mod test {
assert!(result.is_ok());
// unlink
let unlink_req = FsRequest::new();
let result = unlink_req.unlink_sync(&loop_, &Path(path_str));
let result = unlink_req.unlink_sync(&loop_, &Path::from_str(path_str));
assert!(result.is_ok());
} else { fail2!("nread was 0.. wudn't expectin' that."); }
loop_.close();

View File

@ -34,7 +34,7 @@ use rt::uv::idle::IdleWatcher;
use rt::uv::net::{UvIpv4SocketAddr, UvIpv6SocketAddr, accum_sockaddrs};
use rt::uv::addrinfo::GetAddrInfoRequest;
use unstable::sync::Exclusive;
use path::Path;
use path::{GenericPath, Path};
use super::super::io::support::PathLike;
use libc::{lseek, off_t, O_CREAT, O_APPEND, O_TRUNC, O_RDWR, O_RDONLY, O_WRONLY,
S_IRUSR, S_IWUSR, S_IRWXU};
@ -631,7 +631,7 @@ impl IoFactory for UvIoFactory {
None => {
let stat = req.get_stat();
Ok(FileStat {
path: Path(path_str),
path: Path::from_str(path_str),
is_file: stat.is_file(),
is_dir: stat.is_dir(),
size: stat.st_size,
@ -720,7 +720,9 @@ impl IoFactory for UvIoFactory {
let rel_paths = req.get_paths();
let mut paths = ~[];
for r in rel_paths.iter() {
paths.push(Path(path_str+"/"+*r));
let mut p = Path::from_str(path_str);
p.push_str(*r);
paths.push(p);
}
Ok(paths)
},
@ -2177,20 +2179,20 @@ fn file_test_uvio_full_simple_impl() {
{
let create_fm = Create;
let create_fa = ReadWrite;
let mut fd = (*io).fs_open(&Path(path), create_fm, create_fa).unwrap();
let mut fd = (*io).fs_open(&Path::from_str(path), create_fm, create_fa).unwrap();
let write_buf = write_val.as_bytes();
fd.write(write_buf);
}
{
let ro_fm = Open;
let ro_fa = Read;
let mut fd = (*io).fs_open(&Path(path), ro_fm, ro_fa).unwrap();
let mut fd = (*io).fs_open(&Path::from_str(path), ro_fm, ro_fa).unwrap();
let mut read_vec = [0, .. 1028];
let nread = fd.read(read_vec).unwrap();
let read_val = str::from_utf8(read_vec.slice(0, nread as uint));
assert!(read_val == write_val.to_owned());
}
(*io).fs_unlink(&Path(path));
(*io).fs_unlink(&Path::from_str(path));
}
}

View File

@ -578,8 +578,8 @@ mod tests {
let mut prog = run_pwd(None);
let output = str::from_utf8(prog.finish_with_output().output);
let parent_dir = os::getcwd().normalize();
let child_dir = Path(output.trim()).normalize();
let parent_dir = os::getcwd();
let child_dir = Path::from_str(output.trim());
let parent_stat = parent_dir.stat().unwrap();
let child_stat = child_dir.stat().unwrap();
@ -592,11 +592,11 @@ mod tests {
fn test_change_working_directory() {
// test changing to the parent of os::getcwd() because we know
// the path exists (and os::getcwd() is not expected to be root)
let parent_dir = os::getcwd().dir_path().normalize();
let parent_dir = os::getcwd().dir_path();
let mut prog = run_pwd(Some(&parent_dir));
let output = str::from_utf8(prog.finish_with_output().output);
let child_dir = Path(output.trim()).normalize();
let child_dir = Path::from_str(output.trim());
let parent_stat = parent_dir.stat().unwrap();
let child_stat = child_dir.stat().unwrap();

View File

@ -177,7 +177,6 @@ pub mod libc;
pub mod c_str;
pub mod os;
pub mod path;
pub mod path2;
pub mod rand;
pub mod run;
pub mod sys;

View File

@ -225,7 +225,7 @@ pub mod dl {
pub unsafe fn open_external(filename: &path::Path) -> *libc::c_void {
#[fixed_stack_segment]; #[inline(never)];
do os::win32::as_utf16_p(filename.to_str()) |raw_name| {
do os::win32::as_utf16_p(filename.as_str().unwrap()) |raw_name| {
LoadLibraryW(raw_name)
}
}

View File

@ -81,7 +81,7 @@ pub fn expand_include(cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree])
let file = get_single_str_from_tts(cx, sp, tts, "include!");
let p = parse::new_sub_parser_from_file(
cx.parse_sess(), cx.cfg(),
&res_rel_file(cx, sp, &Path(file)), sp);
&res_rel_file(cx, sp, &Path::from_str(file)), sp);
base::MRExpr(p.parse_expr())
}
@ -89,7 +89,7 @@ pub fn expand_include(cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree])
pub fn expand_include_str(cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree])
-> base::MacResult {
let file = get_single_str_from_tts(cx, sp, tts, "include_str!");
let res = io::read_whole_file_str(&res_rel_file(cx, sp, &Path(file)));
let res = io::read_whole_file_str(&res_rel_file(cx, sp, &Path::from_str(file)));
match res {
result::Ok(res) => {
base::MRExpr(cx.expr_str(sp, res.to_managed()))
@ -103,7 +103,7 @@ pub fn expand_include_str(cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree])
pub fn expand_include_bin(cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree])
-> base::MacResult {
let file = get_single_str_from_tts(cx, sp, tts, "include_bin!");
match io::read_whole_file(&res_rel_file(cx, sp, &Path(file))) {
match io::read_whole_file(&res_rel_file(cx, sp, &Path::from_str(file))) {
result::Ok(src) => {
let u8_exprs: ~[@ast::Expr] = src.iter().map(|char| cx.expr_u8(sp, *char)).collect();
base::MRExpr(cx.expr_vec(sp, u8_exprs))
@ -144,10 +144,12 @@ fn topmost_expn_info(expn_info: @codemap::ExpnInfo) -> @codemap::ExpnInfo {
// isn't already)
fn res_rel_file(cx: @ExtCtxt, sp: codemap::Span, arg: &Path) -> Path {
// NB: relative paths are resolved relative to the compilation unit
if !arg.is_absolute {
let cu = Path(cx.codemap().span_to_filename(sp));
cu.dir_path().push_many(arg.components)
if !arg.is_absolute() {
let mut cu = Path::from_str(cx.codemap().span_to_filename(sp));
cu.pop();
cu.push_path(arg);
cu
} else {
(*arg).clone()
arg.clone()
}
}

View File

@ -261,7 +261,8 @@ pub fn new_parser_from_tts(sess: @mut ParseSess,
pub fn file_to_filemap(sess: @mut ParseSess, path: &Path, spanopt: Option<Span>)
-> @FileMap {
match io::read_whole_file_str(path) {
Ok(src) => string_to_filemap(sess, src.to_managed(), path.to_str().to_managed()),
// FIXME (#9639): This needs to handle non-utf8 paths
Ok(src) => string_to_filemap(sess, src.to_managed(), path.as_str().unwrap().to_managed()),
Err(e) => {
match spanopt {
Some(span) => sess.span_diagnostic.span_fatal(span, e),

View File

@ -3992,27 +3992,20 @@ impl Parser {
outer_attrs: &[ast::Attribute],
id_sp: Span)
-> (ast::item_, ~[ast::Attribute]) {
let prefix = Path(self.sess.cm.span_to_filename(*self.span));
let prefix = prefix.dir_path();
let mut prefix = Path::from_str(self.sess.cm.span_to_filename(*self.span));
prefix.pop();
let mod_path_stack = &*self.mod_path_stack;
let mod_path = Path(".").push_many(*mod_path_stack);
let dir_path = prefix.push_many(mod_path.components);
let mod_path = Path::from_str(".").join_many_str(*mod_path_stack);
let dir_path = prefix.join_path(&mod_path);
let file_path = match ::attr::first_attr_value_str_by_name(
outer_attrs, "path") {
Some(d) => {
let path = Path(d);
if !path.is_absolute {
dir_path.push(d)
} else {
path
}
}
Some(d) => dir_path.join_str(d),
None => {
let mod_name = token::interner_get(id.name).to_owned();
let default_path_str = mod_name + ".rs";
let secondary_path_str = mod_name + "/mod.rs";
let default_path = dir_path.push(default_path_str);
let secondary_path = dir_path.push(secondary_path_str);
let default_path = dir_path.join_str(default_path_str);
let secondary_path = dir_path.join_str(secondary_path_str);
let default_exists = default_path.exists();
let secondary_exists = secondary_path.exists();
match (default_exists, secondary_exists) {
@ -4039,28 +4032,30 @@ impl Parser {
path: Path,
outer_attrs: ~[ast::Attribute],
id_sp: Span) -> (ast::item_, ~[ast::Attribute]) {
let full_path = path.normalize();
let maybe_i = do self.sess.included_mod_stack.iter().position |p| { *p == full_path };
let maybe_i = do self.sess.included_mod_stack.iter().position |p| { *p == path };
match maybe_i {
Some(i) => {
let stack = &self.sess.included_mod_stack;
let mut err = ~"circular modules: ";
for p in stack.slice(i, stack.len()).iter() {
err.push_str(p.to_str());
do p.with_display_str |s| {
err.push_str(s);
}
err.push_str(" -> ");
}
err.push_str(full_path.to_str());
do path.with_display_str |s| {
err.push_str(s);
}
self.span_fatal(id_sp, err);
}
None => ()
}
self.sess.included_mod_stack.push(full_path.clone());
self.sess.included_mod_stack.push(path.clone());
let p0 =
new_sub_parser_from_file(self.sess,
self.cfg.clone(),
&full_path,
&path,
id_sp);
let (inner, next) = p0.parse_inner_attrs_and_next();
let mod_attrs = vec::append(outer_attrs, inner);

View File

@ -73,8 +73,8 @@ fn read_line() {
use std::rt::io::file::FileInfo;
use std::rt::io::buffered::BufferedReader;
let path = Path(env!("CFG_SRC_DIR"))
.push_rel(&Path("src/test/bench/shootout-k-nucleotide.data"));
let path = Path::from_str(env!("CFG_SRC_DIR"))
.join_str("src/test/bench/shootout-k-nucleotide.data");
for _ in range(0, 3) {
let mut reader = BufferedReader::new(path.open_reader(Open).unwrap());

View File

@ -122,7 +122,7 @@ fn main() {
};
let writer = if os::getenv("RUST_BENCH").is_some() {
io::file_writer(&Path("./shootout-fasta.data"),
io::file_writer(&Path::from_str("./shootout-fasta.data"),
[io::Truncate, io::Create]).unwrap()
} else {
io::stdout()

View File

@ -164,8 +164,8 @@ fn main() {
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(env!("CFG_SRC_DIR"))
.push_rel(&Path("src/test/bench/shootout-k-nucleotide.data"));
let path = Path::from_str(env!("CFG_SRC_DIR"))
.join_str("src/test/bench/shootout-k-nucleotide.data");
~path.open_reader(Open).unwrap() as ~Reader
} else {
~stdio::stdin() as ~Reader

View File

@ -20,14 +20,14 @@ use std::{io, os, unstable};
pub fn main() {
fn mk_file(path: &str, directory: bool) {
if directory {
os::make_dir(&Path(path), 0xFFFF);
os::make_dir(&Path::from_str(path), 0xFFFF);
} else {
io::mk_file_writer(&Path(path), [io::Create]);
io::mk_file_writer(&Path::from_str(path), [io::Create]);
}
}
fn abs_path(path: &str) -> Path {
os::getcwd().push_many(Path(path).components)
os::getcwd().join_path(&Path::from_str(path))
}
fn glob_vec(pattern: &str) -> ~[Path] {

View File

@ -23,7 +23,7 @@ fn tester()
{
let loader: rsrc_loader = |_path| {result::Ok(~"more blah")};
let path = path::Path("blah");
let path = path::Path::from_str("blah");
assert!(loader(&path).is_ok());
}

View File

@ -25,12 +25,12 @@ fn rename_directory() {
let tmpdir = TempDir::new("rename_directory").expect("rename_directory failed");
let tmpdir = tmpdir.path();
let old_path = tmpdir.push_many(["foo", "bar", "baz"]);
let old_path = tmpdir.join_many_str(["foo", "bar", "baz"]);
assert!(os::mkdir_recursive(&old_path, U_RWX));
let test_file = &old_path.push("temp.txt");
let test_file = &old_path.join_str("temp.txt");
/* Write the temp input file */
let ostream = do test_file.to_str().with_c_str |fromp| {
let ostream = do test_file.with_c_str |fromp| {
do "w+b".with_c_str |modebuf| {
libc::fopen(fromp, modebuf)
}
@ -46,11 +46,11 @@ fn rename_directory() {
}
assert_eq!(libc::fclose(ostream), (0u as libc::c_int));
let new_path = tmpdir.push_many(["quux", "blat"]);
let new_path = tmpdir.join_many_str(["quux", "blat"]);
assert!(os::mkdir_recursive(&new_path, U_RWX));
assert!(os::rename_file(&old_path, &new_path.push("newdir")));
assert!(os::path_is_dir(&new_path.push("newdir")));
assert!(os::path_exists(&new_path.push_many(["newdir", "temp.txt"])));
assert!(os::rename_file(&old_path, &new_path.join_str("newdir")));
assert!(os::path_is_dir(&new_path.join_str("newdir")));
assert!(os::path_exists(&new_path.join_many_str(["newdir", "temp.txt"])));
}
}

View File

@ -18,8 +18,8 @@ use std::io;
use std::os;
pub fn main() {
let dir = tempfile::TempDir::new_in(&Path("."), "").unwrap();
let path = dir.path().push("file");
let dir = tempfile::TempDir::new_in(&Path::from_str("."), "").unwrap();
let path = dir.path().join_str("file");
{
match io::file_writer(&path, [io::Create, io::Truncate]) {

View File

@ -28,12 +28,15 @@ use std::cell::Cell;
fn test_tempdir() {
let path = {
let p = TempDir::new_in(&Path("."), "foobar").unwrap();
let p = TempDir::new_in(&Path::from_str("."), "foobar").unwrap();
let p = p.path();
assert!(p.to_str().ends_with("foobar"));
assert!(ends_with(p.as_vec(), bytes!("foobar")));
p.clone()
};
assert!(!os::path_exists(&path));
fn ends_with(v: &[u8], needle: &[u8]) -> bool {
v.len() >= needle.len() && v.slice_from(v.len()-needle.len()) == needle
}
}
fn test_rm_tempdir() {
@ -81,10 +84,10 @@ fn test_rm_tempdir() {
// Ideally these would be in std::os but then core would need
// to depend on std
fn recursive_mkdir_rel() {
let path = Path("frob");
debug2!("recursive_mkdir_rel: Making: {} in cwd {} [{:?}]", path.to_str(),
os::getcwd().to_str(),
os::path_exists(&path));
let path = Path::from_str("frob");
let cwd = os::getcwd();
debug2!("recursive_mkdir_rel: Making: {} in cwd {} [{:?}]", path.display(),
cwd.display(), os::path_exists(&path));
assert!(os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
assert!(os::path_is_dir(&path));
assert!(os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
@ -92,25 +95,26 @@ fn recursive_mkdir_rel() {
}
fn recursive_mkdir_dot() {
let dot = Path(".");
let dot = Path::from_str(".");
assert!(os::mkdir_recursive(&dot, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
let dotdot = Path("..");
let dotdot = Path::from_str("..");
assert!(os::mkdir_recursive(&dotdot, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
}
fn recursive_mkdir_rel_2() {
let path = Path("./frob/baz");
debug2!("recursive_mkdir_rel_2: Making: {} in cwd {} [{:?}]", path.to_str(),
os::getcwd().to_str(), os::path_exists(&path));
let path = Path::from_str("./frob/baz");
let cwd = os::getcwd();
debug2!("recursive_mkdir_rel_2: Making: {} in cwd {} [{:?}]", path.display(),
cwd.display(), os::path_exists(&path));
assert!(os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
assert!(os::path_is_dir(&path));
assert!(os::path_is_dir(&path.pop()));
let path2 = Path("quux/blat");
debug2!("recursive_mkdir_rel_2: Making: {} in cwd {}", path2.to_str(),
os::getcwd().to_str());
assert!(os::path_is_dir(&path.dir_path()));
let path2 = Path::from_str("quux/blat");
debug2!("recursive_mkdir_rel_2: Making: {} in cwd {}", path2.display(),
cwd.display());
assert!(os::mkdir_recursive(&path2, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
assert!(os::path_is_dir(&path2));
assert!(os::path_is_dir(&path2.pop()));
assert!(os::path_is_dir(&path2.dir_path()));
}
// Ideally this would be in core, but needs TempFile
@ -120,17 +124,17 @@ pub fn test_rmdir_recursive_ok() {
let tmpdir = TempDir::new("test").expect("test_rmdir_recursive_ok: \
couldn't create temp dir");
let tmpdir = tmpdir.path();
let root = tmpdir.push("foo");
let root = tmpdir.join_str("foo");
debug2!("making {}", root.to_str());
debug2!("making {}", root.display());
assert!(os::make_dir(&root, rwx));
assert!(os::make_dir(&root.push("foo"), rwx));
assert!(os::make_dir(&root.push("foo").push("bar"), rwx));
assert!(os::make_dir(&root.push("foo").push("bar").push("blat"), rwx));
assert!(os::make_dir(&root.join_str("foo"), rwx));
assert!(os::make_dir(&root.join_str("foo").join_str("bar"), rwx));
assert!(os::make_dir(&root.join_str("foo").join_str("bar").join_str("blat"), rwx));
assert!(os::remove_dir_recursive(&root));
assert!(!os::path_exists(&root));
assert!(!os::path_exists(&root.push("bar")));
assert!(!os::path_exists(&root.push("bar").push("blat")));
assert!(!os::path_exists(&root.join_str("bar")));
assert!(!os::path_exists(&root.join_str("bar").join_str("blat")));
}
fn in_tmpdir(f: &fn()) {