Skip to content

Commit 3226a80

Browse files
committed
rustpkg: Support sub-package-IDs
Package IDs can now refer to a subdirectory of a particular source tree, and not just a top-level directory with a src/ directory as its parent. For example, referring to the package ID a/b/c/d , in workspace W, if W/src/a is a package, will build the sources for the package in a/b/c/d (and not other crates in W/src/a). Closes #6408
1 parent a6be8d3 commit 3226a80

File tree

7 files changed

+137
-35
lines changed

7 files changed

+137
-35
lines changed

src/librustpkg/package_id.rs

+30-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,35 @@ impl PkgId {
9999
/// True if the ID has multiple components
100100
pub fn is_complex(&self) -> bool {
101101
self.short_name != self.path.to_str()
102-
}
102+
}
103+
104+
pub fn prefixes_iter(&self) -> Prefixes {
105+
Prefixes {
106+
components: self.path.components().to_owned(),
107+
remaining: ~[]
108+
}
109+
}
110+
111+
}
112+
113+
struct Prefixes {
114+
priv components: ~[~str],
115+
priv remaining: ~[~str]
116+
}
117+
118+
impl Iterator<(Path, Path)> for Prefixes {
119+
#[inline]
120+
fn next(&mut self) -> Option<(Path, Path)> {
121+
if self.components.len() <= 1 {
122+
None
123+
}
124+
else {
125+
let last = self.components.pop();
126+
self.remaining.push(last);
127+
// converting to str and then back is a little unfortunate
128+
Some((Path(self.components.to_str()), Path(self.remaining.to_str())))
129+
}
130+
}
103131
}
104132

