Skip to content

Commit 667adad

Browse files
committed
rustpkg: Search for packages correctly when using the rust_path_hack
Previously, any package would match any other package ID when searching using the rust_path_hack, so long as the directory had one or more crate files in it. Now, rustpkg checks that the parent directory matches the package ID. Closes #9273
1 parent 2265416 commit 667adad

File tree

5 files changed

+109
-52
lines changed

5 files changed

+109
-52
lines changed

src/librustpkg/package_source.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ impl PkgSrc {
5959
use conditions::nonexistent_package::cond;
6060

6161
debug!("Checking package source for package ID %s, \
62-
workspace = %s", id.to_str(), workspace.to_str());
62+
workspace = %s use_rust_path_hack = %?",
63+
id.to_str(), workspace.to_str(), use_rust_path_hack);
6364

6465
let mut to_try = ~[];
6566
if use_rust_path_hack {

src/librustpkg/path_util.rs

+18-5
Original file line numberDiff line numberDiff line change
@@ -421,11 +421,16 @@ fn dir_has_file(dir: &Path, file: &str) -> bool {
421421
pub fn find_dir_using_rust_path_hack(p: &PkgId) -> Option<Path> {
422422
let rp = rust_path();
423423
for dir in rp.iter() {
424-
debug!("In find_dir_using_rust_path_hack: checking dir %s", dir.to_str());
425-
if dir_has_file(dir, "lib.rs") || dir_has_file(dir, "main.rs")
426-
|| dir_has_file(dir, "test.rs") || dir_has_file(dir, "bench.rs") {
427-
debug!("Did find id %s in dir %s", p.to_str(), dir.to_str());
428-
return Some(dir.clone());
424+
// Require that the parent directory match the package ID
425+
// Note that this only matches if the package ID being searched for
426+
// has a name that's a single component
427+
if dir.is_parent_of(&p.path) || dir.is_parent_of(&versionize(&p.path, &p.version)) {
428+
debug!("In find_dir_using_rust_path_hack: checking dir %s", dir.to_str());
429+
if dir_has_file(dir, "lib.rs") || dir_has_file(dir, "main.rs")
430+
|| dir_has_file(dir, "test.rs") || dir_has_file(dir, "bench.rs") {
431+
debug!("Did find id %s in dir %s", p.to_str(), dir.to_str());
432+
return Some(dir.clone());
433+
}
429434
}
430435
debug!("Didn't find id %s in dir %s", p.to_str(), dir.to_str())
431436
}
@@ -440,3 +445,11 @@ pub fn user_set_rust_path() -> bool {
440445
Some(_) => true
441446
}
442447
}
448+
449+
/// Append the version string onto the end of the path's filename
450+
fn versionize(p: &Path, v: &Version) -> Path {
451+
let q = p.file_path().to_str();
452+
p.with_filename(fmt!("%s-%s", q, v.to_str()))
453+
}
454+
455+

src/librustpkg/tests.rs

+38-1
Original file line numberDiff line numberDiff line change
@@ -1267,7 +1267,9 @@ fn test_rust_path_can_contain_package_dirs_without_flag() {
12671267
#[test]
12681268
fn rust_path_hack_cwd() {
12691269
// Same as rust_path_hack_test, but the CWD is the dir to build out of
1270-
let cwd = mkdtemp(&os::tmpdir(), "pkg_files").expect("rust_path_hack_cwd");
1270+
let cwd = mkdtemp(&os::tmpdir(), "foo").expect("rust_path_hack_cwd");
1271+
let cwd = cwd.push("foo");
1272+
assert!(os::mkdir_recursive(&cwd, U_RWX));
12711273
writeFile(&cwd.push("lib.rs"), "pub fn f() { }");
12721274

12731275
let dest_workspace = mk_empty_workspace(&Path("bar"), &NoVersion, "dest_workspace");
@@ -1763,6 +1765,41 @@ fn reinstall() {
17631765
assert_built_executable_exists(&workspace, b.short_name);
17641766
}
17651767
1768+
#[test]
1769+
fn correct_package_name_with_rust_path_hack() {
1770+
/*
1771+
Set rust_path_hack flag
1772+
1773+
Try to install bar
1774+
Check that:
1775+
- no output gets produced in any workspace
1776+
- there's an error
1777+
*/
1778+
1779+
// Set RUST_PATH to something containing only the sources for foo
1780+
let foo_id = PkgId::new("foo");
1781+
let bar_id = PkgId::new("bar");
1782+
let foo_workspace = create_local_package(&foo_id);
1783+
let dest_workspace = mk_empty_workspace(&Path("bar"), &NoVersion, "dest_workspace");
1784+
1785+
writeFile(&dest_workspace.push_many(["src", "bar-0.1", "main.rs"]),
1786+
"extern mod blat; fn main() { let _x = (); }");
1787+
1788+
let rust_path = Some(~[(~"RUST_PATH", fmt!("%s:%s", dest_workspace.to_str(),
1789+
foo_workspace.push_many(["src", "foo-0.1"]).to_str()))]);
1790+
// bar doesn't exist, but we want to make sure rustpkg doesn't think foo is bar
1791+
command_line_test_with_env([~"install", ~"--rust-path-hack", ~"bar"],
1792+
&dest_workspace, rust_path);
1793+
assert!(!executable_exists(&dest_workspace, "bar"));
1794+
assert!(!lib_exists(&dest_workspace, &bar_id.path.clone(), bar_id.version.clone()));
1795+
assert!(!executable_exists(&dest_workspace, "foo"));
1796+
assert!(!lib_exists(&dest_workspace, &foo_id.path.clone(), foo_id.version.clone()));
1797+
assert!(!executable_exists(&foo_workspace, "bar"));
1798+
assert!(!lib_exists(&foo_workspace, &bar_id.path.clone(), bar_id.version.clone()));
1799+
assert!(!executable_exists(&foo_workspace, "foo"));
1800+
assert!(!lib_exists(&foo_workspace, &foo_id.path.clone(), foo_id.version.clone()));
1801+
}
1802+
17661803
/// Returns true if p exists and is executable
17671804
fn is_executable(p: &Path) -> bool {
17681805
use std::libc::consts::os::posix88::{S_IXUSR};

src/librustpkg/util.rs

+20-23
Original file line numberDiff line numberDiff line change
@@ -439,26 +439,30 @@ impl<'self> Visitor<()> for ViewItemVisitor<'self> {
439439
let pkg_id = PkgId::new(lib_name);
440440
let workspaces = pkg_parent_workspaces(&self.context.context,
441441
&pkg_id);
442-
let dep_workspace = if workspaces.is_empty() {
443-
error(fmt!("Couldn't find package %s, which is needed by %s, \
444-
in any of the workspaces in the RUST_PATH (%?)",
445-
lib_name,
446-
self.parent.to_str(),
447-
rust_path()));
442+
let source_workspace = if workspaces.is_empty() {
443+
error(fmt!("Couldn't find package %s \
444+
in any of the workspaces in the RUST_PATH (%s)",
445+
lib_name,
446+
rust_path().map(|s| s.to_str()).connect(":")));
448447
cond.raise((pkg_id.clone(), ~"Dependency not found"))
449448
}
450-
else {
449+
else {
451450
workspaces[0]
452451
};
453452
let (outputs_disc, inputs_disc) =
454-
self.context.install(PkgSrc::new(dep_workspace.clone(),
455-
false,
453+
self.context.install(PkgSrc::new(source_workspace.clone(),
454+
// Use the rust_path_hack to search for dependencies iff
455+
// we were already using it
456+
self.context.context.use_rust_path_hack,
456457
pkg_id),
457458
&JustOne(Path(
458-
lib_crate_filename)));
459+
lib_crate_filename)));
459460
debug!("Installed %s, returned %? dependencies and \
460461
%? transitive dependencies",
461462
lib_name, outputs_disc.len(), inputs_disc.len());
463+
// It must have installed *something*...
464+
assert!(!outputs_disc.is_empty());
465+
let target_workspace = outputs_disc[0].pop();
462466
for dep in outputs_disc.iter() {
463467
debug!("Discovering a binary input: %s", dep.to_str());
464468
self.exec.discover_input("binary",
@@ -471,31 +475,24 @@ impl<'self> Visitor<()> for ViewItemVisitor<'self> {
471475
*dep,
472476
digest_file_with_date(&Path(*dep)));
473477
}
474-
else if *what == ~"binary" {
478+
else if *what == ~"binary" {
475479
self.exec.discover_input(*what,
476480
*dep,
477481
digest_only_date(&Path(*dep)));
478482
}
479-
else {
483+
else {
480484
fail!("Bad kind: %s", *what);
481485
}
482486
}
483487
// Also, add an additional search path
484-
debug!("Adding additional search path: %s", lib_name);
485-
let installed_library =
486-
installed_library_in_workspace(&Path(lib_name), &dep_workspace)
487-
.expect(fmt!("rustpkg failed to install dependency %s",
488-
lib_name));
489-
let install_dir = installed_library.pop();
490-
debug!("Installed %s into %s [%?]", lib_name, install_dir.to_str(),
491-
datestamp(&installed_library));
492-
(self.save)(install_dir);
488+
debug!("Installed %s into %s", lib_name, target_workspace.to_str());
489+
(self.save)(target_workspace);
493490
}
494-
}}
491+
}
492+
}
495493
// Ignore `use`s
496494
_ => ()
497495
}
498-
499496
visit::walk_view_item(self, vi, env)
500497
}
501498
}

src/libstd/path.rs

+31-22
Original file line numberDiff line numberDiff line change
@@ -236,16 +236,16 @@ pub trait GenericPath : Clone + Eq + ToStr {
236236

237237
/// Returns `true` iff `child` is a suffix of `parent`. See the test
238238
/// case for examples.
239-
pub fn is_parent_of(parent: &Path, child: &Path) -> bool {
240-
if !parent.is_absolute() || child.is_absolute()
241-
|| parent.components.len() < child.components.len()
242-
|| parent.components.is_empty() {
239+
fn is_parent_of(&self, child: &Self) -> bool {
240+
if !self.is_absolute() || child.is_absolute()
241+
|| self.components().len() < child.components().len()
242+
|| self.components().is_empty() {
243243
return false;
244244
}
245245
let child_components = child.components().len();
246-
let parent_components = parent.components().len();
247-
let to_drop = parent.components.len() - child_components;
248-
parent.components.slice(to_drop, parent_components) == child.components
246+
let parent_components = self.components().len();
247+
let to_drop = self.components().len() - child_components;
248+
self.components().slice(to_drop, parent_components) == child.components()
249249
}
250250

251251
fn components<'a>(&'a self) -> &'a [~str];
@@ -1468,14 +1468,22 @@ mod tests {
14681468

14691469
#[test]
14701470
fn test_is_parent_of() {
1471-
assert!(is_parent_of(&PosixPath("/a/b/c/d/e"), &PosixPath("c/d/e")));
1472-
assert!(!is_parent_of(&PosixPath("a/b/c/d/e"), &PosixPath("c/d/e")));
1473-
assert!(!is_parent_of(&PosixPath("/a/b/c/d/e"), &PosixPath("/c/d/e")));
1474-
assert!(!is_parent_of(&PosixPath(""), &PosixPath("")));
1475-
assert!(!is_parent_of(&PosixPath(""), &PosixPath("a/b/c")));
1476-
assert!(is_parent_of(&PosixPath("/a/b/c"), &PosixPath("")));
1477-
assert!(is_parent_of(&PosixPath("/a/b/c"), &PosixPath("a/b/c")));
1478-
assert!(!is_parent_of(&PosixPath("/a/b/c"), &PosixPath("d/e/f")));
1471+
fn is_parent_of_pp(p: &PosixPath, q: &PosixPath) -> bool {
1472+
p.is_parent_of(q)
1473+
}
1474+
1475+
assert!(is_parent_of_pp(&PosixPath("/a/b/c/d/e"), &PosixPath("c/d/e")));
1476+
assert!(!is_parent_of_pp(&PosixPath("a/b/c/d/e"), &PosixPath("c/d/e")));
1477+
assert!(!is_parent_of_pp(&PosixPath("/a/b/c/d/e"), &PosixPath("/c/d/e")));
1478+
assert!(!is_parent_of_pp(&PosixPath(""), &PosixPath("")));
1479+
assert!(!is_parent_of_pp(&PosixPath(""), &PosixPath("a/b/c")));
1480+
assert!(is_parent_of_pp(&PosixPath("/a/b/c"), &PosixPath("")));
1481+
assert!(is_parent_of_pp(&PosixPath("/a/b/c"), &PosixPath("a/b/c")));
1482+
assert!(!is_parent_of_pp(&PosixPath("/a/b/c"), &PosixPath("d/e/f")));
1483+
1484+
fn is_parent_of_wp(p: &WindowsPath, q: &WindowsPath) -> bool {
1485+
p.is_parent_of(q)
1486+
}
14791487

14801488
let abcde = WindowsPath("C:\\a\\b\\c\\d\\e");
14811489
let rel_abcde = WindowsPath("a\\b\\c\\d\\e");
@@ -1486,13 +1494,14 @@ mod tests {
14861494
let rel_abc = WindowsPath("a\\b\\c");
14871495
let def = WindowsPath("d\\e\\f");
14881496

1489-
assert!(is_parent_of(&abcde, &cde));
1490-
assert!(!is_parent_of(&rel_abcde, &cde));
1491-
assert!(!is_parent_of(&abcde, &slashcde));
1492-
assert!(!is_parent_of(&empty, &empty));
1493-
assert!(is_parent_of(&abc, &empty);
1494-
assert!(is_parent_of(&abc, &rel_abc));
1495-
assert!(!is_parent_of(&abc, &def));
1497+
assert!(is_parent_of_wp(&abcde, &cde));
1498+
assert!(!is_parent_of_wp(&rel_abcde, &cde));
1499+
assert!(!is_parent_of_wp(&abcde, &slashcde));
1500+
assert!(!is_parent_of_wp(&empty, &empty));
1501+
assert!(!is_parent_of_wp(&empty, &rel_abc));
1502+
assert!(is_parent_of_wp(&abc, &empty));
1503+
assert!(is_parent_of_wp(&abc, &rel_abc));
1504+
assert!(!is_parent_of_wp(&abc, &def));
14961505
}
14971506

14981507
}

0 commit comments

Comments
 (0)