path2: Update based on more review feedback
Standardize the is_sep() functions to be the same in both posix and windows, and re-export from path. Update extra::glob to use this. Remove the usage of either, as it's going away. Move the WindowsPath-specific methods out of WindowsPath and make them top-level functions of path::windows instead. This way you cannot accidentally write code that will fail to compile on non-windows architectures without typing ::windows anywhere. Remove GenericPath::from_c_str() and just impl BytesContainer for CString instead. Remove .join_path() and .push_path() and just implement BytesContainer for Path instead. Remove FilenameDisplay and add a boolean flag to Display instead. Remove .each_parent(). It only had one caller, so just inline its definition there.
This commit is contained in:
parent
c01a97b7a9
commit
bab7eb20df
@ -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().join_path(file);
|
||||
let filepath = testfile.dir_path().join(file);
|
||||
io::read_whole_file_str(&filepath).unwrap()
|
||||
}
|
||||
None => { srcs[srcs.len() - 2u].clone() }
|
||||
@ -657,7 +657,7 @@ 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).join_path(&auxname)
|
||||
aux_output_dir_name(config, testfile).join(&auxname)
|
||||
}
|
||||
|
||||
fn make_exe_name(config: &config, testfile: &Path) -> Path {
|
||||
@ -757,7 +757,7 @@ fn output_testname(testfile: &Path) -> Path {
|
||||
|
||||
fn output_base_name(config: &config, testfile: &Path) -> Path {
|
||||
config.build_base
|
||||
.join_path(&output_testname(testfile))
|
||||
.join(&output_testname(testfile))
|
||||
.with_extension(config.stage_id.as_slice())
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
*/
|
||||
|
||||
use std::{os, path};
|
||||
use std::path::is_sep;
|
||||
|
||||
use sort;
|
||||
|
||||
@ -81,11 +82,7 @@ pub fn glob(pattern: &str) -> GlobIterator {
|
||||
*/
|
||||
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() }
|
||||
fn check_windows_verbatim(p: &Path) -> bool { path::windows::is_verbatim(p) }
|
||||
#[cfg(not(windows))]
|
||||
fn check_windows_verbatim(_: &Path) -> bool { false }
|
||||
|
||||
@ -98,7 +95,7 @@ fn check_windows_verbatim(_: &Path) -> bool { false }
|
||||
// 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());
|
||||
root.push(pat_root.get_ref());
|
||||
}
|
||||
|
||||
let root_len = pat_root.map_move_default(0u, |p| p.as_vec().len());
|
||||
@ -462,7 +459,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_sep2(a) && path::windows::is_sep2(b) {
|
||||
if cfg!(windows) && path::windows::is_sep(a) && path::windows::is_sep(b) {
|
||||
true
|
||||
} else if !case_sensitive && a.is_ascii() && b.is_ascii() {
|
||||
// FIXME: work with non-ascii chars properly (issue #1347)
|
||||
@ -472,16 +469,6 @@ 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_sep2(c)
|
||||
} else {
|
||||
c <= '\x7F' && path::posix::is_sep(&(c as u8))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configuration options to modify the behaviour of `Pattern::matches_with(..)`
|
||||
*/
|
||||
|
@ -45,7 +45,7 @@ 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);
|
||||
let mut p = sess.filesearch.sysroot().join_path(&r);
|
||||
let mut p = sess.filesearch.sysroot().join(&r);
|
||||
p.push(os::dll_filename("rustrt"));
|
||||
p
|
||||
}
|
||||
@ -148,7 +148,7 @@ pub fn get_install_prefix_rpath(target_triple: &str) -> ~str {
|
||||
|
||||
let tlib = filesearch::relative_target_lib_path(target_triple);
|
||||
let mut path = Path::new(install_prefix);
|
||||
path.push_path(&tlib);
|
||||
path.push(&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()
|
||||
|
@ -100,7 +100,7 @@ fn get_target_lib_path(&self) -> Path {
|
||||
}
|
||||
fn get_target_lib_file_path(&self, file: &Path) -> Path {
|
||||
let mut p = self.get_target_lib_path();
|
||||
p.push_path(file);
|
||||
p.push(file);
|
||||
p
|
||||
}
|
||||
}
|
||||
@ -148,7 +148,7 @@ pub fn relative_target_lib_path(target_triple: &str) -> Path {
|
||||
|
||||
fn make_target_lib_path(sysroot: &Path,
|
||||
target_triple: &str) -> Path {
|
||||
sysroot.join_path(&relative_target_lib_path(target_triple))
|
||||
sysroot.join(&relative_target_lib_path(target_triple))
|
||||
}
|
||||
|
||||
fn make_rustpkg_target_lib_path(dir: &Path,
|
||||
@ -196,7 +196,7 @@ pub fn rust_path() -> ~[Path] {
|
||||
}
|
||||
None => ~[]
|
||||
};
|
||||
let cwd = os::getcwd();
|
||||
let mut cwd = os::getcwd();
|
||||
// now add in default entries
|
||||
let cwd_dot_rust = cwd.join(".rust");
|
||||
if !env_rust_path.contains(&cwd_dot_rust) {
|
||||
@ -205,30 +205,27 @@ pub fn rust_path() -> ~[Path] {
|
||||
if !env_rust_path.contains(&cwd) {
|
||||
env_rust_path.push(cwd.clone());
|
||||
}
|
||||
do cwd.each_parent() |p| {
|
||||
if !env_rust_path.contains(&p.join(".rust")) {
|
||||
push_if_exists(&mut env_rust_path, p);
|
||||
loop {
|
||||
let f = cwd.pop();
|
||||
if f.is_none() || bytes!("..") == f.unwrap() {
|
||||
break;
|
||||
}
|
||||
true
|
||||
};
|
||||
cwd.push(".rust");
|
||||
if !env_rust_path.contains(&cwd) && os::path_exists(&cwd) {
|
||||
env_rust_path.push(cwd.clone());
|
||||
}
|
||||
cwd.pop();
|
||||
}
|
||||
let h = os::homedir();
|
||||
for h in h.iter() {
|
||||
if !env_rust_path.contains(&h.join(".rust")) {
|
||||
push_if_exists(&mut env_rust_path, h);
|
||||
let p = h.join(".rust");
|
||||
if !env_rust_path.contains(&p) && os::path_exists(&p) {
|
||||
env_rust_path.push(p);
|
||||
}
|
||||
}
|
||||
env_rust_path
|
||||
}
|
||||
|
||||
|
||||
/// Adds p/.rust into vec, only if it exists
|
||||
fn push_if_exists(vec: &mut ~[Path], p: &Path) {
|
||||
let maybe_dir = p.join(".rust");
|
||||
if os::path_exists(&maybe_dir) {
|
||||
vec.push(maybe_dir);
|
||||
}
|
||||
}
|
||||
|
||||
// The name of the directory rustc expects libraries to be located.
|
||||
// On Unix should be "lib", on windows "bin"
|
||||
pub fn libdir() -> ~str {
|
||||
|
@ -95,20 +95,20 @@ pub fn new(mut source_workspace: Path,
|
||||
// We search for sources under both src/ and build/ , because build/ is where
|
||||
// automatically-checked-out sources go.
|
||||
let mut result = source_workspace.join("src");
|
||||
result.push_path(&id.path.dir_path());
|
||||
result.push(&id.path.dir_path());
|
||||
result.push(format!("{}-{}", id.short_name, id.version.to_str()));
|
||||
to_try.push(result);
|
||||
let mut result = source_workspace.join("src");
|
||||
result.push_path(&id.path);
|
||||
result.push(&id.path);
|
||||
to_try.push(result);
|
||||
|
||||
let mut result = build_dir.join("src");
|
||||
result.push_path(&id.path.dir_path());
|
||||
result.push(&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 mut other_result = build_dir.join("src");
|
||||
other_result.push_path(&id.path);
|
||||
other_result.push(&id.path);
|
||||
to_try.push(other_result.clone());
|
||||
output_names.push(other_result);
|
||||
|
||||
@ -146,7 +146,7 @@ pub fn new(mut source_workspace: Path,
|
||||
source_workspace: source.clone(),
|
||||
build_in_destination: build_in_destination,
|
||||
destination_workspace: destination,
|
||||
start_dir: start.join_path(&suffix),
|
||||
start_dir: start.join(&suffix),
|
||||
id: id,
|
||||
libs: ~[],
|
||||
mains: ~[],
|
||||
@ -371,7 +371,7 @@ fn build_crates(&self,
|
||||
cfgs: &[~str],
|
||||
what: OutputType) {
|
||||
for crate in crates.iter() {
|
||||
let path = self.start_dir.join_path(&crate.file);
|
||||
let path = self.start_dir.join(&crate.file);
|
||||
debug2!("build_crates: compiling {}", path.display());
|
||||
let cfgs = crate.cfgs + cfgs;
|
||||
|
||||
@ -416,7 +416,7 @@ pub fn declare_inputs(&self, prep: &mut workcache::Prep) {
|
||||
debug2!("In declare inputs, self = {}", self.to_str());
|
||||
for cs in to_do.iter() {
|
||||
for c in cs.iter() {
|
||||
let path = self.start_dir.join_path(&c.file);
|
||||
let path = self.start_dir.join(&c.file);
|
||||
debug2!("Declaring input: {}", path.display());
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
prep.declare_input("file", path.as_str().unwrap(),
|
||||
|
@ -68,7 +68,7 @@ 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.join_path(&pkgid.path) || {
|
||||
if *p == src_dir.join(&pkgid.path) || {
|
||||
let pf = p.filename_str();
|
||||
do pf.iter().any |&g| {
|
||||
match split_version_general(g, '-') {
|
||||
@ -196,7 +196,7 @@ pub fn library_in_workspace(path: &Path, short_name: &str, where: Target,
|
||||
prefix = {}", short_name, where, workspace.display(), prefix);
|
||||
|
||||
let dir_to_search = match where {
|
||||
Build => target_build_dir(workspace).join_path(path),
|
||||
Build => target_build_dir(workspace).join(path),
|
||||
Install => target_lib_dir(workspace)
|
||||
};
|
||||
|
||||
@ -273,7 +273,7 @@ fn library_in(short_name: &str, version: &Version, dir_to_search: &Path) -> Opti
|
||||
// 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.join_path(&result_filename);
|
||||
let absolute_path = dir_to_search.join(&result_filename);
|
||||
debug2!("result_filename = {}", absolute_path.display());
|
||||
absolute_path
|
||||
};
|
||||
@ -329,7 +329,7 @@ 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).join_path(&pkgid.path),
|
||||
(Build, _) => target_build_dir(workspace).join(&pkgid.path),
|
||||
(Install, Lib) => target_lib_dir(workspace),
|
||||
(Install, _) => target_bin_dir(workspace)
|
||||
};
|
||||
@ -347,7 +347,7 @@ 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.push_path(&pkgid.path);
|
||||
result.push(&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) {
|
||||
@ -370,7 +370,7 @@ 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.join_path(&pkg_id.path)
|
||||
Build => workspace.join(&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() },
|
||||
@ -388,7 +388,7 @@ pub fn mk_output_path(what: OutputType, where: Target,
|
||||
os::EXE_SUFFIX))
|
||||
};
|
||||
if !output_path.is_absolute() {
|
||||
output_path = os::getcwd().join_path(&output_path);
|
||||
output_path = os::getcwd().join(&output_path);
|
||||
}
|
||||
debug2!("mk_output_path: returning {}", output_path.display());
|
||||
output_path
|
||||
|
@ -416,15 +416,15 @@ fn build(&self, pkg_src: &mut PkgSrc, what_to_build: &WhatToBuild) {
|
||||
|
||||
debug2!("build: workspace = {} (in Rust path? {:?} is git dir? {:?} \
|
||||
pkgid = {} pkgsrc start_dir = {}", workspace.display(),
|
||||
in_rust_path(&workspace), is_git_dir(&workspace.join_path(&pkgid.path)),
|
||||
in_rust_path(&workspace), is_git_dir(&workspace.join(&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.join_path(&pkgid.path)) {
|
||||
if !in_rust_path(&workspace) && is_git_dir(&workspace.join(&pkgid.path)) {
|
||||
let mut out_dir = default_workspace().join("src");
|
||||
out_dir.push_path(&pkgid.path);
|
||||
let git_result = source_control::safe_git_clone(&workspace.join_path(&pkgid.path),
|
||||
out_dir.push(&pkgid.path);
|
||||
let git_result = source_control::safe_git_clone(&workspace.join(&pkgid.path),
|
||||
&pkgid.version,
|
||||
&out_dir);
|
||||
match git_result {
|
||||
@ -494,7 +494,7 @@ fn build(&self, pkg_src: &mut PkgSrc, what_to_build: &WhatToBuild) {
|
||||
// We expect that p is relative to the package source's start directory,
|
||||
// so check that assumption
|
||||
debug2!("JustOne: p = {}", p.display());
|
||||
assert!(os::path_exists(&pkg_src.start_dir.join_path(p)));
|
||||
assert!(os::path_exists(&pkg_src.start_dir.join(p)));
|
||||
if is_lib(p) {
|
||||
PkgSrc::push_crate(&mut pkg_src.libs, 0, p);
|
||||
} else if is_main(p) {
|
||||
@ -553,7 +553,7 @@ fn install(&self, mut pkg_src: PkgSrc, what: &WhatToBuild) -> (~[Path], ~[(~str,
|
||||
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.join_path(&c.file);
|
||||
let path = pkg_src.start_dir.join(&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()));
|
||||
|
@ -156,7 +156,7 @@ fn run_git(args: &[~str], env: Option<~[(~str, ~str)]>, cwd: &Path, err_msg: &st
|
||||
fn init_git_repo(p: &Path) -> TempDir {
|
||||
assert!(p.is_relative());
|
||||
let tmp = TempDir::new("git_local").expect("couldn't create temp dir");
|
||||
let work_dir = tmp.path().join_path(p);
|
||||
let work_dir = tmp.path().join(p);
|
||||
let work_dir_for_opts = work_dir.clone();
|
||||
assert!(os::mkdir_recursive(&work_dir, U_RWX));
|
||||
debug2!("Running: git init in {}", work_dir.display());
|
||||
@ -793,7 +793,7 @@ fn test_package_request_version() {
|
||||
== repo.join_many([".rust", "bin", "test_pkg_version"]));
|
||||
|
||||
let mut dir = target_build_dir(&repo.join(".rust"));
|
||||
dir.push_path(&Path::new("src/mockgithub.com/catamorphism/test_pkg_version-0.3"));
|
||||
dir.push(&Path::new("src/mockgithub.com/catamorphism/test_pkg_version-0.3"));
|
||||
debug2!("dir = {}", dir.display());
|
||||
assert!(os::path_is_dir(&dir));
|
||||
assert!(os::path_exists(&dir.join("version-0.3-file.txt")));
|
||||
|
@ -177,7 +177,7 @@ pub fn compile_input(context: &BuildContext,
|
||||
// not sure if we should support anything else
|
||||
|
||||
let mut out_dir = target_build_dir(workspace);
|
||||
out_dir.push_path(&pkg_id.path);
|
||||
out_dir.push(&pkg_id.path);
|
||||
// Make the output directory if it doesn't exist already
|
||||
assert!(os::mkdir_recursive(&out_dir, U_RWX));
|
||||
|
||||
|
@ -98,7 +98,7 @@ 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.join_path(local_path);
|
||||
let local_path = rp.join(local_path);
|
||||
let git_dir = local_path.join(".git");
|
||||
if !os::path_is_dir(&git_dir) {
|
||||
continue;
|
||||
|
@ -78,7 +78,7 @@ pub fn getcwd() -> Path {
|
||||
fail2!()
|
||||
}
|
||||
|
||||
GenericPath::from_c_str(CString::new(buf as *c_char, false))
|
||||
Path::new(CString::new(buf as *c_char, false))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -608,7 +608,7 @@ fn lookup() -> Path {
|
||||
pub fn walk_dir(p: &Path, f: &fn(&Path) -> bool) -> bool {
|
||||
let r = list_dir(p);
|
||||
r.iter().advance(|q| {
|
||||
let path = &p.join_path(q);
|
||||
let path = &p.join(q);
|
||||
f(path) && (!path_is_dir(path) || walk_dir(path, |p| f(p)))
|
||||
})
|
||||
}
|
||||
@ -648,7 +648,7 @@ pub fn make_absolute(p: &Path) -> Path {
|
||||
p.clone()
|
||||
} else {
|
||||
let mut ret = getcwd();
|
||||
ret.push_path(p);
|
||||
ret.push(p);
|
||||
ret
|
||||
}
|
||||
}
|
||||
@ -730,7 +730,7 @@ unsafe fn get_list(p: &Path) -> ~[Path] {
|
||||
let mut entry_ptr = readdir(dir_ptr);
|
||||
while (entry_ptr as uint != 0) {
|
||||
let cstr = CString::new(rust_list_dir_val(entry_ptr), false);
|
||||
paths.push(GenericPath::from_c_str(cstr));
|
||||
paths.push(Path::new(cstr));
|
||||
entry_ptr = readdir(dir_ptr);
|
||||
}
|
||||
closedir(dir_ptr);
|
||||
@ -800,7 +800,7 @@ unsafe fn get_list(p: &Path) -> ~[Path] {
|
||||
* This version prepends each entry with the directory.
|
||||
*/
|
||||
pub fn list_dir_path(p: &Path) -> ~[Path] {
|
||||
list_dir(p).map(|f| p.join_path(f))
|
||||
list_dir(p).map(|f| p.join(f))
|
||||
}
|
||||
|
||||
/// Removes a directory at the specified path, after removing
|
||||
|
@ -30,9 +30,7 @@
|
||||
## Usage
|
||||
|
||||
Usage of this module is fairly straightforward. Unless writing platform-specific
|
||||
code, `Path` should be used to refer to the platform-native path, and methods
|
||||
used should be restricted to those defined in `GenericPath`, and those methods
|
||||
that are declared identically on both `PosixPath` and `WindowsPath`.
|
||||
code, `Path` should be used to refer to the platform-native path.
|
||||
|
||||
Creation of a path is typically done with either `Path::new(some_str)` or
|
||||
`Path::new(some_vec)`. This path can be modified with `.push()` and
|
||||
@ -69,7 +67,6 @@
|
||||
use container::Container;
|
||||
use c_str::CString;
|
||||
use clone::Clone;
|
||||
use either::{Left, Right};
|
||||
use fmt;
|
||||
use iter::Iterator;
|
||||
use option::{Option, None, Some};
|
||||
@ -121,6 +118,19 @@
|
||||
#[cfg(windows)]
|
||||
pub use RevStrComponentIter = self::windows::RevStrComponentIter;
|
||||
|
||||
/// Typedef for the platform-native separator char func
|
||||
#[cfg(unix)]
|
||||
pub use is_sep = self::posix::is_sep;
|
||||
/// Typedef for the platform-native separator char func
|
||||
#[cfg(windows)]
|
||||
pub use is_sep = self::windows::is_sep;
|
||||
/// Typedef for the platform-native separator byte func
|
||||
#[cfg(unix)]
|
||||
pub use is_sep_byte = self::posix::is_sep_byte;
|
||||
/// Typedef for the platform-native separator byte func
|
||||
#[cfg(windows)]
|
||||
pub use is_sep_byte = self::windows::is_sep_byte;
|
||||
|
||||
pub mod posix;
|
||||
pub mod windows;
|
||||
|
||||
@ -162,19 +172,6 @@ fn new_opt<T: BytesContainer>(path: T) -> Option<Self> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new Path from a CString.
|
||||
/// The resulting Path will always be normalized.
|
||||
///
|
||||
/// See individual Path impls for potential restrictions.
|
||||
#[inline]
|
||||
fn from_c_str(path: CString) -> Self {
|
||||
// CStrings can't contain NULs
|
||||
let v = path.as_bytes();
|
||||
// v is NUL-terminated. Strip it off
|
||||
let v = v.slice_to(v.len()-1);
|
||||
unsafe { GenericPathUnsafe::new_unchecked(v) }
|
||||
}
|
||||
|
||||
/// Returns the path as a string, if possible.
|
||||
/// If the path is not representable in utf-8, this returns None.
|
||||
#[inline]
|
||||
@ -195,15 +192,15 @@ fn as_str<'a>(&'a self) -> Option<&'a str> {
|
||||
///
|
||||
/// This will print the equivalent of `to_display_str()` when used with a {} format parameter.
|
||||
fn display<'a>(&'a self) -> Display<'a, Self> {
|
||||
Display{ path: self }
|
||||
Display{ path: self, filename: false }
|
||||
}
|
||||
|
||||
/// Returns an object that implements `fmt::Default` for printing filenames
|
||||
///
|
||||
/// This will print the equivalent of `to_filename_display_str()` when used with a {}
|
||||
/// format parameter. If there is no filename, nothing will be printed.
|
||||
fn filename_display<'a>(&'a self) -> FilenameDisplay<'a, Self> {
|
||||
FilenameDisplay{ path: self }
|
||||
fn filename_display<'a>(&'a self) -> Display<'a, Self> {
|
||||
Display{ path: self, filename: true }
|
||||
}
|
||||
|
||||
/// Returns the directory component of `self`, as a byte vector (with no trailing separator).
|
||||
@ -314,13 +311,17 @@ fn set_filename<T: BytesContainer>(&mut self, filename: T) {
|
||||
/// Raises the `null_byte` condition if the filestem contains a NUL.
|
||||
fn set_filestem<T: BytesContainer>(&mut self, filestem: T) {
|
||||
// borrowck is being a pain here
|
||||
enum Value<T> {
|
||||
Checked(T),
|
||||
Unchecked(~[u8])
|
||||
}
|
||||
let val = {
|
||||
match self.filename() {
|
||||
None => Left(filestem),
|
||||
None => Checked(filestem),
|
||||
Some(name) => {
|
||||
let dot = '.' as u8;
|
||||
match name.rposition_elem(&dot) {
|
||||
None | Some(0) => Left(filestem),
|
||||
None | Some(0) => Checked(filestem),
|
||||
Some(idx) => {
|
||||
let mut v;
|
||||
if contains_nul(filestem.container_as_bytes()) {
|
||||
@ -336,15 +337,15 @@ fn set_filestem<T: BytesContainer>(&mut self, filestem: T) {
|
||||
v.push_all(filestem);
|
||||
}
|
||||
v.push_all(name.slice_from(idx));
|
||||
Right(v)
|
||||
Unchecked(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
match val {
|
||||
Left(v) => self.set_filename(v),
|
||||
Right(v) => unsafe { self.set_filename_unchecked(v) }
|
||||
Checked(v) => self.set_filename(v),
|
||||
Unchecked(v) => unsafe { self.set_filename_unchecked(v) }
|
||||
}
|
||||
}
|
||||
/// Replaces the extension with the given byte vector or string.
|
||||
@ -545,12 +546,6 @@ fn push<T: BytesContainer>(&mut self, path: T) {
|
||||
unsafe { self.push_unchecked(path) }
|
||||
}
|
||||
}
|
||||
/// Pushes a Path onto `self`.
|
||||
/// If the argument represents an absolute path, it replaces `self`.
|
||||
#[inline]
|
||||
fn push_path(&mut self, path: &Self) {
|
||||
self.push(path.as_vec())
|
||||
}
|
||||
/// Pushes multiple paths (as byte vectors or strings) onto `self`.
|
||||
/// See `push` for details.
|
||||
#[inline]
|
||||
@ -590,14 +585,6 @@ fn join<T: BytesContainer>(&self, path: T) -> Self {
|
||||
p.push(path);
|
||||
p
|
||||
}
|
||||
/// Returns a new Path constructed by joining `self` with the given path.
|
||||
/// If the given path is absolute, the new Path will represent just that.
|
||||
#[inline]
|
||||
fn join_path(&self, path: &Self) -> Self {
|
||||
let mut p = self.clone();
|
||||
p.push_path(path);
|
||||
p
|
||||
}
|
||||
/// Returns a new Path constructed by joining `self` with the given paths
|
||||
/// (as byte vectors or strings).
|
||||
/// See `join` for details.
|
||||
@ -632,21 +619,6 @@ fn is_relative(&self) -> bool {
|
||||
/// paths refer to separate drives, an absolute path is returned.
|
||||
fn path_relative_from(&self, base: &Self) -> Option<Self>;
|
||||
|
||||
/// Executes a callback with the receiver and every parent
|
||||
fn each_parent(&self, f: &fn(&Self) -> bool) -> bool {
|
||||
let mut p = self.clone();
|
||||
loop {
|
||||
if !f(&p) {
|
||||
return false;
|
||||
}
|
||||
let f = p.pop();
|
||||
if f.is_none() || bytes!("..") == f.unwrap() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
/// Returns whether the relative path `child` is a suffix of `self`.
|
||||
fn ends_with_path(&self, child: &Self) -> bool;
|
||||
}
|
||||
@ -674,7 +646,7 @@ fn container_as_str<'a>(&'a self) -> &'a str {
|
||||
fn container_as_str_opt<'a>(&'a self) -> Option<&'a str> {
|
||||
str::from_utf8_slice_opt(self.container_as_bytes())
|
||||
}
|
||||
/// Returns whether the concrete receiver is a string type
|
||||
/// Returns whether .container_as_str() is guaranteed to not fail
|
||||
// FIXME (#8888): Remove unused arg once ::<for T> works
|
||||
#[inline]
|
||||
fn is_str(_: Option<Self>) -> bool { false }
|
||||
@ -703,11 +675,8 @@ pub trait GenericPathUnsafe {
|
||||
|
||||
/// Helper struct for printing paths with format!()
|
||||
pub struct Display<'self, P> {
|
||||
priv path: &'self P
|
||||
}
|
||||
/// Helper struct for printing filenames with format!()
|
||||
pub struct FilenameDisplay<'self, P> {
|
||||
priv path: &'self P
|
||||
priv path: &'self P,
|
||||
priv filename: bool
|
||||
}
|
||||
|
||||
impl<'self, P: GenericPath> fmt::Default for Display<'self, P> {
|
||||
@ -724,7 +693,14 @@ impl<'self, P: GenericPath> ToStr for Display<'self, P> {
|
||||
/// If the path is not UTF-8, invalid sequences with be replaced with the
|
||||
/// unicode replacement char. This involves allocation.
|
||||
fn to_str(&self) -> ~str {
|
||||
from_utf8_with_replacement(self.path.as_vec())
|
||||
if self.filename {
|
||||
match self.path.filename() {
|
||||
None => ~"",
|
||||
Some(v) => from_utf8_with_replacement(v)
|
||||
}
|
||||
} else {
|
||||
from_utf8_with_replacement(self.path.as_vec())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -735,47 +711,9 @@ impl<'self, P: GenericPath> Display<'self, P> {
|
||||
/// unicode replacement char. This involves allocation.
|
||||
#[inline]
|
||||
pub fn with_str<T>(&self, f: &fn(&str) -> T) -> T {
|
||||
match self.path.as_str() {
|
||||
Some(s) => f(s),
|
||||
None => {
|
||||
let s = self.to_str();
|
||||
f(s.as_slice())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'self, P: GenericPath> fmt::Default for FilenameDisplay<'self, P> {
|
||||
fn fmt(d: &FilenameDisplay<P>, f: &mut fmt::Formatter) {
|
||||
do d.with_str |s| {
|
||||
f.pad(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'self, P: GenericPath> ToStr for FilenameDisplay<'self, P> {
|
||||
/// Returns the filename as a string. If there is no filename, ~"" will be
|
||||
/// returned.
|
||||
///
|
||||
/// If the filename is not UTF-8, invalid sequences will be replaced with
|
||||
/// the unicode replacement char. This involves allocation.
|
||||
fn to_str(&self) -> ~str {
|
||||
match self.path.filename() {
|
||||
None => ~"",
|
||||
Some(v) => from_utf8_with_replacement(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'self, P: GenericPath> FilenameDisplay<'self, P> {
|
||||
/// Provides the filename as a string to a closure. If there is no
|
||||
/// filename, "" will be provided.
|
||||
///
|
||||
/// If the filename is not UTF-8, invalid sequences will be replaced with
|
||||
/// the unicode replacement char. This involves allocation.
|
||||
#[inline]
|
||||
pub fn with_str<T>(&self, f: &fn(&str) -> T) -> T {
|
||||
match self.path.filename_str() {
|
||||
let opt = if self.filename { self.path.filename_str() }
|
||||
else { self.path.as_str() };
|
||||
match opt {
|
||||
Some(s) => f(s),
|
||||
None => {
|
||||
let s = self.to_str();
|
||||
@ -865,6 +803,14 @@ fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
|
||||
}
|
||||
}
|
||||
|
||||
impl BytesContainer for CString {
|
||||
#[inline]
|
||||
fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
|
||||
let s = self.as_bytes();
|
||||
s.slice_to(s.len()-1)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn contains_nul(v: &[u8]) -> bool {
|
||||
v.iter().any(|&x| x == 0)
|
||||
@ -1121,13 +1067,13 @@ mod tests {
|
||||
use c_str::ToCStr;
|
||||
|
||||
#[test]
|
||||
fn test_from_c_str() {
|
||||
fn test_cstring() {
|
||||
let input = "/foo/bar/baz";
|
||||
let path: PosixPath = GenericPath::from_c_str(input.to_c_str());
|
||||
let path: PosixPath = PosixPath::new(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());
|
||||
let path: WindowsPath = WindowsPath::new(input.to_c_str());
|
||||
assert_eq!(path.as_str().unwrap(), input.as_slice());
|
||||
}
|
||||
}
|
||||
|
@ -48,12 +48,19 @@ pub struct Path {
|
||||
}
|
||||
|
||||
/// The standard path separator character
|
||||
pub static sep: u8 = '/' as u8;
|
||||
pub static sep: char = '/';
|
||||
static sep_byte: u8 = sep as u8;
|
||||
|
||||
/// Returns whether the given byte is a path separator
|
||||
#[inline]
|
||||
pub fn is_sep(u: &u8) -> bool {
|
||||
*u == sep
|
||||
pub fn is_sep_byte(u: &u8) -> bool {
|
||||
*u as char == sep
|
||||
}
|
||||
|
||||
/// Returns whether the given char is a path separator
|
||||
#[inline]
|
||||
pub fn is_sep(c: char) -> bool {
|
||||
c == sep
|
||||
}
|
||||
|
||||
impl Eq for Path {
|
||||
@ -89,11 +96,29 @@ fn iter_bytes(&self, lsb0: bool, f: &fn(buf: &[u8]) -> bool) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
impl BytesContainer for Path {
|
||||
#[inline]
|
||||
fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
|
||||
self.as_vec()
|
||||
}
|
||||
#[inline]
|
||||
fn container_into_owned_bytes(self) -> ~[u8] {
|
||||
self.into_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'self> BytesContainer for &'self Path {
|
||||
#[inline]
|
||||
fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
|
||||
self.as_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl GenericPathUnsafe for Path {
|
||||
unsafe fn new_unchecked<T: BytesContainer>(path: T) -> Path {
|
||||
let path = Path::normalize(path.container_as_bytes());
|
||||
assert!(!path.is_empty());
|
||||
let idx = path.rposition_elem(&sep);
|
||||
let idx = path.rposition_elem(&sep_byte);
|
||||
Path{ repr: path, sepidx: idx }
|
||||
}
|
||||
|
||||
@ -106,11 +131,11 @@ unsafe fn set_dirname_unchecked<T: BytesContainer>(&mut self, dirname: T) {
|
||||
None => {
|
||||
let mut v = vec::with_capacity(dirname.len() + self.repr.len() + 1);
|
||||
v.push_all(dirname);
|
||||
v.push(sep);
|
||||
v.push(sep_byte);
|
||||
v.push_all(self.repr);
|
||||
self.repr = Path::normalize(v);
|
||||
}
|
||||
Some(0) if self.repr.len() == 1 && self.repr[0] == sep => {
|
||||
Some(0) if self.repr.len() == 1 && self.repr[0] == sep_byte => {
|
||||
self.repr = Path::normalize(dirname);
|
||||
}
|
||||
Some(idx) if self.repr.slice_from(idx+1) == bytes!("..") => {
|
||||
@ -127,7 +152,7 @@ unsafe fn set_dirname_unchecked<T: BytesContainer>(&mut self, dirname: T) {
|
||||
self.repr = Path::normalize(v);
|
||||
}
|
||||
}
|
||||
self.sepidx = self.repr.rposition_elem(&sep);
|
||||
self.sepidx = self.repr.rposition_elem(&sep_byte);
|
||||
}
|
||||
|
||||
unsafe fn set_filename_unchecked<T: BytesContainer>(&mut self, filename: T) {
|
||||
@ -136,7 +161,7 @@ unsafe fn set_filename_unchecked<T: BytesContainer>(&mut self, filename: T) {
|
||||
None if bytes!("..") == self.repr => {
|
||||
let mut v = vec::with_capacity(3 + filename.len());
|
||||
v.push_all(dot_dot_static);
|
||||
v.push(sep);
|
||||
v.push(sep_byte);
|
||||
v.push_all(filename);
|
||||
self.repr = Path::normalize(v);
|
||||
}
|
||||
@ -146,7 +171,7 @@ unsafe fn set_filename_unchecked<T: BytesContainer>(&mut self, filename: T) {
|
||||
Some(idx) if self.repr.slice_from(idx+1) == bytes!("..") => {
|
||||
let mut v = vec::with_capacity(self.repr.len() + 1 + filename.len());
|
||||
v.push_all(self.repr);
|
||||
v.push(sep);
|
||||
v.push(sep_byte);
|
||||
v.push_all(filename);
|
||||
self.repr = Path::normalize(v);
|
||||
}
|
||||
@ -157,22 +182,22 @@ unsafe fn set_filename_unchecked<T: BytesContainer>(&mut self, filename: T) {
|
||||
self.repr = Path::normalize(v);
|
||||
}
|
||||
}
|
||||
self.sepidx = self.repr.rposition_elem(&sep);
|
||||
self.sepidx = self.repr.rposition_elem(&sep_byte);
|
||||
}
|
||||
|
||||
unsafe fn push_unchecked<T: BytesContainer>(&mut self, path: T) {
|
||||
let path = path.container_as_bytes();
|
||||
if !path.is_empty() {
|
||||
if path[0] == sep {
|
||||
if path[0] == sep_byte {
|
||||
self.repr = Path::normalize(path);
|
||||
} else {
|
||||
let mut v = vec::with_capacity(self.repr.len() + path.len() + 1);
|
||||
v.push_all(self.repr);
|
||||
v.push(sep);
|
||||
v.push(sep_byte);
|
||||
v.push_all(path);
|
||||
self.repr = Path::normalize(v);
|
||||
}
|
||||
self.sepidx = self.repr.rposition_elem(&sep);
|
||||
self.sepidx = self.repr.rposition_elem(&sep_byte);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -228,7 +253,7 @@ fn pop(&mut self) -> Option<~[u8]> {
|
||||
} else {
|
||||
self.repr.truncate(idx);
|
||||
}
|
||||
self.sepidx = self.repr.rposition_elem(&sep);
|
||||
self.sepidx = self.repr.rposition_elem(&sep_byte);
|
||||
Some(v)
|
||||
}
|
||||
}
|
||||
@ -244,7 +269,7 @@ fn root_path(&self) -> Option<Path> {
|
||||
|
||||
#[inline]
|
||||
fn is_absolute(&self) -> bool {
|
||||
self.repr[0] == sep
|
||||
self.repr[0] == sep_byte
|
||||
}
|
||||
|
||||
fn is_ancestor_of(&self, other: &Path) -> bool {
|
||||
@ -305,7 +330,7 @@ fn path_relative_from(&self, base: &Path) -> Option<Path> {
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(Path::new(comps.connect_vec(&sep)))
|
||||
Some(Path::new(comps.connect_vec(&sep_byte)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -347,14 +372,14 @@ pub fn new_opt<T: BytesContainer>(path: T) -> Option<Path> {
|
||||
fn normalize<V: Vector<u8>+CopyableVector<u8>>(v: V) -> ~[u8] {
|
||||
// borrowck is being very picky
|
||||
let val = {
|
||||
let is_abs = !v.as_slice().is_empty() && v.as_slice()[0] == sep;
|
||||
let is_abs = !v.as_slice().is_empty() && v.as_slice()[0] == sep_byte;
|
||||
let v_ = if is_abs { v.as_slice().slice_from(1) } else { v.as_slice() };
|
||||
let comps = normalize_helper(v_, is_abs);
|
||||
match comps {
|
||||
None => None,
|
||||
Some(comps) => {
|
||||
if is_abs && comps.is_empty() {
|
||||
Some(~[sep])
|
||||
Some(~[sep_byte])
|
||||
} else {
|
||||
let n = if is_abs { comps.len() } else { comps.len() - 1} +
|
||||
comps.iter().map(|v| v.len()).sum();
|
||||
@ -367,7 +392,7 @@ fn normalize<V: Vector<u8>+CopyableVector<u8>>(v: V) -> ~[u8] {
|
||||
}
|
||||
}
|
||||
for comp in it {
|
||||
v.push(sep);
|
||||
v.push(sep_byte);
|
||||
v.push_all(comp);
|
||||
}
|
||||
Some(v)
|
||||
@ -386,10 +411,10 @@ fn normalize<V: Vector<u8>+CopyableVector<u8>>(v: V) -> ~[u8] {
|
||||
/// /a/b/c and a/b/c yield the same set of components.
|
||||
/// A path of "/" yields no components. A path of "." yields one component.
|
||||
pub fn component_iter<'a>(&'a self) -> ComponentIter<'a> {
|
||||
let v = if self.repr[0] == sep {
|
||||
let v = if self.repr[0] == sep_byte {
|
||||
self.repr.slice_from(1)
|
||||
} else { self.repr.as_slice() };
|
||||
let mut ret = v.split_iter(is_sep);
|
||||
let mut ret = v.split_iter(is_sep_byte);
|
||||
if v.is_empty() {
|
||||
// consume the empty "" component
|
||||
ret.next();
|
||||
@ -400,10 +425,10 @@ pub fn component_iter<'a>(&'a self) -> ComponentIter<'a> {
|
||||
/// 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 {
|
||||
let v = if self.repr[0] == sep_byte {
|
||||
self.repr.slice_from(1)
|
||||
} else { self.repr.as_slice() };
|
||||
let mut ret = v.rsplit_iter(is_sep);
|
||||
let mut ret = v.rsplit_iter(is_sep_byte);
|
||||
if v.is_empty() {
|
||||
// consume the empty "" component
|
||||
ret.next();
|
||||
@ -432,7 +457,7 @@ fn normalize_helper<'a>(v: &'a [u8], is_abs: bool) -> Option<~[&'a [u8]]> {
|
||||
let mut comps: ~[&'a [u8]] = ~[];
|
||||
let mut n_up = 0u;
|
||||
let mut changed = false;
|
||||
for comp in v.split_iter(is_sep) {
|
||||
for comp in v.split_iter(is_sep_byte) {
|
||||
if comp.is_empty() { changed = true }
|
||||
else if comp == bytes!(".") { changed = true }
|
||||
else if comp == bytes!("..") {
|
||||
@ -928,7 +953,7 @@ macro_rules! t(
|
||||
{
|
||||
let mut p = Path::new($path);
|
||||
let push = Path::new($push);
|
||||
p.push_path(&push);
|
||||
p.push(&push);
|
||||
assert_eq!(p.as_str(), Some($exp));
|
||||
}
|
||||
)
|
||||
@ -1049,7 +1074,7 @@ macro_rules! t(
|
||||
{
|
||||
let path = Path::new($path);
|
||||
let join = Path::new($join);
|
||||
let res = path.join_path(&join);
|
||||
let res = path.join(&join);
|
||||
assert_eq!(res.as_str(), Some($exp));
|
||||
}
|
||||
)
|
||||
@ -1598,58 +1623,4 @@ macro_rules! t(
|
||||
// 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::new("/foo/bar").each_parent(|_| true));
|
||||
assert!(!Path::new("/foo/bar").each_parent(|_| false));
|
||||
|
||||
macro_rules! t(
|
||||
(s: $path:expr, $exp:expr) => (
|
||||
{
|
||||
let path = Path::new($path);
|
||||
let exp: &[&str] = $exp;
|
||||
let mut comps = exp.iter().map(|&x|x);
|
||||
do path.each_parent |p| {
|
||||
let p = p.as_str();
|
||||
assert!(p.is_some());
|
||||
let e = comps.next();
|
||||
assert!(e.is_some());
|
||||
assert_eq!(p.unwrap(), e.unwrap());
|
||||
true
|
||||
};
|
||||
assert!(comps.next().is_none());
|
||||
}
|
||||
);
|
||||
(v: $path:expr, $exp:expr) => (
|
||||
{
|
||||
let path = Path::new($path);
|
||||
let exp: &[&[u8]] = $exp;
|
||||
let mut comps = exp.iter().map(|&x|x);
|
||||
do path.each_parent |p| {
|
||||
let p = p.as_vec();
|
||||
let e = comps.next();
|
||||
assert!(e.is_some());
|
||||
assert_eq!(p, e.unwrap());
|
||||
true
|
||||
};
|
||||
assert!(comps.next().is_none());
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
t!(s: "/foo/bar", ["/foo/bar", "/foo", "/"]);
|
||||
t!(s: "/foo/bar/baz", ["/foo/bar/baz", "/foo/bar", "/foo", "/"]);
|
||||
t!(s: "/foo", ["/foo", "/"]);
|
||||
t!(s: "/", ["/"]);
|
||||
t!(s: "foo/bar/baz", ["foo/bar/baz", "foo/bar", "foo", "."]);
|
||||
t!(s: "foo/bar", ["foo/bar", "foo", "."]);
|
||||
t!(s: "foo", ["foo", "."]);
|
||||
t!(s: ".", ["."]);
|
||||
t!(s: "..", [".."]);
|
||||
t!(s: "../../foo", ["../../foo", "../.."]);
|
||||
|
||||
t!(v: b!("foo/bar", 0x80), [b!("foo/bar", 0x80), b!("foo"), b!(".")]);
|
||||
t!(v: b!(0xff, "/bar"), [b!(0xff, "/bar"), b!(0xff), b!(".")]);
|
||||
}
|
||||
}
|
||||
|
@ -121,6 +121,44 @@ fn iter_bytes(&self, lsb0: bool, f: &fn(&[u8]) -> bool) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
impl BytesContainer for Path {
|
||||
#[inline]
|
||||
fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
|
||||
self.as_vec()
|
||||
}
|
||||
#[inline]
|
||||
fn container_into_owned_bytes(self) -> ~[u8] {
|
||||
self.into_vec()
|
||||
}
|
||||
#[inline]
|
||||
fn container_as_str<'a>(&'a self) -> &'a str {
|
||||
self.as_str().unwrap()
|
||||
}
|
||||
#[inline]
|
||||
fn container_as_str_opt<'a>(&'a self) -> Option<&'a str> {
|
||||
self.as_str()
|
||||
}
|
||||
#[inline]
|
||||
fn is_str(_: Option<Path>) -> bool { true }
|
||||
}
|
||||
|
||||
impl<'self> BytesContainer for &'self Path {
|
||||
#[inline]
|
||||
fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
|
||||
self.as_vec()
|
||||
}
|
||||
#[inline]
|
||||
fn container_as_str<'a>(&'a self) -> &'a str {
|
||||
self.as_str().unwrap()
|
||||
}
|
||||
#[inline]
|
||||
fn container_as_str_opt<'a>(&'a self) -> Option<&'a str> {
|
||||
self.as_str()
|
||||
}
|
||||
#[inline]
|
||||
fn is_str(_: Option<&'self Path>) -> bool { true }
|
||||
}
|
||||
|
||||
impl GenericPathUnsafe for Path {
|
||||
/// See `GenericPathUnsafe::from_vec_unchecked`.
|
||||
///
|
||||
@ -235,7 +273,7 @@ unsafe fn push_unchecked<T: BytesContainer>(&mut self, path: T) {
|
||||
fn is_vol_abs(path: &str, prefix: Option<PathPrefix>) -> bool {
|
||||
// assume prefix is Some(DiskPrefix)
|
||||
let rest = path.slice_from(prefix_len(prefix));
|
||||
!rest.is_empty() && rest[0].is_ascii() && is_sep2(rest[0] as char)
|
||||
!rest.is_empty() && rest[0].is_ascii() && is_sep(rest[0] as char)
|
||||
}
|
||||
fn shares_volume(me: &Path, path: &str) -> bool {
|
||||
// path is assumed to have a prefix of Some(DiskPrefix)
|
||||
@ -246,8 +284,8 @@ fn shares_volume(me: &Path, path: &str) -> bool {
|
||||
}
|
||||
}
|
||||
fn is_sep_(prefix: Option<PathPrefix>, u: u8) -> bool {
|
||||
u.is_ascii() && if prefix_is_verbatim(prefix) { is_sep(u as char) }
|
||||
else { is_sep2(u as char) }
|
||||
if prefix_is_verbatim(prefix) { is_sep_verbatim(u as char) }
|
||||
else { is_sep(u as char) }
|
||||
}
|
||||
|
||||
fn replace_path(me: &mut Path, path: &str, prefix: Option<PathPrefix>) {
|
||||
@ -262,7 +300,7 @@ fn replace_path(me: &mut Path, path: &str, prefix: Option<PathPrefix>) {
|
||||
fn append_path(me: &mut Path, path: &str) {
|
||||
// appends a path that has no prefix
|
||||
// if me is verbatim, we need to pre-normalize the new path
|
||||
let path_ = if me.is_verbatim() { Path::normalize__(path, None) }
|
||||
let path_ = if is_verbatim(me) { Path::normalize__(path, None) }
|
||||
else { None };
|
||||
let pathlen = path_.map_default(path.len(), |p| p.len());
|
||||
let mut s = str::with_capacity(me.repr.len() + 1 + pathlen);
|
||||
@ -291,7 +329,7 @@ fn append_path(me: &mut Path, path: &str) {
|
||||
}
|
||||
None if !path.is_empty() && is_sep_(self.prefix, path[0]) => {
|
||||
// volume-relative path
|
||||
if self.prefix().is_some() {
|
||||
if self.prefix.is_some() {
|
||||
// truncate self down to the prefix, then append
|
||||
let n = self.prefix_len();
|
||||
self.repr.truncate(n);
|
||||
@ -418,11 +456,6 @@ fn file_path(&self) -> Option<Path> {
|
||||
self.filename_str().map_move(|s| unsafe { GenericPathUnsafe::new_unchecked(s) })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn push_path(&mut self, path: &Path) {
|
||||
self.push(path.as_str().unwrap())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn pop(&mut self) -> Option<~[u8]> {
|
||||
self.pop_str().map_move(|s| s.into_bytes())
|
||||
@ -463,7 +496,7 @@ fn root_path(&self) -> Option<Path> {
|
||||
}
|
||||
_ => self.repr.slice_to(self.prefix_len())
|
||||
}))
|
||||
} else if self.is_vol_relative() {
|
||||
} else if is_vol_relative(self) {
|
||||
Some(Path::new(self.repr.slice_to(1)))
|
||||
} else {
|
||||
None
|
||||
@ -493,14 +526,14 @@ fn is_absolute(&self) -> bool {
|
||||
|
||||
#[inline]
|
||||
fn is_relative(&self) -> bool {
|
||||
self.prefix.is_none() && !self.is_vol_relative()
|
||||
self.prefix.is_none() && !is_vol_relative(self)
|
||||
}
|
||||
|
||||
fn is_ancestor_of(&self, other: &Path) -> bool {
|
||||
if !self.equiv_prefix(other) {
|
||||
false
|
||||
} else if self.is_absolute() != other.is_absolute() ||
|
||||
self.is_vol_relative() != other.is_vol_relative() {
|
||||
is_vol_relative(self) != is_vol_relative(other) {
|
||||
false
|
||||
} else {
|
||||
let mut ita = self.str_component_iter().map(|x|x.unwrap());
|
||||
@ -544,8 +577,8 @@ fn comp_requires_verbatim(s: &str) -> bool {
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else if self.is_vol_relative() != base.is_vol_relative() {
|
||||
if self.is_vol_relative() {
|
||||
} else if is_vol_relative(self) != is_vol_relative(base) {
|
||||
if is_vol_relative(self) {
|
||||
Some(self.clone())
|
||||
} else {
|
||||
None
|
||||
@ -555,8 +588,8 @@ fn comp_requires_verbatim(s: &str) -> bool {
|
||||
let mut itb = base.str_component_iter().map(|x|x.unwrap());
|
||||
let mut comps = ~[];
|
||||
|
||||
let a_verb = self.is_verbatim();
|
||||
let b_verb = base.is_verbatim();
|
||||
let a_verb = is_verbatim(self);
|
||||
let b_verb = is_verbatim(base);
|
||||
loop {
|
||||
match (ita.next(), itb.next()) {
|
||||
(None, None) => break,
|
||||
@ -598,20 +631,6 @@ fn comp_requires_verbatim(s: &str) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
fn each_parent(&self, f: &fn(&Path) -> bool) -> bool {
|
||||
let mut p = self.clone();
|
||||
loop {
|
||||
if !f(&p) {
|
||||
return false;
|
||||
}
|
||||
let f = p.pop();
|
||||
if f.is_none() || (!p.is_verbatim() && bytes!("..") == f.unwrap()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn ends_with_path(&self, child: &Path) -> bool {
|
||||
if !child.is_relative() { return false; }
|
||||
let mut selfit = self.str_component_iter().invert();
|
||||
@ -694,34 +713,6 @@ fn convert<'a>(x: Option<&'a str>) -> &'a [u8] {
|
||||
self.rev_str_component_iter().map(convert)
|
||||
}
|
||||
|
||||
/// 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.
|
||||
#[inline]
|
||||
pub fn is_vol_relative(&self) -> bool {
|
||||
self.prefix.is_none() && self.repr[0] == sep as u8
|
||||
}
|
||||
|
||||
/// Returns whether the path is considered "cwd-relative", which means a path
|
||||
/// with a volume prefix that is not absolute. This look like "C:foo.txt". Paths
|
||||
/// of this form are relative to the cwd on the given volume.
|
||||
#[inline]
|
||||
pub fn is_cwd_relative(&self) -> bool {
|
||||
self.prefix == Some(DiskPrefix) && !self.is_absolute()
|
||||
}
|
||||
|
||||
/// Returns the PathPrefix for this Path
|
||||
#[inline]
|
||||
pub fn prefix(&self) -> Option<PathPrefix> {
|
||||
self.prefix
|
||||
}
|
||||
|
||||
/// Returns whether the prefix is a verbatim prefix, i.e. \\?\
|
||||
#[inline]
|
||||
pub fn is_verbatim(&self) -> bool {
|
||||
prefix_is_verbatim(self.prefix)
|
||||
}
|
||||
|
||||
fn equiv_prefix(&self, other: &Path) -> bool {
|
||||
match (self.prefix, other.prefix) {
|
||||
(Some(DiskPrefix), Some(VerbatimDiskPrefix)) => {
|
||||
@ -866,8 +857,8 @@ fn update_sepidx(&mut self) {
|
||||
let s = if self.has_nonsemantic_trailing_slash() {
|
||||
self.repr.slice_to(self.repr.len()-1)
|
||||
} else { self.repr.as_slice() };
|
||||
let idx = s.rfind(if !prefix_is_verbatim(self.prefix) { is_sep2 }
|
||||
else { is_sep });
|
||||
let idx = s.rfind(if !prefix_is_verbatim(self.prefix) { is_sep }
|
||||
else { is_sep_verbatim });
|
||||
let prefixlen = self.prefix_len();
|
||||
self.sepidx = idx.and_then(|x| if x < prefixlen { None } else { Some(x) });
|
||||
}
|
||||
@ -893,7 +884,7 @@ fn sepidx_or_prefix_len(&self) -> Option<(uint,uint,uint)> {
|
||||
}
|
||||
|
||||
fn has_nonsemantic_trailing_slash(&self) -> bool {
|
||||
self.is_verbatim() && self.repr.len() > self.prefix_len()+1 &&
|
||||
is_verbatim(self) && self.repr.len() > self.prefix_len()+1 &&
|
||||
self.repr[self.repr.len()-1] == sep as u8
|
||||
}
|
||||
|
||||
@ -905,23 +896,65 @@ fn update_normalized<S: Str>(&mut self, s: S) {
|
||||
}
|
||||
}
|
||||
|
||||
/// 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.
|
||||
#[inline]
|
||||
pub fn is_vol_relative(path: &Path) -> bool {
|
||||
path.prefix.is_none() && is_sep_byte(&path.repr[0])
|
||||
}
|
||||
|
||||
/// Returns whether the path is considered "cwd-relative", which means a path
|
||||
/// with a volume prefix that is not absolute. This look like "C:foo.txt". Paths
|
||||
/// of this form are relative to the cwd on the given volume.
|
||||
#[inline]
|
||||
pub fn is_cwd_relative(path: &Path) -> bool {
|
||||
path.prefix == Some(DiskPrefix) && !path.is_absolute()
|
||||
}
|
||||
|
||||
/// Returns the PathPrefix for this Path
|
||||
#[inline]
|
||||
pub fn prefix(path: &Path) -> Option<PathPrefix> {
|
||||
path.prefix
|
||||
}
|
||||
|
||||
/// Returns whether the Path's prefix is a verbatim prefix, i.e. \\?\
|
||||
#[inline]
|
||||
pub fn is_verbatim(path: &Path) -> bool {
|
||||
prefix_is_verbatim(path.prefix)
|
||||
}
|
||||
|
||||
/// The standard path separator character
|
||||
pub static sep: char = '\\';
|
||||
/// The alternative path separator character
|
||||
pub static sep2: char = '/';
|
||||
|
||||
/// Returns whether the given byte is a path separator.
|
||||
/// Only allows the primary separator '\'; use is_sep2 to allow '/'.
|
||||
/// Returns whether the given char is a path separator.
|
||||
/// Allows both the primary separator '\' and the alternative separator '/'.
|
||||
#[inline]
|
||||
pub fn is_sep(c: char) -> bool {
|
||||
c == sep || c == sep2
|
||||
}
|
||||
|
||||
/// Returns whether the given char is a path separator.
|
||||
/// Only allows the primary separator '\'; use is_sep to allow '/'.
|
||||
#[inline]
|
||||
pub fn is_sep_verbatim(c: char) -> bool {
|
||||
c == sep
|
||||
}
|
||||
|
||||
/// Returns whether the given byte is a path separator.
|
||||
/// Allows both the primary separator '\' and the alternative separator '/'.
|
||||
#[inline]
|
||||
pub fn is_sep2(c: char) -> bool {
|
||||
c == sep || c == sep2
|
||||
pub fn is_sep_byte(u: &u8) -> bool {
|
||||
*u as char == sep || *u as char == sep2
|
||||
}
|
||||
|
||||
/// Returns whether the given byte is a path separator.
|
||||
/// Only allows the primary separator '\'; use is_sep_byte to allow '/'.
|
||||
#[inline]
|
||||
pub fn is_sep_byte_verbatim(u: &u8) -> bool {
|
||||
*u as char == sep
|
||||
}
|
||||
|
||||
/// Prefix types for Path
|
||||
@ -953,7 +986,7 @@ pub fn parse_prefix<'a>(mut path: &'a str) -> Option<PathPrefix> {
|
||||
if path.starts_with("UNC\\") {
|
||||
// \\?\UNC\server\share
|
||||
path = path.slice_from(4);
|
||||
let (idx_a, idx_b) = match parse_two_comps(path, is_sep) {
|
||||
let (idx_a, idx_b) = match parse_two_comps(path, is_sep_verbatim) {
|
||||
Some(x) => x,
|
||||
None => (path.len(), 0)
|
||||
};
|
||||
@ -977,7 +1010,7 @@ pub fn parse_prefix<'a>(mut path: &'a str) -> Option<PathPrefix> {
|
||||
let idx = path.find('\\').unwrap_or(path.len());
|
||||
return Some(DeviceNSPrefix(idx));
|
||||
}
|
||||
match parse_two_comps(path, is_sep2) {
|
||||
match parse_two_comps(path, is_sep) {
|
||||
Some((idx_a, idx_b)) if idx_a > 0 && idx_b > 0 => {
|
||||
// \\server\share
|
||||
return Some(UNCPrefix(idx_a, idx_b));
|
||||
@ -1006,14 +1039,14 @@ fn parse_two_comps<'a>(mut path: &'a str, f: &fn(char)->bool) -> Option<(uint, u
|
||||
|
||||
// None result means the string didn't need normalizing
|
||||
fn normalize_helper<'a>(s: &'a str, prefix: Option<PathPrefix>) -> (bool,Option<~[&'a str]>) {
|
||||
let f = if !prefix_is_verbatim(prefix) { is_sep2 } else { is_sep };
|
||||
let f = if !prefix_is_verbatim(prefix) { is_sep } else { is_sep_verbatim };
|
||||
let is_abs = s.len() > prefix_len(prefix) && f(s.char_at(prefix_len(prefix)));
|
||||
let s_ = s.slice_from(prefix_len(prefix));
|
||||
let s_ = if is_abs { s_.slice_from(1) } else { s_ };
|
||||
|
||||
if is_abs && s_.is_empty() {
|
||||
return (is_abs, match prefix {
|
||||
Some(DiskPrefix) | None => (if is_sep(s.char_at(prefix_len(prefix))) { None }
|
||||
Some(DiskPrefix) | None => (if is_sep_verbatim(s.char_at(prefix_len(prefix))) { None }
|
||||
else { Some(~[]) }),
|
||||
Some(_) => Some(~[]), // need to trim the trailing separator
|
||||
});
|
||||
@ -1036,7 +1069,7 @@ fn normalize_helper<'a>(s: &'a str, prefix: Option<PathPrefix>) -> (bool,Option<
|
||||
} else { comps.push(comp) }
|
||||
}
|
||||
if !changed && !prefix_is_verbatim(prefix) {
|
||||
changed = s.find(is_sep2).is_some();
|
||||
changed = s.find(is_sep).is_some();
|
||||
}
|
||||
if changed {
|
||||
if comps.is_empty() && !is_abs && prefix.is_none() {
|
||||
@ -1078,8 +1111,8 @@ fn prefix_len(p: Option<PathPrefix>) -> uint {
|
||||
}
|
||||
|
||||
fn prefix_is_sep(p: Option<PathPrefix>, c: u8) -> bool {
|
||||
c.is_ascii() && if !prefix_is_verbatim(p) { is_sep2(c as char) }
|
||||
else { is_sep(c as char) }
|
||||
c.is_ascii() && if !prefix_is_verbatim(p) { is_sep(c as char) }
|
||||
else { is_sep_verbatim(c as char) }
|
||||
}
|
||||
|
||||
// Stat support
|
||||
@ -1636,9 +1669,9 @@ macro_rules! t(
|
||||
|
||||
// we do want to check one odd case though to ensure the prefix is re-parsed
|
||||
let mut p = Path::new("\\\\?\\C:");
|
||||
assert_eq!(p.prefix(), Some(VerbatimPrefix(2)));
|
||||
assert_eq!(prefix(&p), Some(VerbatimPrefix(2)));
|
||||
p.push("foo");
|
||||
assert_eq!(p.prefix(), Some(VerbatimDiskPrefix));
|
||||
assert_eq!(prefix(&p), Some(VerbatimDiskPrefix));
|
||||
assert_eq!(p.as_str(), Some("\\\\?\\C:\\foo"));
|
||||
|
||||
// and another with verbatim non-normalized paths
|
||||
@ -1654,7 +1687,7 @@ macro_rules! t(
|
||||
{
|
||||
let mut p = Path::new($path);
|
||||
let push = Path::new($push);
|
||||
p.push_path(&push);
|
||||
p.push(&push);
|
||||
assert_eq!(p.as_str(), Some($exp));
|
||||
}
|
||||
)
|
||||
@ -1837,7 +1870,7 @@ macro_rules! t(
|
||||
{
|
||||
let path = Path::new($path);
|
||||
let join = Path::new($join);
|
||||
let res = path.join_path(&join);
|
||||
let res = path.join(&join);
|
||||
assert_eq!(res.as_str(), Some($exp));
|
||||
}
|
||||
)
|
||||
@ -1849,7 +1882,7 @@ macro_rules! t(
|
||||
t!(s: "a\\b", "\\c\\d", "\\c\\d");
|
||||
t!(s: ".", "a\\b", "a\\b");
|
||||
t!(s: "\\", "a\\b", "\\a\\b");
|
||||
// join_path is implemented using push_path, so there's no need for
|
||||
// join is implemented using push, so there's no need for
|
||||
// the full set of prefix tests
|
||||
}
|
||||
|
||||
@ -2217,11 +2250,11 @@ macro_rules! t(
|
||||
let b = path.is_absolute();
|
||||
assert!(b == abs, "Path '{}'.is_absolute(): expected {:?}, found {:?}",
|
||||
path.as_str().unwrap(), abs, b);
|
||||
let b = path.is_vol_relative();
|
||||
assert!(b == vol, "Path '{}'.is_vol_relative(): expected {:?}, found {:?}",
|
||||
let b = is_vol_relative(&path);
|
||||
assert!(b == vol, "is_vol_relative('{}'): expected {:?}, found {:?}",
|
||||
path.as_str().unwrap(), vol, b);
|
||||
let b = path.is_cwd_relative();
|
||||
assert!(b == cwd, "Path '{}'.is_cwd_relative(): expected {:?}, found {:?}",
|
||||
let b = is_cwd_relative(&path);
|
||||
assert!(b == cwd, "is_cwd_relative('{}'): expected {:?}, found {:?}",
|
||||
path.as_str().unwrap(), cwd, b);
|
||||
let b = path.is_relative();
|
||||
assert!(b == rel, "Path '{}'.is_relativf(): expected {:?}, found {:?}",
|
||||
@ -2614,54 +2647,4 @@ macro_rules! t(
|
||||
t!(s: ".", [b!(".")]);
|
||||
// since this is really a wrapper around str_component_iter, those tests suffice
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_each_parent() {
|
||||
assert!(Path::new("/foo/bar").each_parent(|_| true));
|
||||
assert!(!Path::new("/foo/bar").each_parent(|_| false));
|
||||
|
||||
macro_rules! t(
|
||||
(s: $path:expr, $exp:expr) => (
|
||||
{
|
||||
let path = Path::new($path);
|
||||
let exp: &[&str] = $exp;
|
||||
let mut comps = exp.iter().map(|&x|x);
|
||||
do path.each_parent |p| {
|
||||
let p = p.as_str();
|
||||
assert!(p.is_some());
|
||||
let e = comps.next();
|
||||
assert!(e.is_some());
|
||||
assert_eq!(p.unwrap(), e.unwrap());
|
||||
true
|
||||
};
|
||||
assert!(comps.next().is_none());
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
t!(s: "\\foo\\bar", ["\\foo\\bar", "\\foo", "\\"]);
|
||||
t!(s: "\\foo\\bar\\baz", ["\\foo\\bar\\baz", "\\foo\\bar", "\\foo", "\\"]);
|
||||
t!(s: "\\foo", ["\\foo", "\\"]);
|
||||
t!(s: "\\", ["\\"]);
|
||||
t!(s: "foo\\bar\\baz", ["foo\\bar\\baz", "foo\\bar", "foo", "."]);
|
||||
t!(s: "foo\\bar", ["foo\\bar", "foo", "."]);
|
||||
t!(s: "foo", ["foo", "."]);
|
||||
t!(s: ".", ["."]);
|
||||
t!(s: "..", [".."]);
|
||||
t!(s: "..\\..\\foo", ["..\\..\\foo", "..\\.."]);
|
||||
t!(s: "C:\\a\\b", ["C:\\a\\b", "C:\\a", "C:\\"]);
|
||||
t!(s: "C:\\", ["C:\\"]);
|
||||
t!(s: "C:a\\b", ["C:a\\b", "C:a", "C:"]);
|
||||
t!(s: "C:", ["C:"]);
|
||||
t!(s: "C:..\\..\\a", ["C:..\\..\\a", "C:..\\.."]);
|
||||
t!(s: "C:..", ["C:.."]);
|
||||
t!(s: "\\\\a\\b\\c", ["\\\\a\\b\\c", "\\\\a\\b"]);
|
||||
t!(s: "\\\\a\\b", ["\\\\a\\b"]);
|
||||
t!(s: "\\\\?\\a\\b\\c", ["\\\\?\\a\\b\\c", "\\\\?\\a\\b", "\\\\?\\a"]);
|
||||
t!(s: "\\\\?\\C:\\a\\b", ["\\\\?\\C:\\a\\b", "\\\\?\\C:\\a", "\\\\?\\C:\\"]);
|
||||
t!(s: "\\\\?\\UNC\\a\\b\\c", ["\\\\?\\UNC\\a\\b\\c", "\\\\?\\UNC\\a\\b"]);
|
||||
t!(s: "\\\\.\\a\\b\\c", ["\\\\.\\a\\b\\c", "\\\\.\\a\\b", "\\\\.\\a"]);
|
||||
t!(s: "\\\\?\\a\\..\\b\\.\\c/d", ["\\\\?\\a\\..\\b\\.\\c/d", "\\\\?\\a\\..\\b\\.",
|
||||
"\\\\?\\a\\..\\b", "\\\\?\\a\\..", "\\\\?\\a"]);
|
||||
}
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ fn res_rel_file(cx: @ExtCtxt, sp: codemap::Span, arg: &Path) -> Path {
|
||||
if !arg.is_absolute() {
|
||||
let mut cu = Path::new(cx.codemap().span_to_filename(sp));
|
||||
cu.pop();
|
||||
cu.push_path(arg);
|
||||
cu.push(arg);
|
||||
cu
|
||||
} else {
|
||||
arg.clone()
|
||||
|
@ -3996,7 +3996,7 @@ fn eval_src_mod(&self,
|
||||
prefix.pop();
|
||||
let mod_path_stack = &*self.mod_path_stack;
|
||||
let mod_path = Path::new(".").join_many(*mod_path_stack);
|
||||
let dir_path = prefix.join_path(&mod_path);
|
||||
let dir_path = prefix.join(&mod_path);
|
||||
let file_path = match ::attr::first_attr_value_str_by_name(
|
||||
outer_attrs, "path") {
|
||||
Some(d) => dir_path.join(d),
|
||||
|
@ -27,7 +27,7 @@ fn mk_file(path: &str, directory: bool) {
|
||||
}
|
||||
|
||||
fn abs_path(path: &str) -> Path {
|
||||
os::getcwd().join_path(&Path::new(path))
|
||||
os::getcwd().join(&Path::new(path))
|
||||
}
|
||||
|
||||
fn glob_vec(pattern: &str) -> ~[Path] {
|
||||
|
Loading…
Reference in New Issue
Block a user