105133
impl ToStr for PkgId {
@@ -119,3 +147,4 @@ pub fn hash(data: ~str) -> ~str {
119147
write(hasher, data);
120148
hasher.result_str()
121149
}
150+

src/librustpkg/package_source.rs

+37-6
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,33 @@ impl PkgSrc {
7777
let dir: Path = match path {
7878
Some(d) => (*d).clone(),
7979
None => {
80+
// See if any of the prefixes of this package ID form a valid package ID
81+
// That is, is this a package ID that points into the middle of a workspace?
82+
for (prefix, suffix) in id.prefixes_iter() {
83+
let package_id = PkgId::new(prefix.to_str());
84+
let path = workspace.push("src").push_rel(&package_id.path);
85+
debug!("in loop: checking if %s is a directory", path.to_str());
86+
if os::path_is_dir(&path) {
87+
let ps = PkgSrc::new(workspace.clone(),
88+
use_rust_path_hack,
89+
PkgId::new(prefix.to_str()));
90+
debug!("pkgsrc: Returning [%s|%s|%s]", workspace.to_str(),
91+
ps.start_dir.push_rel(&suffix).to_str(), ps.id.to_str());
92+
93+
return PkgSrc {
94+
workspace: workspace,
95+
start_dir: ps.start_dir.push_rel(&suffix),
96+
id: ps.id,
97+
libs: ~[],
98+
mains: ~[],
99+
tests: ~[],
100+
benchs: ~[]
101+
}
102+
103+
};
104+
}
105+
106+
// Ok, no prefixes work, so try fetching from git
80107
let mut ok_d = None;
81108
for w in to_try.iter() {
82109
debug!("Calling fetch_git on %s", w.to_str());
@@ -93,16 +120,17 @@ impl PkgSrc {
93120
if use_rust_path_hack {
94121
match find_dir_using_rust_path_hack(&id) {
95122
Some(d) => d,
96-
None => cond.raise((id.clone(),
97-
~"supplied path for package dir does not \
98-
exist, and couldn't interpret it as a URL fragment"))
123+
None => {
124+
cond.raise((id.clone(),
125+
~"supplied path for package dir does not \
126+
exist, and couldn't interpret it as a URL fragment"))
127+
}
99128
}
100129
}
101130
else {
102131
cond.raise((id.clone(),
103-
~"supplied path for package dir does not \
104-
exist, and couldn't interpret it as a URL fragment"))
105-
132+
~"supplied path for package dir does not \
133+
exist, and couldn't interpret it as a URL fragment"))
106134
}
107135
}
108136
}
@@ -115,6 +143,9 @@ impl PkgSrc {
115143
non-directory"));
116144
}
117145

146+
debug!("pkgsrc: Returning {%s|%s|%s}", workspace.to_str(),
147+
dir.to_str(), id.to_str());
148+
118149
PkgSrc {
119150
workspace: workspace,
120151
start_dir: dir,

src/librustpkg/path_util.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,6 @@ pub fn make_dir_rwx(p: &Path) -> bool { os::make_dir(p, U_RWX) }
4949
/// True if there's a directory in <workspace> with
5050
/// pkgid's short name
5151
pub fn workspace_contains_package_id(pkgid: &PkgId, workspace: &Path) -> bool {
52-
debug!("Checking in src dir of %s for %s",
53-
workspace.to_str(), pkgid.to_str());
5452
workspace_contains_package_id_(pkgid, workspace, |p| { p.push("src") }).is_some()
5553
}
5654

@@ -141,9 +139,17 @@ pub fn built_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option<Pat
141139
}
142140

143141
/// Does the actual searching stuff
144-
pub fn installed_library_in_workspace(short_name: &str, workspace: &Path) -> Option<Path> {
142+
pub fn installed_library_in_workspace(pkg_path: &Path, workspace: &Path) -> Option<Path> {
145143
// This could break once we're handling multiple versions better -- I should add a test for it
146-
library_in_workspace(&Path(short_name), short_name, Install, workspace, "lib", &NoVersion)
144+
match pkg_path.filename() {
145+
None => None,
146+
Some(short_name) => library_in_workspace(pkg_path,
147+
short_name,
148+
Install,
149+
workspace,
150+
"lib",
151+
&NoVersion)
152+
}
147153
}
148154

149155
/// `workspace` is used to figure out the directory to search.

src/librustpkg/search.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ use version::Version;
1515
/// return Some(p) (returns the first one of there are multiple matches.) Return
1616
/// None if there's no such path.
1717
/// FIXME #8711: This ignores the desired version.
18-
pub fn find_installed_library_in_rust_path(short_name: &str, _version: &Version) -> Option<Path> {
18+
pub fn find_installed_library_in_rust_path(pkg_path: &Path, _version: &Version) -> Option<Path> {
1919
let rp = rust_path();
20+
debug!("find_installed_library_in_rust_path: looking for path %s", pkg_path.to_str());
2021
for p in rp.iter() {
21-
match installed_library_in_workspace(short_name, p) {
22+
match installed_library_in_workspace(pkg_path, p) {
2223
Some(path) => return Some(path),
2324
None => ()
2425
}

src/librustpkg/tests.rs

+51-20
Original file line numberDiff line numberDiff line change
@@ -328,13 +328,13 @@ fn create_local_package_with_custom_build_hook(pkgid: &PkgId,
328328

329329
}
330330

331-
fn assert_lib_exists(repo: &Path, short_name: &str, v: Version) {
332-
assert!(lib_exists(repo, short_name, v));
331+
fn assert_lib_exists(repo: &Path, pkg_path: &Path, v: Version) {
332+
assert!(lib_exists(repo, pkg_path, v));
333333
}
334334

335-
fn lib_exists(repo: &Path, short_name: &str, _v: Version) -> bool { // ??? version?
336-
debug!("assert_lib_exists: repo = %s, short_name = %s", repo.to_str(), short_name);
337-
let lib = installed_library_in_workspace(short_name, repo);
335+
fn lib_exists(repo: &Path, pkg_path: &Path, _v: Version) -> bool { // ??? version?
336+
debug!("assert_lib_exists: repo = %s, pkg_path = %s", repo.to_str(), pkg_path.to_str());
337+
let lib = installed_library_in_workspace(pkg_path, repo);
338338
debug!("assert_lib_exists: checking whether %? exists", lib);
339339
lib.is_some() && {
340340
let libname = lib.get_ref();
@@ -507,7 +507,7 @@ fn test_install_valid() {
507507
assert!(os::path_exists(&exec));
508508
assert!(is_rwx(&exec));
509509

510-
let lib = installed_library_in_workspace(temp_pkg_id.short_name, &temp_workspace);
510+
let lib = installed_library_in_workspace(&temp_pkg_id.path, &temp_workspace);
511511
debug!("lib = %?", lib);
512512
assert!(lib.map_default(false, |l| os::path_exists(l)));
513513
assert!(lib.map_default(false, |l| is_rwx(l)));
@@ -571,7 +571,7 @@ fn test_install_git() {
571571
let _built_lib =
572572
built_library_in_workspace(&temp_pkg_id,
573573
&ws).expect("test_install_git: built lib should exist");
574-
assert_lib_exists(&ws, temp_pkg_id.short_name, temp_pkg_id.version.clone());
574+
assert_lib_exists(&ws, &temp_pkg_id.path, temp_pkg_id.version.clone());
575575
let built_test = built_test_in_workspace(&temp_pkg_id,
576576
&ws).expect("test_install_git: built test should exist");
577577
assert!(os::path_exists(&built_test));
@@ -685,7 +685,7 @@ fn test_package_request_version() {
685685
686686
command_line_test([~"install", fmt!("%s#0.3", local_path)], &repo);
687687
688-
assert!(match installed_library_in_workspace("test_pkg_version", &repo.push(".rust")) {
688+
assert!(match installed_library_in_workspace(&Path("test_pkg_version"), &repo.push(".rust")) {
689689
Some(p) => {
690690
debug!("installed: %s", p.to_str());
691691
p.to_str().ends_with(fmt!("0.3%s", os::consts::DLL_SUFFIX))
@@ -731,7 +731,7 @@ fn rustpkg_library_target() {
731731
732732
add_git_tag(&package_dir, ~"1.0");
733733
command_line_test([~"install", ~"foo"], &foo_repo);
734-
assert_lib_exists(&foo_repo.push(".rust"), "foo", ExactRevision(~"1.0"));
734+
assert_lib_exists(&foo_repo.push(".rust"), &Path("foo"), ExactRevision(~"1.0"));
735735
}
736736
737737
#[test]
@@ -754,7 +754,7 @@ fn package_script_with_default_build() {
754754
fail!("Couldn't copy file");
755755
}
756756
command_line_test([~"install", ~"fancy-lib"], &dir);
757-
assert_lib_exists(&dir, "fancy-lib", NoVersion);
757+
assert_lib_exists(&dir, &Path("fancy-lib"), NoVersion);
758758
assert!(os::path_exists(&dir.push("build").push("fancy-lib").push("generated.rs")));
759759
}
760760
@@ -783,7 +783,7 @@ fn rustpkg_install_no_arg() {
783783
"fn main() { let _x = (); }");
784784
debug!("install_no_arg: dir = %s", package_dir.to_str());
785785
command_line_test([~"install"], &package_dir);
786-
assert_lib_exists(&tmp, "foo", NoVersion);
786+
assert_lib_exists(&tmp, &Path("foo"), NoVersion);
787787
}
788788
789789
#[test]
@@ -1172,11 +1172,11 @@ fn rust_path_hack_test(hack_flag: bool) {
11721172
dest_workspace.to_str(), workspace.push_many(["src", "foo-0.1"]).to_str());
11731173
command_line_test_with_env(~[~"install"] + if hack_flag { ~[~"--rust-path-hack"] } else { ~[] } +
11741174
~[~"foo"], &dest_workspace, rust_path);
1175-
assert_lib_exists(&dest_workspace, "foo", NoVersion);
1175+
assert_lib_exists(&dest_workspace, &Path("foo"), NoVersion);
11761176
assert_executable_exists(&dest_workspace, "foo");
11771177
assert_built_library_exists(&dest_workspace, "foo");
11781178
assert_built_executable_exists(&dest_workspace, "foo");
1179-
assert!(!lib_exists(&workspace, "foo", NoVersion));
1179+
assert!(!lib_exists(&workspace, &Path("foo"), NoVersion));
11801180
assert!(!executable_exists(&workspace, "foo"));
11811181
assert!(!built_library_exists(&workspace, "foo"));
11821182
assert!(!built_executable_exists(&workspace, "foo"));
@@ -1212,9 +1212,9 @@ fn rust_path_hack_cwd() {
12121212
debug!("declare -x RUST_PATH=%s", dest_workspace.to_str());
12131213
command_line_test_with_env([~"install", ~"--rust-path-hack", ~"foo"], &cwd, rust_path);
12141214
debug!("Checking that foo exists in %s", dest_workspace.to_str());
1215-
assert_lib_exists(&dest_workspace, "foo", NoVersion);
1215+
assert_lib_exists(&dest_workspace, &Path("foo"), NoVersion);
12161216
assert_built_library_exists(&dest_workspace, "foo");
1217-
assert!(!lib_exists(&cwd, "foo", NoVersion));
1217+
assert!(!lib_exists(&cwd, &Path("foo"), NoVersion));
12181218
assert!(!built_library_exists(&cwd, "foo"));
12191219
}
12201220

@@ -1232,9 +1232,9 @@ fn rust_path_hack_multi_path() {
12321232
debug!("declare -x RUST_PATH=%s", dest_workspace.to_str());
12331233
command_line_test_with_env([~"install", ~"--rust-path-hack", name.clone()], &subdir, rust_path);
12341234
debug!("Checking that %s exists in %s", name, dest_workspace.to_str());
1235-
assert_lib_exists(&dest_workspace, "quux", NoVersion);
1235+
assert_lib_exists(&dest_workspace, &Path("quux"), NoVersion);
12361236
assert_built_library_exists(&dest_workspace, name);
1237-
assert!(!lib_exists(&subdir, "quux", NoVersion));
1237+
assert!(!lib_exists(&subdir, &Path("quux"), NoVersion));
12381238
assert!(!built_library_exists(&subdir, name));
12391239
}
12401240

@@ -1251,9 +1251,9 @@ fn rust_path_hack_install_no_arg() {
12511251
debug!("declare -x RUST_PATH=%s", dest_workspace.to_str());
12521252
command_line_test_with_env([~"install", ~"--rust-path-hack"], &source_dir, rust_path);
12531253
debug!("Checking that foo exists in %s", dest_workspace.to_str());
1254-
assert_lib_exists(&dest_workspace, "foo", NoVersion);
1254+
assert_lib_exists(&dest_workspace, &Path("foo"), NoVersion);
12551255
assert_built_library_exists(&dest_workspace, "foo");
1256-
assert!(!lib_exists(&source_dir, "foo", NoVersion));
1256+
assert!(!lib_exists(&source_dir, &Path("foo"), NoVersion));
12571257
assert!(!built_library_exists(&cwd, "foo"));
12581258
}
12591259

@@ -1378,7 +1378,7 @@ fn notrans_flag_fail() {
13781378
// we can't tell
13791379
assert!(!built_executable_exists(&workspace, "foo"));
13801380
assert!(!object_file_exists(&workspace, "foo"));
1381-
assert!(!lib_exists(&workspace, "foo", NoVersion));
1381+
assert!(!lib_exists(&workspace, &Path("foo"), NoVersion));
13821382
}
13831383
}
13841384

@@ -1550,6 +1550,37 @@ fn test_optimized_build() {
15501550
assert!(built_executable_exists(&workspace, "foo"));
15511551
}
15521552
1553+
fn pkgid_pointing_to_subdir() {
1554+
// The actual repo is mockgithub.com/mozilla/some_repo
1555+
// rustpkg should recognize that and treat the part after some_repo/ as a subdir
1556+
let workspace = mkdtemp(&os::tmpdir(), "parent_repo").expect("Couldn't create temp dir");
1557+
assert!(os::mkdir_recursive(&workspace.push_many([~"src", ~"mockgithub.com",
1558+
~"mozilla", ~"some_repo"]), U_RWX));
1559+
1560+
let foo_dir = workspace.push_many([~"src", ~"mockgithub.com", ~"mozilla", ~"some_repo",
1561+
~"extras", ~"foo"]);
1562+
let bar_dir = workspace.push_many([~"src", ~"mockgithub.com", ~"mozilla", ~"some_repo",
1563+
~"extras", ~"bar"]);
1564+
assert!(os::mkdir_recursive(&foo_dir, U_RWX));
1565+
assert!(os::mkdir_recursive(&bar_dir, U_RWX));
1566+
writeFile(&foo_dir.push("lib.rs"), "pub fn f() {}");
1567+
writeFile(&bar_dir.push("lib.rs"), "pub fn g() {}");
1568+
1569+
debug!("Creating a file in %s", workspace.to_str());
1570+
let testpkg_dir = workspace.push_many([~"src", ~"testpkg-0.1"]);
1571+
assert!(os::mkdir_recursive(&testpkg_dir, U_RWX));
1572+
1573+
writeFile(&testpkg_dir.push("main.rs"),
1574+
"extern mod foo = \"mockgithub.com/mozilla/some_repo/extras/foo\";\n
1575+
extern mod bar = \"mockgithub.com/mozilla/some_repo/extras/bar\";\n
1576+
use foo::f; use bar::g; \n
1577+
fn main() { f(); g(); }");
1578+
1579+
debug!("RUST_PATH=%s", workspace.to_str());
1580+
command_line_test([~"install", ~"testpkg"], &workspace);
1581+
assert_executable_exists(&workspace, "testpkg");
1582+
}
1583+
15531584
/// Returns true if p exists and is executable
15541585
fn is_executable(p: &Path) -> bool {
15551586
use std::libc::consts::os::posix88::{S_IXUSR};

src/librustpkg/util.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,8 @@ pub fn find_and_install_dependencies(ctxt: &BuildContext,
378378
Some(p) => p,
379379
None => sess.str_of(lib_ident)
380380
};
381-
match installed_library_in_workspace(lib_name, &ctxt.sysroot()) {
381+
debug!("Finding and installing... %s", lib_name);
382+
match installed_library_in_workspace(&Path(lib_name), &ctxt.sysroot()) {
382383
Some(ref installed_path) => {
383384
debug!("It exists: %s", installed_path.to_str());
384385
// Say that [path for c] has a discovered dependency on
@@ -420,8 +421,9 @@ pub fn find_and_install_dependencies(ctxt: &BuildContext,
420421
}
421422
}
422423
// Also, add an additional search path
424+
debug!("Adding additional search path: %s", lib_name);
423425
let installed_library =
424-
installed_library_in_workspace(lib_name, workspace)
426+
installed_library_in_workspace(&Path(lib_name), workspace)
425427
.expect( fmt!("rustpkg failed to install dependency %s",
426428
lib_name));
427429
let install_dir = installed_library.pop();

src/librustpkg/workspace.rs

+2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ pub fn each_pkg_parent_workspace(cx: &Context, pkgid: &PkgId, action: &fn(&Path)
3838
return true;
3939
}
4040

41+
/// Given a package ID, return a vector of all of the workspaces in
42+
/// the RUST_PATH that contain it
4143
pub fn pkg_parent_workspaces(cx: &Context, pkgid: &PkgId) -> ~[Path] {
4244
let rs: ~[Path] = rust_path().move_iter()
4345
.filter(|ws| workspace_contains_package_id(pkgid, ws))

0 commit comments

Comments
 (0)