From 9f104d4213ae31f4e61b210ef34b223c81c8c3af Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 11 May 2013 22:45:13 -0400 Subject: [PATCH] rustpkg: Remove #[allow(vecs_implicitly_copyable)] --- src/librustpkg/path_util.rs | 25 +++++----- src/librustpkg/rustpkg.rc | 82 +++++++++++++++---------------- src/librustpkg/util.rs | 98 +++++++++++++++++-------------------- src/librustpkg/workspace.rs | 2 +- 4 files changed, 100 insertions(+), 107 deletions(-) diff --git a/src/librustpkg/path_util.rs b/src/librustpkg/path_util.rs index d21fdcda7f7..477a7af4550 100644 --- a/src/librustpkg/path_util.rs +++ b/src/librustpkg/path_util.rs @@ -55,21 +55,21 @@ pub fn normalize(p: ~Path) -> ~Path { /// True if there's a directory in with /// pkgid's short name -pub fn workspace_contains_package_id(pkgid: PkgId, workspace: &Path) -> bool { +pub fn workspace_contains_package_id(pkgid: &PkgId, workspace: &Path) -> bool { let pkgpath = workspace.push("src").push(pkgid.path.to_str()); os::path_is_dir(&pkgpath) } /// Return the directory for 's source files in . /// Doesn't check that it exists. -pub fn pkgid_src_in_workspace(pkgid: PkgId, workspace: &Path) -> Path { +pub fn pkgid_src_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path { let result = workspace.push("src"); result.push(pkgid.path.to_str()) } /// Figure out what the executable name for in 's build /// directory is, and if the file exists, return it. -pub fn built_executable_in_workspace(pkgid: PkgId, workspace: &Path) -> Option { +pub fn built_executable_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option { let mut result = workspace.push("build"); result = result.push_rel(&pkgid.path); // should use a target-specific subdirectory @@ -87,7 +87,7 @@ pub fn built_executable_in_workspace(pkgid: PkgId, workspace: &Path) -> Option

