1
Fork 0

rustpkg: Make rustpkg commands work without a package ID

`rustpkg build`, if executed in a package source directory inside
a workspace, will now build that package. By "inside a workspace"
I mean that the parent directory has to be called `src`, and rustpkg
will create a `build` directory in .. if there isn't already one.

Same goes for `rustpkg install` and `rustpkg clean`.

For the time being, `rustpkg build` (etc.) will still error out if
you run it inside a directory whose parent isn't called `src`.
I'm not sure whether or not it's desirable to have it do something
in a non-workspace directory.
This commit is contained in:
Tim Chevalier 2013-06-26 17:42:24 -07:00
parent 78f8b407e3
commit e39ea2a5c8
7 changed files with 210 additions and 70 deletions

View file

@ -18,11 +18,18 @@ pub fn list_installed_packages(f: &fn(&PkgId) -> bool) -> bool {
for workspaces.iter().advance |p| { for workspaces.iter().advance |p| {
let binfiles = os::list_dir(&p.push("bin")); let binfiles = os::list_dir(&p.push("bin"));
for binfiles.iter().advance() |exec| { for binfiles.iter().advance() |exec| {
f(&PkgId::new(*exec, p)); let exec_path = Path(*exec).filestem();
do exec_path.iter().advance |s| {
f(&PkgId::new(*s, p))
};
} }
let libfiles = os::list_dir(&p.push("lib")); let libfiles = os::list_dir(&p.push("lib"));
for libfiles.iter().advance() |lib| { for libfiles.iter().advance() |lib| {
f(&PkgId::new(*lib, p)); debug!("Full name: %s", *lib);
let lib_path = Path(*lib).filestem();
do lib_path.iter().advance |s| {
f(&PkgId::new(*s, p))
};
} }
} }
true true

View file

@ -54,11 +54,17 @@ pub fn rust_path() -> ~[Path] {
}; };
let cwd = os::getcwd(); let cwd = os::getcwd();
// now add in default entries // now add in default entries
env_rust_path.push(cwd.push(".rust"));
env_rust_path.push(cwd.clone()); env_rust_path.push(cwd.clone());
do cwd.each_parent() |p| { push_if_exists(&mut env_rust_path, p) }; do cwd.each_parent() |p| { push_if_exists(&mut env_rust_path, p) };
let h = os::homedir(); let h = os::homedir();
for h.iter().advance |h| { push_if_exists(&mut env_rust_path, h); } // Avoid adding duplicates
// could still add dups if someone puts one of these in the RUST_PATH
// manually, though...
for h.iter().advance |hdir| {
if !(cwd.is_ancestor_of(hdir) || hdir.is_ancestor_of(&cwd)) {
push_if_exists(&mut env_rust_path, hdir);
}
}
env_rust_path env_rust_path
} }

View file