in 's build /// directory is, and if the file exists, return it. -pub fn built_library_in_workspace(pkgid: PkgId, workspace: &Path) -> Option { +pub fn built_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Option { let mut result = workspace.push("build"); result = result.push_rel(&pkgid.path); // should use a target-specific subdirectory @@ -159,7 +159,7 @@ pub fn built_library_in_workspace(pkgid: PkgId, workspace: &Path) -> Option /// in /// As a side effect, creates the bin-dir if it doesn't exist -pub fn target_executable_in_workspace(pkgid: PkgId, workspace: &Path) -> Path { +pub fn target_executable_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path { target_file_in_workspace(pkgid, workspace, Main) } @@ -167,23 +167,23 @@ pub fn target_executable_in_workspace(pkgid: PkgId, workspace: &Path) -> Path { /// Returns the executable that would be installed for /// in /// As a side effect, creates the bin-dir if it doesn't exist -pub fn target_library_in_workspace(pkgid: PkgId, workspace: &Path) -> Path { +pub fn target_library_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path { target_file_in_workspace(pkgid, workspace, Lib) } /// Returns the test executable that would be installed for /// in -pub fn target_test_in_workspace(pkgid: PkgId, workspace: &Path) -> Path { +pub fn target_test_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path { target_file_in_workspace(pkgid, workspace, Test) } /// Returns the bench executable that would be installed for /// in -pub fn target_bench_in_workspace(pkgid: PkgId, workspace: &Path) -> Path { +pub fn target_bench_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path { target_file_in_workspace(pkgid, workspace, Bench) } -fn target_file_in_workspace(pkgid: PkgId, workspace: &Path, +fn target_file_in_workspace(pkgid: &PkgId, workspace: &Path, what: OutputType) -> Path { use conditions::bad_path::cond; @@ -193,7 +193,8 @@ fn target_file_in_workspace(pkgid: PkgId, workspace: &Path, let result = workspace.push(subdir); if create_dir { if !os::path_exists(&result) && !mkdir_recursive(&result, u_rwx) { - cond.raise((result, fmt!("I couldn't create the %s dir", subdir))); + cond.raise((copy result, + fmt!("I couldn't create the %s dir", subdir))); } } mk_output_path(what, pkgid.path.to_str(), result) @@ -202,13 +203,13 @@ fn target_file_in_workspace(pkgid: PkgId, workspace: &Path, /// Return the directory for 's build artifacts in . /// Creates it if it doesn't exist. -pub fn build_pkg_id_in_workspace(pkgid: PkgId, workspace: &Path) -> Path { +pub fn build_pkg_id_in_workspace(pkgid: &PkgId, workspace: &Path) -> Path { use conditions::bad_path::cond; let mut result = workspace.push("build"); // n.b. Should actually use a target-specific // subdirectory of build/ - result = result.push(normalize(~pkgid.path).to_str()); + result = result.push(normalize(~copy pkgid.path).to_str()); if os::path_exists(&result) || os::mkdir_recursive(&result, u_rwx) { result } diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index 30a84f56b5c..54713a66c0c 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -17,8 +17,6 @@ #[license = "MIT/ASL2"]; #[crate_type = "lib"]; -#[allow(vecs_implicitly_copyable, - non_implicitly_copyable_typarams)]; extern mod std(vers = "0.7-pre"); extern mod rustc(vers = "0.7-pre"); @@ -52,9 +50,9 @@ pub mod usage; /// A PkgScript represents user-supplied custom logic for /// special build hooks. This only exists for packages with /// an explicit package script. -struct PkgScript { +struct PkgScript<'self> { /// Uniquely identifies this package - id: PkgId, + id: &'self PkgId, // Used to have this field: deps: ~[(~str, Option<~str>)] // but I think it shouldn't be stored here /// The contents of the package script: either a file path, @@ -71,24 +69,24 @@ struct PkgScript { build_dir: Path } -impl PkgScript { +impl<'self> PkgScript<'self> { /// Given the path name for a package script /// and a package ID, parse the package script into /// a PkgScript that we can then execute - fn parse(script: Path, workspace: &Path, id: PkgId) -> PkgScript { + fn parse<'a>(script: Path, workspace: &Path, id: &'a PkgId) -> PkgScript<'a> { // Get the executable name that was invoked - let binary = os::args()[0]; + let binary = @copy os::args()[0]; // Build the rustc session data structures to pass // to the compiler let options = @session::options { - binary: @binary, + binary: binary, crate_type: session::bin_crate, - .. *session::basic_options() + .. copy *session::basic_options() }; let input = driver::file_input(script); let sess = driver::build_session(options, diagnostic::emit); - let cfg = driver::build_configuration(sess, @binary, &input); - let (crate, _) = driver::compile_upto(sess, cfg, &input, + let cfg = driver::build_configuration(sess, binary, &input); + let (crate, _) = driver::compile_upto(sess, copy cfg, &input, driver::cu_parse, None); let work_dir = build_pkg_id_in_workspace(id, workspace); @@ -123,10 +121,10 @@ impl PkgScript { let root = r.pop().pop().pop().pop(); // :-\ debug!("Root is %s, calling compile_rest", root.to_str()); let exe = self.build_dir.push(~"pkg" + util::exe_suffix()); - util::compile_crate_from_input(self.input, self.id, - Some(self.build_dir), + util::compile_crate_from_input(&self.input, self.id, + Some(copy self.build_dir), sess, Some(crate), - exe, os::args()[0], + &exe, @copy os::args()[0], driver::cu_everything); debug!("Running program: %s %s %s", exe.to_str(), root.to_str(), what); let status = run::run_program(exe.to_str(), ~[root.to_str(), what]); @@ -188,9 +186,9 @@ impl Ctx { } // The package id is presumed to be the first command-line // argument - let pkgid = PkgId::new(args[0]); - for pkg_parent_workspaces(pkgid) |workspace| { - self.build(workspace, pkgid); + let pkgid = PkgId::new(copy args[0]); + for pkg_parent_workspaces(&pkgid) |workspace| { + self.build(workspace, &pkgid); } } ~"clean" => { @@ -199,16 +197,16 @@ impl Ctx { } // The package id is presumed to be the first command-line // argument - let pkgid = PkgId::new(args[0]); + let pkgid = PkgId::new(copy args[0]); let cwd = os::getcwd(); - self.clean(&cwd, pkgid); // tjc: should use workspace, not cwd + self.clean(&cwd, &pkgid); // tjc: should use workspace, not cwd } ~"do" => { if args.len() < 2 { return usage::do_cmd(); } - self.do_cmd(args[0], args[1]); + self.do_cmd(copy args[0], copy args[1]); } ~"info" => { self.info(); @@ -221,8 +219,8 @@ impl Ctx { // The package id is presumed to be the first command-line // argument let pkgid = PkgId::new(args[0]); - for pkg_parent_workspaces(pkgid) |workspace| { - self.install(workspace, pkgid); + for pkg_parent_workspaces(&pkgid) |workspace| { + self.install(workspace, &pkgid); } } ~"prefer" => { @@ -230,7 +228,7 @@ impl Ctx { return usage::uninstall(); } - let (name, vers) = sep_name_vers(args[0]); + let (name, vers) = sep_name_vers(copy args[0]); self.prefer(name.get(), vers); } @@ -242,7 +240,7 @@ impl Ctx { return usage::uninstall(); } - let (name, vers) = sep_name_vers(args[0]); + let (name, vers) = sep_name_vers(copy args[0]); self.uninstall(name.get(), vers); } @@ -251,7 +249,7 @@ impl Ctx { return usage::uninstall(); } - let (name, vers) = sep_name_vers(args[0]); + let (name, vers) = sep_name_vers(copy args[0]); self.unprefer(name.get(), vers); } @@ -259,18 +257,18 @@ impl Ctx { } } - fn do_cmd(&self, _cmd: ~str, _pkgname: ~str) { + fn do_cmd(&self, _cmd: &str, _pkgname: &str) { // stub fail!("`do` not yet implemented"); } - fn build(&self, workspace: &Path, pkgid: PkgId) { + fn build(&self, workspace: &Path, pkgid: &PkgId) { let src_dir = pkgid_src_in_workspace(pkgid, workspace); let build_dir = build_pkg_id_in_workspace(pkgid, workspace); debug!("Destination dir = %s", build_dir.to_str()); // Create the package source - let mut src = PkgSrc::new(&workspace.push("src"), &build_dir, &pkgid); + let mut src = PkgSrc::new(&workspace.push("src"), &build_dir, pkgid); debug!("Package src = %?", src); // Is there custom build logic? If so, use it @@ -311,7 +309,7 @@ impl Ctx { } - fn clean(&self, workspace: &Path, id: PkgId) { + fn clean(&self, workspace: &Path, id: &PkgId) { // Could also support a custom build hook in the pkg // script for cleaning files rustpkg doesn't know about. // Do something reasonable for now @@ -332,7 +330,7 @@ impl Ctx { fail!("info not yet implemented"); } - fn install(&self, workspace: &Path, id: PkgId) { + fn install(&self, workspace: &Path, id: &PkgId) { use conditions::copy_failed::cond; // Should use RUST_PATH in the future. @@ -348,13 +346,13 @@ impl Ctx { for maybe_executable.each |exec| { debug!("Copying: %s -> %s", exec.to_str(), target_exec.to_str()); if !os::copy_file(exec, &target_exec) { - cond.raise((*exec, target_exec)); + cond.raise((copy *exec, copy target_exec)); } } for maybe_library.each |lib| { debug!("Copying: %s -> %s", lib.to_str(), target_lib.to_str()); if !os::copy_file(lib, &target_lib) { - cond.raise((*lib, target_lib)); + cond.raise((copy *lib, copy target_lib)); } } } @@ -387,7 +385,7 @@ impl Ctx { } } - fn fetch_git(&self, dir: &Path, url: ~str, target: Option<~str>) { + fn fetch_git(&self, dir: &Path, url: ~str, mut target: Option<~str>) { util::note(fmt!("fetching from %s using git", url)); // Git can't clone into a non-empty directory @@ -405,7 +403,7 @@ impl Ctx { do util::temp_change_dir(dir) { success = run::program_output(~"git", ~[~"checkout", - target.get()]).status != 0 + target.swap_unwrap()]).status != 0 } if !success { @@ -525,7 +523,7 @@ pub struct Listener { } pub fn run(listeners: ~[Listener]) { - let rcmd = os::args()[2]; + let rcmd = copy os::args()[2]; let mut found = false; for listeners.each |listener| { @@ -652,12 +650,12 @@ impl PkgSrc { // tjc: Rather than erroring out, need to try downloading the // contents of the path to a local directory (#5679) if !os::path_exists(&dir) { - cond.raise((self.id, ~"missing package dir")); + cond.raise((copy self.id, ~"missing package dir")); } if !os::path_is_dir(&dir) { - cond.raise((self.id, ~"supplied path for package dir is a \ - non-directory")); + cond.raise((copy self.id, ~"supplied path for package dir is a \ + non-directory")); } dir @@ -681,7 +679,7 @@ impl PkgSrc { /// Requires that dashes in p have already been normalized to /// underscores fn stem_matches(&self, p: &Path) -> bool { - let self_id = normalize(~self.id.path).filestem(); + let self_id = normalize(~copy self.id.path).filestem(); if self_id == p.filestem() { return true; } @@ -737,7 +735,7 @@ impl PkgSrc { util::note(~"Couldn't infer any crates to build.\n\ Try naming a crate `main.rs`, `lib.rs`, \ `test.rs`, or `bench.rs`."); - cond.raise(self.id); + cond.raise(copy self.id); } debug!("found %u libs, %u mains, %u tests, %u benchs", @@ -752,7 +750,7 @@ impl PkgSrc { dst_dir: &Path, src_dir: &Path, crates: &[Crate], - cfgs: ~[~str], + cfgs: &[~str], test: bool, crate_type: crate_type) { for crates.each |&crate| { @@ -760,7 +758,7 @@ impl PkgSrc { util::note(fmt!("build_crates: compiling %s", path.to_str())); util::note(fmt!("build_crates: destination dir is %s", dst_dir.to_str())); - let result = util::compile_crate(maybe_sysroot, self.id, path, + let result = util::compile_crate(maybe_sysroot, &self.id, path, dst_dir, crate.flags, crate.cfgs + cfgs, diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 14879c147e0..779a66f63a9 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -28,6 +28,11 @@ use syntax::attr::{mk_attr}; use rustc::back::link::output_type_exe; use rustc::driver::session::{lib_crate, unknown_crate, crate_type}; +static Commands: &'static [&'static str] = + &["build", "clean", "do", "info", "install", "prefer", "test", "uninstall", + "unprefer"]; + + pub type ExitCode = int; // For now /// A version is either an exact revision, @@ -41,28 +46,28 @@ impl Ord for Version { fn lt(&self, other: &Version) -> bool { match (self, other) { (&ExactRevision(f1), &ExactRevision(f2)) => f1 < f2, - (&SemVersion(v1), &SemVersion(v2)) => v1 < v2, + (&SemVersion(ref v1), &SemVersion(ref v2)) => v1 < v2, _ => false // incomparable, really } } fn le(&self, other: &Version) -> bool { match (self, other) { (&ExactRevision(f1), &ExactRevision(f2)) => f1 <= f2, - (&SemVersion(v1), &SemVersion(v2)) => v1 <= v2, + (&SemVersion(ref v1), &SemVersion(ref v2)) => v1 <= v2, _ => false // incomparable, really } } fn ge(&self, other: &Version) -> bool { match (self, other) { (&ExactRevision(f1), &ExactRevision(f2)) => f1 > f2, - (&SemVersion(v1), &SemVersion(v2)) => v1 > v2, + (&SemVersion(ref v1), &SemVersion(ref v2)) => v1 > v2, _ => false // incomparable, really } } fn gt(&self, other: &Version) -> bool { match (self, other) { (&ExactRevision(f1), &ExactRevision(f2)) => f1 >= f2, - (&SemVersion(v1), &SemVersion(v2)) => v1 >= v2, + (&SemVersion(ref v1), &SemVersion(ref v2)) => v1 >= v2, _ => false // incomparable, really } } @@ -72,8 +77,8 @@ impl Ord for Version { impl ToStr for Version { fn to_str(&self) -> ~str { match *self { - ExactRevision(n) => n.to_str(), - SemVersion(v) => v.to_str() + ExactRevision(ref n) => n.to_str(), + SemVersion(ref v) => v.to_str() } } } @@ -147,11 +152,8 @@ pub fn root() -> Path { } } -pub fn is_cmd(cmd: ~str) -> bool { - let cmds = &[~"build", ~"clean", ~"do", ~"info", ~"install", ~"prefer", - ~"test", ~"uninstall", ~"unprefer"]; - - vec::contains(cmds, &cmd) +pub fn is_cmd(cmd: &str) -> bool { + Commands.any(|&c| c == cmd) } pub fn parse_name(id: ~str) -> result::Result<~str, ~str> { @@ -220,7 +222,7 @@ fn fold_item(ctx: @mut ReadyCtx, for attrs.each |attr| { match attr.node.value.node { - ast::meta_list(_, mis) => { + ast::meta_list(_, ref mis) => { for mis.each |mi| { match mi.node { ast::meta_word(cmd) => cmds.push(copy *cmd), @@ -266,15 +268,14 @@ fn add_pkg_module(ctx: @mut ReadyCtx, m: ast::_mod) -> ast::_mod { } fn mk_listener_vec(ctx: @mut ReadyCtx) -> @ast::expr { - let fns = ctx.fns; - let descs = do fns.map |listener| { - mk_listener_rec(ctx, *listener) + let descs = do ctx.fns.map |listener| { + mk_listener_rec(ctx, listener) }; let ext_cx = ctx.ext_cx; build::mk_slice_vec_e(ext_cx, dummy_sp(), descs) } -fn mk_listener_rec(ctx: @mut ReadyCtx, listener: ListenerFn) -> @ast::expr { +fn mk_listener_rec(ctx: @mut ReadyCtx, listener: &ListenerFn) -> @ast::expr { let span = listener.span; let cmds = do listener.cmds.map |&cmd| { let ext_cx = ctx.ext_cx; @@ -437,11 +438,11 @@ pub fn add_pkg(pkg: &Pkg) -> bool { // FIXME (#4432): Use workcache to only compile when needed pub fn compile_input(sysroot: Option<@Path>, - pkg_id: PkgId, + pkg_id: &PkgId, in_file: &Path, out_dir: &Path, - flags: ~[~str], - cfgs: ~[~str], + flags: &[~str], + cfgs: &[~str], opt: bool, test: bool, crate_type: session::crate_type) -> bool { @@ -456,7 +457,7 @@ pub fn compile_input(sysroot: Option<@Path>, // tjc: by default, use the package ID name as the link name // not sure if we should support anything else - let binary = os::args()[0]; + let binary = @copy os::args()[0]; let building_library = match crate_type { lib_crate | unknown_crate => true, _ => false @@ -485,32 +486,27 @@ pub fn compile_input(sysroot: Option<@Path>, + flags + cfgs.flat_map(|&c| { ~[~"--cfg", c] }), driver::optgroups()).get(); - let options = @session::options { + let mut options = session::options { crate_type: crate_type, optimize: if opt { session::Aggressive } else { session::No }, test: test, maybe_sysroot: sysroot, addl_lib_search_paths: ~[copy *out_dir], - .. *driver::build_session_options(@binary, &matches, diagnostic::emit) - }; - let mut crate_cfg = options.cfg; - - for cfgs.each |&cfg| { - crate_cfg.push(attr::mk_word_item(@cfg)); - } - - let options = @session::options { - cfg: vec::append(options.cfg, crate_cfg), // output_type should be conditional output_type: output_type_exe, // Use this to get a library? That's weird - .. *options + .. copy *driver::build_session_options(binary, &matches, diagnostic::emit) }; - let sess = driver::build_session(options, diagnostic::emit); + + for cfgs.each |&cfg| { + options.cfg.push(attr::mk_word_item(@cfg)); + } + + let sess = driver::build_session(@options, diagnostic::emit); debug!("calling compile_crate_from_input, out_dir = %s, building_library = %?", out_dir.to_str(), sess.building_library); - let _ = compile_crate_from_input(input, pkg_id, Some(*out_dir), sess, None, - out_file, binary, + let _ = compile_crate_from_input(&input, pkg_id, Some(copy *out_dir), sess, + None, &out_file, binary, driver::cu_everything); true } @@ -520,18 +516,19 @@ pub fn compile_input(sysroot: Option<@Path>, // If crate_opt is present, then finish compilation. If it's None, then // call compile_upto and return the crate // also, too many arguments -pub fn compile_crate_from_input(input: driver::input, - pkg_id: PkgId, +pub fn compile_crate_from_input(input: &driver::input, + pkg_id: &PkgId, build_dir_opt: Option, sess: session::Session, crate_opt: Option<@ast::crate>, - out_file: Path, - binary: ~str, + out_file: &Path, + binary: @~str, what: driver::compile_upto) -> @ast::crate { debug!("Calling build_output_filenames with %? and %s", build_dir_opt, out_file.to_str()); - let outputs = driver::build_output_filenames(&input, &build_dir_opt, &Some(out_file), sess); + let outputs = driver::build_output_filenames(input, &build_dir_opt, + &Some(copy *out_file), sess); debug!("Outputs are %? and output type = %?", outputs, sess.opts.output_type); - let cfg = driver::build_configuration(sess, @binary, &input); + let cfg = driver::build_configuration(sess, binary, input); match crate_opt { Some(c) => { debug!("Calling compile_rest, outputs = %?", outputs); @@ -541,7 +538,7 @@ pub fn compile_crate_from_input(input: driver::input, } None => { debug!("Calling compile_upto, outputs = %?", outputs); - let (crate, _) = driver::compile_upto(sess, cfg, &input, + let (crate, _) = driver::compile_upto(sess, copy cfg, input, driver::cu_parse, Some(outputs)); debug!("About to inject link_meta info..."); @@ -552,7 +549,8 @@ pub fn compile_crate_from_input(input: driver::input, debug!("How many attrs? %?", attr::find_linkage_metas(crate.node.attrs).len()); if attr::find_linkage_metas(crate.node.attrs).is_empty() { - crate_to_use = add_attrs(*crate, ~[mk_attr(@dummy_spanned(meta_list(@~"link", + crate_to_use = add_attrs(copy *crate, + ~[mk_attr(@dummy_spanned(meta_list(@~"link", // change PkgId to have a field? ~[@dummy_spanned(meta_name_value(@~"name", mk_string_lit(@pkg_id.path.filestem().get()))), @@ -578,20 +576,16 @@ pub fn exe_suffix() -> ~str { ~"" } /// Returns a copy of crate `c` with attributes `attrs` added to its /// attributes -fn add_attrs(c: ast::crate, new_attrs: ~[attribute]) -> @ast::crate { - @spanned { - node: crate_ { - attrs: c.node.attrs + new_attrs, ..c.node - }, - span: c.span - } +fn add_attrs(mut c: ast::crate, new_attrs: ~[attribute]) -> @ast::crate { + c.node.attrs += new_attrs; + @c } // Called by build_crates // FIXME (#4432): Use workcache to only compile when needed -pub fn compile_crate(sysroot: Option<@Path>, pkg_id: PkgId, +pub fn compile_crate(sysroot: Option<@Path>, pkg_id: &PkgId, crate: &Path, dir: &Path, - flags: ~[~str], cfgs: ~[~str], opt: bool, + flags: &[~str], cfgs: &[~str], opt: bool, test: bool, crate_type: crate_type) -> bool { debug!("compile_crate: crate=%s, dir=%s", crate.to_str(), dir.to_str()); debug!("compile_crate: short_name = %s, flags =...", pkg_id.to_str()); diff --git a/src/librustpkg/workspace.rs b/src/librustpkg/workspace.rs index b0c6df05038..8941dbfd20e 100644 --- a/src/librustpkg/workspace.rs +++ b/src/librustpkg/workspace.rs @@ -14,7 +14,7 @@ use path_util::{rust_path, workspace_contains_package_id}; use util::PkgId; use core::path::Path; -pub fn pkg_parent_workspaces(pkgid: PkgId, action: &fn(&Path) -> bool) -> bool { +pub fn pkg_parent_workspaces(pkgid: &PkgId, action: &fn(&Path) -> bool) -> bool { // Using the RUST_PATH, find workspaces that contain // this package ID let workspaces = rust_path().filtered(|ws|