@ -42,7 +42,7 @@ use path_util::{U_RWX, rust_path, in_rust_path};
use path_util::{built_executable_in_workspace, built_library_in_workspace, default_workspace}; use path_util::{built_executable_in_workspace, built_library_in_workspace, default_workspace};
use path_util::{target_executable_in_workspace, target_library_in_workspace}; use path_util::{target_executable_in_workspace, target_library_in_workspace};
use source_control::is_git_dir; use source_control::is_git_dir;
use workspace::{each_pkg_parent_workspace, pkg_parent_workspaces}; use workspace::{each_pkg_parent_workspace, pkg_parent_workspaces, in_workspace, cwd_to_workspace};
use context::Ctx; use context::Ctx;
use package_id::PkgId; use package_id::PkgId;
use package_source::PkgSrc; use package_source::PkgSrc;
@ -199,26 +199,41 @@ impl CtxMethods for Ctx {
match cmd { match cmd {
"build" => { "build" => {
if args.len() < 1 { if args.len() < 1 {
return usage::build(); if !in_workspace(|| { usage::build() } ) {
return;
}
let (workspace, pkgid) = cwd_to_workspace();
self.build(&workspace, &pkgid);
} }
// The package id is presumed to be the first command-line else {
// argument // The package id is presumed to be the first command-line
let pkgid = PkgId::new(args[0].clone(), &os::getcwd()); // argument
for each_pkg_parent_workspace(&pkgid) |workspace| { let pkgid = PkgId::new(args[0].clone(), &os::getcwd());
debug!("found pkg %s in workspace %s, trying to build", for each_pkg_parent_workspace(&pkgid) |workspace| {
pkgid.to_str(), workspace.to_str()); debug!("found pkg %s in workspace %s, trying to build",
self.build(workspace, &pkgid); pkgid.to_str(), workspace.to_str());
self.build(workspace, &pkgid);
}
} }
} }
"clean" => { "clean" => {
if args.len() < 1 { if args.len() < 1 {
return usage::build(); if !in_workspace(|| { usage::clean() } ) {
return;
}
// tjc: Maybe clean should clean all the packages in the
// current workspace, though?
let (workspace, pkgid) = cwd_to_workspace();
self.clean(&workspace, &pkgid);
}
else {
// The package id is presumed to be the first command-line
// argument
let pkgid = PkgId::new(args[0].clone(), &os::getcwd());
let cwd = os::getcwd();
self.clean(&cwd, &pkgid); // tjc: should use workspace, not cwd
} }
// The package id is presumed to be the first command-line
// argument
let pkgid = PkgId::new(args[0].clone(), &os::getcwd());
let cwd = os::getcwd();
self.clean(&cwd, &pkgid); // tjc: should use workspace, not cwd
} }
"do" => { "do" => {
if args.len() < 2 { if args.len() < 2 {
@ -232,37 +247,36 @@ impl CtxMethods for Ctx {
} }
"install" => { "install" => {
if args.len() < 1 { if args.len() < 1 {
return usage::install(); if !in_workspace(|| { usage::install() }) {
} return;
}
// The package id is presumed to be the first command-line let (workspace, pkgid) = cwd_to_workspace();
// argument self.install(&workspace, &pkgid);
let pkgid = PkgId::new(args[0], &os::getcwd());
let workspaces = pkg_parent_workspaces(&pkgid);
if workspaces.is_empty() {
debug!("install! workspaces was empty");
let rp = rust_path();
assert!(!rp.is_empty());
let src = PkgSrc::new(&rp[0], &build_pkg_id_in_workspace(&pkgid, &rp[0]),
&pkgid);
src.fetch_git();
self.install(&rp[0], &pkgid);
} }
else { else {
for each_pkg_parent_workspace(&pkgid) |workspace| { // The package id is presumed to be the first command-line
debug!("install: found pkg %s in workspace %s, trying to build", // argument
pkgid.to_str(), workspace.to_str()); let pkgid = PkgId::new(args[0], &os::getcwd());
let workspaces = pkg_parent_workspaces(&pkgid);
self.install(workspace, &pkgid); if workspaces.is_empty() {
let rp = rust_path();
assert!(!rp.is_empty());
let src = PkgSrc::new(&rp[0], &build_pkg_id_in_workspace(&pkgid, &rp[0]),
&pkgid);
src.fetch_git();
self.install(&rp[0], &pkgid);
}
else {
for each_pkg_parent_workspace(&pkgid) |workspace| {
self.install(workspace, &pkgid);
}
} }
} }
} }
"list" => { "list" => {
io::println("Installed packages:"); io::println("Installed packages:");
for installed_packages::list_installed_packages |pkg_id| { for installed_packages::list_installed_packages |pkg_id| {
io::println(fmt!("%s-%s", io::println(pkg_id.local_path.to_str());
pkg_id.local_path.to_str(),
pkg_id.version.to_str()));
} }
} }
"prefer" => { "prefer" => {

View file

@ -218,7 +218,6 @@ fn command_line_test(args: &[~str], cwd: &Path) -> ProcessOutput {
fn command_line_test_with_env(args: &[~str], cwd: &Path, env: Option<~[(~str, ~str)]>) fn command_line_test_with_env(args: &[~str], cwd: &Path, env: Option<~[(~str, ~str)]>)
-> ProcessOutput { -> ProcessOutput {
let cmd = test_sysroot().push("bin").push("rustpkg").to_str(); let cmd = test_sysroot().push("bin").push("rustpkg").to_str();
let cwd = normalize(RemotePath((*cwd).clone()));
debug!("About to run command: %? %? in %s", cmd, args, cwd.to_str()); debug!("About to run command: %? %? in %s", cmd, args, cwd.to_str());
assert!(os::path_is_dir(&*cwd)); assert!(os::path_is_dir(&*cwd));
let cwd = (*cwd).clone(); let cwd = (*cwd).clone();
@ -322,6 +321,14 @@ fn assert_executable_exists(repo: &Path, short_name: &str) {
assert!(is_rwx(&exec)); assert!(is_rwx(&exec));
} }
fn assert_built_executable_exists(repo: &Path, short_name: &str) {
debug!("assert_built_executable_exists: repo = %s, short_name = %s", repo.to_str(), short_name);
let exec = built_executable_in_workspace(&PkgId::new(short_name, repo),
repo).expect("assert_built_executable_exists failed");
assert!(os::path_exists(&exec));
assert!(is_rwx(&exec));
}
fn command_line_test_output(args: &[~str]) -> ~[~str] { fn command_line_test_output(args: &[~str]) -> ~[~str] {
let mut result = ~[]; let mut result = ~[];
let p_output = command_line_test(args, &os::getcwd()); let p_output = command_line_test(args, &os::getcwd());
@ -490,30 +497,29 @@ fn test_install_git() {
// should have test, bench, lib, and main // should have test, bench, lib, and main
command_line_test([~"install", temp_pkg_id.local_path.to_str()], &repo); command_line_test([~"install", temp_pkg_id.local_path.to_str()], &repo);
// Check that all files exist // Check that all files exist
let ws = repo.push(".rust"); debug!("Checking for files in %s", repo.to_str());
debug!("Checking for files in %s", ws.to_str()); let exec = target_executable_in_workspace(&temp_pkg_id, &repo);
let exec = target_executable_in_workspace(&temp_pkg_id, &ws);
debug!("exec = %s", exec.to_str()); debug!("exec = %s", exec.to_str());
assert!(os::path_exists(&exec)); assert!(os::path_exists(&exec));
assert!(is_rwx(&exec)); assert!(is_rwx(&exec));
let _built_lib = let _built_lib =
built_library_in_workspace(&temp_pkg_id, built_library_in_workspace(&temp_pkg_id,
&ws).expect("test_install_git: built lib should exist"); &repo).expect("test_install_git: built lib should exist");
let lib = target_library_in_workspace(&temp_pkg_id, &ws); let lib = target_library_in_workspace(&temp_pkg_id, &repo);
debug!("lib = %s", lib.to_str()); debug!("lib = %s", lib.to_str());
assert!(os::path_exists(&lib)); assert!(os::path_exists(&lib));
assert!(is_rwx(&lib)); assert!(is_rwx(&lib));
let built_test = built_test_in_workspace(&temp_pkg_id, let built_test = built_test_in_workspace(&temp_pkg_id,
&ws).expect("test_install_git: built test should exist"); &repo).expect("test_install_git: built test should exist");
assert!(os::path_exists(&built_test)); assert!(os::path_exists(&built_test));
let built_bench = built_bench_in_workspace(&temp_pkg_id, let built_bench = built_bench_in_workspace(&temp_pkg_id,
&ws).expect("test_install_git: built bench should exist"); &repo).expect("test_install_git: built bench should exist");
assert!(os::path_exists(&built_bench)); assert!(os::path_exists(&built_bench));
// And that the test and bench executables aren't installed // And that the test and bench executables aren't installed
let test = target_test_in_workspace(&temp_pkg_id, &ws); let test = target_test_in_workspace(&temp_pkg_id, &repo);
assert!(!os::path_exists(&test)); assert!(!os::path_exists(&test));
debug!("test = %s", test.to_str()); debug!("test = %s", test.to_str());
let bench = target_bench_in_workspace(&temp_pkg_id, &ws); let bench = target_bench_in_workspace(&temp_pkg_id, &repo);
debug!("bench = %s", bench.to_str()); debug!("bench = %s", bench.to_str());
assert!(!os::path_exists(&bench)); assert!(!os::path_exists(&bench));
} }
@ -586,12 +592,12 @@ fn test_package_version() {
command_line_test([~"install", ~"mockgithub.com/catamorphism/test_pkg_version"], command_line_test([~"install", ~"mockgithub.com/catamorphism/test_pkg_version"],
&repo); &repo);
assert!(match built_library_in_workspace(&temp_pkg_id, assert!(match built_library_in_workspace(&temp_pkg_id,
&repo.push(".rust")) { &repo) {
Some(p) => p.to_str().ends_with(fmt!("0.4%s", os::consts::DLL_SUFFIX)), Some(p) => p.to_str().ends_with(fmt!("0.4%s", os::consts::DLL_SUFFIX)),
None => false None => false
}); });
assert!(built_executable_in_workspace(&temp_pkg_id, &repo.push(".rust")) assert!(built_executable_in_workspace(&temp_pkg_id, &repo)
== Some(repo.push(".rust").push("build"). == Some(repo.push("build").
push("mockgithub.com"). push("mockgithub.com").
push("catamorphism"). push("catamorphism").
push("test_pkg_version"). push("test_pkg_version").
@ -689,7 +695,7 @@ fn rustpkg_library_target() {
add_git_tag(&package_dir, ~"1.0"); add_git_tag(&package_dir, ~"1.0");
command_line_test([~"install", ~"foo"], &foo_repo); command_line_test([~"install", ~"foo"], &foo_repo);
assert_lib_exists(&foo_repo.push(".rust"), "foo", ExactRevision(~"1.0")); assert_lib_exists(&foo_repo, "foo", ExactRevision(~"1.0"));
} }
#[test] #[test]
@ -716,14 +722,55 @@ fn package_script_with_default_build() {
assert!(os::path_exists(&dir.push("build").push("fancy_lib").push("generated.rs"))); assert!(os::path_exists(&dir.push("build").push("fancy_lib").push("generated.rs")));
} }
#[test]
fn rustpkg_build_no_arg() {
let tmp = mkdtemp(&os::tmpdir(), "rustpkg_build_no_arg").expect("rustpkg_build_no_arg failed");
let package_dir = tmp.push("src").push("foo");
assert!(os::mkdir_recursive(&package_dir, U_RWX));
writeFile(&package_dir.push("main.rs"),
"fn main() { let _x = (); }");
debug!("build_no_arg: dir = %s", package_dir.to_str());
command_line_test([~"build"], &package_dir);
assert_built_executable_exists(&tmp, "foo");
}
#[test]
fn rustpkg_install_no_arg() {
let tmp = mkdtemp(&os::tmpdir(),
"rustpkg_install_no_arg").expect("rustpkg_build_no_arg failed");
let package_dir = tmp.push("src").push("foo");
assert!(os::mkdir_recursive(&package_dir, U_RWX));
writeFile(&package_dir.push("lib.rs"),
"fn main() { let _x = (); }");
debug!("install_no_arg: dir = %s", package_dir.to_str());
command_line_test([~"install"], &package_dir);
assert_lib_exists(&tmp, "foo", NoVersion);
}
#[test]
fn rustpkg_clean_no_arg() {
let tmp = mkdtemp(&os::tmpdir(), "rustpkg_clean_no_arg").expect("rustpkg_clean_no_arg failed");
let package_dir = tmp.push("src").push("foo");
assert!(os::mkdir_recursive(&package_dir, U_RWX));
writeFile(&package_dir.push("main.rs"),
"fn main() { let _x = (); }");
debug!("clean_no_arg: dir = %s", package_dir.to_str());
command_line_test([~"build"], &package_dir);
assert_built_executable_exists(&tmp, "foo");
command_line_test([~"clean"], &package_dir);
assert!(!built_executable_in_workspace(&PkgId::new("foo", &package_dir),
&tmp).map_default(false, |m| { os::path_exists(m) }));
}
#[test] #[test]
#[ignore (reason = "Un-ignore when #7071 is fixed")] #[ignore (reason = "Un-ignore when #7071 is fixed")]
fn rust_path_test() { fn rust_path_test() {
let dir_for_path = mkdtemp(&os::tmpdir(), "more_rust").expect("rust_path_test failed"); let dir_for_path = mkdtemp(&os::tmpdir(), "more_rust").expect("rust_path_test failed");
let dir = mk_workspace(&dir_for_path, &normalize(RemotePath(Path("foo"))), &NoVersion); let dir = mk_workspace(&dir_for_path, &normalize(RemotePath(Path("foo"))), &NoVersion);
debug!("dir = %s", dir.to_str()); debug!("dir = %s", dir.to_str());
writeFile(&Path("/Users/tjc/more_rust/src/foo-0.1/main.rs"), writeFile(&dir.push("main.rs"), "fn main() { let _x = (); }");
"fn main() { let _x = (); }");
let cwd = os::getcwd(); let cwd = os::getcwd();
debug!("cwd = %s", cwd.to_str()); debug!("cwd = %s", cwd.to_str());
@ -781,21 +828,24 @@ fn test_list() {
let quux = PkgId::new("quux", &dir); let quux = PkgId::new("quux", &dir);
create_local_package_in(&quux, &dir); create_local_package_in(&quux, &dir);
// NOTE Not really great output, though...
// NOTE do any tests need to be unignored?
command_line_test([~"install", ~"foo"], &dir); command_line_test([~"install", ~"foo"], &dir);
let env_arg = ~[(~"RUST_PATH", dir.to_str())]; let env_arg = ~[(~"RUST_PATH", dir.to_str())];
debug!("RUST_PATH = %s", dir.to_str());
let list_output = command_line_test_output_with_env([~"list"], env_arg.clone()); let list_output = command_line_test_output_with_env([~"list"], env_arg.clone());
assert!(list_output.iter().any(|x| x.starts_with("foo-"))); assert!(list_output.iter().any(|x| x.starts_with("libfoo_")));
command_line_test([~"install", ~"bar"], &dir); command_line_test([~"install", ~"bar"], &dir);
let list_output = command_line_test_output_with_env([~"list"], env_arg.clone()); let list_output = command_line_test_output_with_env([~"list"], env_arg.clone());
assert!(list_output.iter().any(|x| x.starts_with("foo-"))); assert!(list_output.iter().any(|x| x.starts_with("libfoo_")));
assert!(list_output.iter().any(|x| x.starts_with("bar-"))); assert!(list_output.iter().any(|x| x.starts_with("libbar_")));
command_line_test([~"install", ~"quux"], &dir); command_line_test([~"install", ~"quux"], &dir);
let list_output = command_line_test_output_with_env([~"list"], env_arg); let list_output = command_line_test_output_with_env([~"list"], env_arg);
assert!(list_output.iter().any(|x| x.starts_with("foo-"))); assert!(list_output.iter().any(|x| x.starts_with("libfoo_")));
assert!(list_output.iter().any(|x| x.starts_with("bar-"))); assert!(list_output.iter().any(|x| x.starts_with("libbar_")));
assert!(list_output.iter().any(|x| x.starts_with("quux-"))); assert!(list_output.iter().any(|x| x.starts_with("libquux_")));
} }
#[test] #[test]
@ -836,7 +886,7 @@ fn install_check_duplicates() {
let mut contents = ~[]; let mut contents = ~[];
let check_dups = |p: &PkgId| { let check_dups = |p: &PkgId| {
if contents.contains(p) { if contents.contains(p) {
fail!("package database contains duplicate ID"); fail!("package %s appears in `list` output more than once", p.local_path.to_str());
} }
else { else {
contents.push((*p).clone()); contents.push((*p).clone());

View file

@ -23,10 +23,11 @@ Options:
} }
pub fn build() { pub fn build() {
io::println("rustpkg [options..] build io::println("rustpkg [options..] build [package-ID]
Build all targets described in the package script in the current Build the given package ID if specified. With no package ID argument,
directory. build the package in the current directory. In that case, the current
directory must be a direct child of an `src` directory in a workspace.
Options: Options:
-c, --cfg Pass a cfg flag to the package script"); -c, --cfg Pass a cfg flag to the package script");

View file

@ -10,9 +10,10 @@
// rustpkg utilities having to do with workspaces // rustpkg utilities having to do with workspaces
use std::os;
use std::path::Path;
use path_util::{rust_path, workspace_contains_package_id}; use path_util::{rust_path, workspace_contains_package_id};
use package_id::PkgId; use package_id::PkgId;
use std::path::Path;
pub fn each_pkg_parent_workspace(pkgid: &PkgId, action: &fn(&Path) -> bool) -> bool { pub fn each_pkg_parent_workspace(pkgid: &PkgId, action: &fn(&Path) -> bool) -> bool {
// Using the RUST_PATH, find workspaces that contain // Using the RUST_PATH, find workspaces that contain
@ -38,3 +39,24 @@ pub fn pkg_parent_workspaces(pkgid: &PkgId) -> ~[Path] {
.filter(|ws| workspace_contains_package_id(pkgid, ws)) .filter(|ws| workspace_contains_package_id(pkgid, ws))
.collect() .collect()
} }
pub fn in_workspace(complain: &fn()) -> bool {
let dir_part = os::getcwd().pop().components.clone();
if *(dir_part.last()) != ~"src" {
complain();
false
}
else {
true
}
}
/// Construct a workspace and package-ID name based on the current directory.
/// This gets used when rustpkg gets invoked without a package-ID argument.
pub fn cwd_to_workspace() -> (Path, PkgId) {
let cwd = os::getcwd();
let ws = cwd.pop().pop();
let cwd_ = cwd.clone();
let pkgid = cwd_.components.last().to_str();
(ws, PkgId::new(pkgid, &cwd))
}

View file

@ -122,6 +122,9 @@ pub trait GenericPath {
/// Returns `true` if `self` is an absolute path. /// Returns `true` if `self` is an absolute path.
fn is_absolute(&self) -> bool; fn is_absolute(&self) -> bool;
/// True if `self` is an ancestor of `other`. See `test_is_ancestor_of` for examples
fn is_ancestor_of(&self, (&Self)) -> bool;
} }
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
@ -698,6 +701,15 @@ impl GenericPath for PosixPath {
fn is_absolute(&self) -> bool { fn is_absolute(&self) -> bool {
self.is_absolute self.is_absolute
} }
fn is_ancestor_of(&self, other: &PosixPath) -> bool {
debug!("%s / %s %? %?", self.to_str(), other.to_str(), self.is_absolute,
self.components.len());
self == other ||
(!other.components.is_empty() && !(self.components.is_empty() && !self.is_absolute) &&
self.is_ancestor_of(&other.pop()))
}
} }
@ -974,8 +986,13 @@ impl GenericPath for WindowsPath {
fn is_absolute(&self) -> bool { fn is_absolute(&self) -> bool {
self.is_absolute self.is_absolute
} }
}
fn is_ancestor_of(&self, other: &WindowsPath) -> bool {
self == other ||
(!other.components.is_empty() && !(self.components.is_empty() && !self.is_absolute) &&
self.is_ancestor_of(&other.pop()))
}
}
pub fn normalize(components: &[~str]) -> ~[~str] { pub fn normalize(components: &[~str]) -> ~[~str] {
let mut cs = ~[]; let mut cs = ~[];
@ -1290,4 +1307,27 @@ mod tests {
assert_eq!(WindowsPath("C:\\COM1.TXT").is_restricted(), true); assert_eq!(WindowsPath("C:\\COM1.TXT").is_restricted(), true);
assert_eq!(WindowsPath("c:\\prn.exe").is_restricted(), true); assert_eq!(WindowsPath("c:\\prn.exe").is_restricted(), true);
} }
#[test]
fn test_is_ancestor_of() {
assert!(&PosixPath("/a/b").is_ancestor_of(&PosixPath("/a/b/c/d")));
assert!(!&PosixPath("/a/b/c/d").is_ancestor_of(&PosixPath("/a/b")));
assert!(!&PosixPath("/a/b").is_ancestor_of(&PosixPath("/c/d")));
assert!(&PosixPath("/a/b").is_ancestor_of(&PosixPath("/a/b/c/d")));
assert!(&PosixPath("/").is_ancestor_of(&PosixPath("/a/b/c")));
assert!(!&PosixPath("/").is_ancestor_of(&PosixPath("")));
assert!(!&PosixPath("/a/b/c").is_ancestor_of(&PosixPath("")));
assert!(!&PosixPath("").is_ancestor_of(&PosixPath("/a/b/c")));
assert!(&WindowsPath("C:\\a\\b").is_ancestor_of(&WindowsPath("C:\\a\\b\\c\\d")));
assert!(!&WindowsPath("C:\\a\\b\\c\\d").is_ancestor_of(&WindowsPath("C:\\a\\b")));
assert!(!&WindowsPath("C:\\a\\b").is_ancestor_of(&WindowsPath("C:\\c\\d")));
assert!(&WindowsPath("C:\\a\\b").is_ancestor_of(&WindowsPath("C:\\a\\b\\c\\d")));
assert!(&WindowsPath("C:\\").is_ancestor_of(&WindowsPath("C:\\a\\b\\c")));
assert!(!&WindowsPath("C:\\").is_ancestor_of(&WindowsPath("")));
assert!(!&WindowsPath("C:\\a\\b\\c").is_ancestor_of(&WindowsPath("")));
assert!(!&WindowsPath("").is_ancestor_of(&WindowsPath("C:\\a\\b\\c")));
}
} }