// except according to those terms.
use std::hash::Streaming;
-use std::hash;
use syntax::crateid;
+use extra::hex::ToHex;
+use rustc::util::sha2::{Digest, Sha256};
/// Path-fragment identifier of a package such as
/// 'github.com/graydon/test'; path must be a relative
}
impl CrateId {
- pub fn get_version<'a>(&'a self) -> &'a str {
+ pub fn version_or_default<'a>(&'a self) -> &'a str {
match self.version {
Some(ref ver) => ver.as_slice(),
None => "0.0"
}
}
+ pub fn to_crate_id_str(&self) -> ~str {
+ format!("{}\\#{}", self.path.as_str().unwrap(), self.version_or_default())
+ }
+
+ pub fn to_lib_name(&self) -> ~str {
+ format!("{}-{}-{}", self.short_name, self.hash(), self.version_or_default())
+ }
+
pub fn hash(&self) -> ~str {
- // FIXME (#9639): hash should take a &[u8] so we can hash the real path
- self.path.display().with_str(|s| {
- let vers = self.get_version();
- format!("{}-{}-{}", s, hash(s + vers), vers)
- })
+ let mut hasher = Sha256::new();
+ hasher.reset();
+ hasher.input_str(self.to_crate_id_str());
+ let hash = hasher.result_bytes().to_hex();
+ hash.slice_chars(0, 8).to_owned()
}
pub fn short_name_with_version(&self) -> ~str {
- format!("{}-{}", self.short_name, self.get_version())
+ format!("{}-{}", self.short_name, self.version_or_default())
}
/// True if the ID has multiple components
impl ToStr for CrateId {
fn to_str(&self) -> ~str {
// should probably use the filestem and not the whole path
- format!("{}-{}", self.path.as_str().unwrap(), self.get_version())
+ format!("{}-{}", self.path.as_str().unwrap(), self.version_or_default())
}
}
-
pub fn write<W: Writer>(writer: &mut W, string: &str) {
writer.write(string.as_bytes());
}
-
-pub fn hash(data: ~str) -> ~str {
- let hasher = &mut hash::default_state();
- write(hasher, data);
- hasher.result_str()
-}
-
// FIXME (#9639): This needs to handle non-utf8 paths
let url = format!("https://{}", crateid.path.as_str().unwrap());
debug!("Fetching package: git clone {} {} [version={}]",
- url, clone_target.display(), crateid.get_version());
+ url, clone_target.display(), crateid.version_or_default());
let mut failed = false;
pub use crate_id::CrateId;
pub use target::{OutputType, Main, Lib, Test, Bench, Target, Build, Install};
-pub use version::{Version, split_version, split_version_general,
- try_parsing_version};
+pub use version::{Version, split_version, split_version_general, try_parsing_version};
pub use rustc::metadata::filesearch::rust_path;
-use rustc::metadata::filesearch::{libdir, relative_target_lib_path};
-use rustc::driver::driver::host_triple;
use std::libc;
use std::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
use std::os;
use std::io;
use std::io::fs;
+use rustc::metadata::filesearch::{libdir, relative_target_lib_path};
+use rustc::driver::driver::host_triple;
use messages::*;
pub fn default_workspace() -> Path {
/// Figure out what the library name for <crateid> in <workspace>'s build
/// directory is, and if the file exists, return it.
pub fn built_library_in_workspace(crateid: &CrateId, workspace: &Path) -> Option<Path> {
- library_in_workspace(&crateid.path, crateid.short_name, Build, workspace, "build",
- &crateid.version)
+ library_in_workspace(crateid, Build, workspace)
}
/// Does the actual searching stuff
-pub fn installed_library_in_workspace(pkg_path: &Path, workspace: &Path) -> Option<Path> {
+pub fn installed_library_in_workspace(crate_id: &CrateId, workspace: &Path) -> Option<Path> {
// This could break once we're handling multiple versions better -- I should add a test for it
// FIXME (#9639): This needs to handle non-utf8 paths
- match pkg_path.filename_str() {
+ match crate_id.path.filename_str() {
None => None,
- Some(short_name) => library_in_workspace(pkg_path,
- short_name,
- Install,
- workspace,
- libdir(),
- &None)
+ Some(_short_name) => library_in_workspace(crate_id, Install, workspace)
}
}
/// `workspace` is used to figure out the directory to search.
/// `short_name` is taken as the link name of the library.
-pub fn library_in_workspace(path: &Path, short_name: &str, where: Target,
- workspace: &Path, prefix: &str, version: &Version) -> Option<Path> {
+pub fn library_in_workspace(crate_id: &CrateId, where: Target, workspace: &Path) -> Option<Path> {
debug!("library_in_workspace: checking whether a library named {} exists",
- short_name);
-
- // We don't know what the hash is, so we have to search through the directory
- // contents
-
- debug!("short_name = {} where = {:?} workspace = {} \
- prefix = {}", short_name, where, workspace.display(), prefix);
+ crate_id.short_name);
let dir_to_search = match where {
- Build => target_build_dir(workspace).join(path),
+ Build => target_build_dir(workspace).join(&crate_id.path),
Install => target_lib_dir(workspace)
};
- library_in(short_name, version, &dir_to_search)
+ library_in(crate_id, &dir_to_search)
}
pub fn system_library(sysroot: &Path, crate_id: &str) -> Option<Path> {
- let (lib_name, version) = split_crate_id(crate_id);
- library_in(lib_name, &version, &sysroot.join(relative_target_lib_path(host_triple())))
-}
-
-fn library_in(short_name: &str, version: &Version, dir_to_search: &Path) -> Option<Path> {
- debug!("Listing directory {}", dir_to_search.display());
- let dir_contents = {
- let _guard = io::ignore_io_error();
- fs::readdir(dir_to_search)
- };
- debug!("dir has {:?} entries", dir_contents.len());
-
- let dll_prefix = format!("{}{}", os::consts::DLL_PREFIX, short_name);
- let dll_filetype = os::consts::DLL_EXTENSION;
- let rlib_prefix = format!("{}{}", "lib", short_name);
- let rlib_filetype = "rlib";
-
- debug!("dll_prefix = {} and dll_filetype = {}", dll_prefix, dll_filetype);
- debug!("rlib_prefix = {} and rlib_filetype = {}", rlib_prefix, rlib_filetype);
-
- // Find a filename that matches the pattern:
- // (lib_prefix)-hash-(version)(lib_suffix)
- let mut libraries = dir_contents.iter().filter(|p| {
- let extension = p.extension_str();
- debug!("p = {}, p's extension is {:?}", p.display(), extension);
- match extension {
- None => false,
- Some(ref s) => dll_filetype == *s || rlib_filetype == *s,
+ library_in(&CrateId::new(crate_id), &sysroot.join(relative_target_lib_path(host_triple())))
+}
+
+fn library_in(crate_id: &CrateId, dir_to_search: &Path) -> Option<Path> {
+ let lib_name = crate_id.to_lib_name();
+ let filenames = [
+ format!("{}{}.{}", "lib", lib_name, "rlib"),
+ format!("{}{}{}", os::consts::DLL_PREFIX, lib_name, os::consts::DLL_SUFFIX),
+ ];
+
+ for filename in filenames.iter() {
+ debug!("filename = {}", filename.as_slice());
+ let path = dir_to_search.join(filename.as_slice());
+ if path.exists() {
+ debug!("found: {}", path.display());
+ return Some(path);
}
- });
-
- let mut result_filename = None;
- for p_path in libraries {
- // Find a filename that matches the pattern: (lib_prefix)-hash-(version)(lib_suffix)
- // and remember what the hash was
- let mut f_name = match p_path.filestem_str() {
- Some(s) => s, None => continue
- };
- // Already checked the filetype above
-
- // This is complicated because library names and versions can both contain dashes
- loop {
- if f_name.is_empty() { break; }
- match f_name.rfind('-') {
- Some(i) => {
- debug!("Maybe {} is a version", f_name.slice(i + 1, f_name.len()));
- match try_parsing_version(f_name.slice(i + 1, f_name.len())) {
- Some(ref found_vers) if version == &Some(found_vers.to_owned()) ||
- version == &None => {
- match f_name.slice(0, i).rfind('-') {
- Some(j) => {
- let lib_prefix = match p_path.extension_str() {
- Some(ref s) if dll_filetype == *s => &dll_prefix,
- _ => &rlib_prefix,
- };
- debug!("Maybe {} equals {}", f_name.slice(0, j), *lib_prefix);
- if f_name.slice(0, j) == *lib_prefix {
- result_filename = Some(p_path.clone());
- }
- break;
- }
- None => break
- }
- }
- _ => { f_name = f_name.slice(0, i); }
- }
- }
- None => break
- } // match
- } // loop
- } // for
-
- if result_filename.is_none() {
- debug!("warning: library_in_workspace didn't find a library in {} for {}",
- dir_to_search.display(), short_name);
- }
-
- // Return the filename that matches, which we now know exists
- // (if result_filename != None)
- let abs_path = result_filename.map(|result_filename| {
- let absolute_path = dir_to_search.join(&result_filename);
- debug!("result_filename = {}", absolute_path.display());
- absolute_path
- });
-
- abs_path
-}
-
-fn split_crate_id<'a>(crate_id: &'a str) -> (&'a str, Version) {
- match split_version(crate_id) {
- Some((name, vers)) =>
- match vers {
- Some(ref v) => match v.find('-') {
- Some(pos) => (name, Some(v.slice(0, pos).to_owned())),
- None => (name, Some(v.to_owned()))
- },
- _ => (name, vers)
- },
- None => (crate_id, None)
}
+ debug!("warning: library_in_workspace didn't find a library in {} for {}",
+ dir_to_search.display(), crate_id.short_name);
+ return None;
}
-
-
/// Returns the executable that would be installed for <crateid>
/// in <workspace>
/// As a side effect, creates the bin-dir if it doesn't exist
}
-fn assert_lib_exists(repo: &Path, pkg_path: &Path, v: Option<~str>) {
- assert!(lib_exists(repo, pkg_path, v));
+fn assert_lib_exists(repo: &Path, crate_id: &CrateId) {
+ assert!(lib_exists(repo, crate_id));
}
-fn lib_exists(repo: &Path, pkg_path: &Path, _v: Option<~str>) -> bool { // ??? version?
- debug!("assert_lib_exists: repo = {}, pkg_path = {}", repo.display(), pkg_path.display());
- let lib = installed_library_in_workspace(pkg_path, repo);
+fn lib_exists(repo: &Path, crate_id: &CrateId) -> bool {
+ debug!("assert_lib_exists: repo = {}, crate_id = {}", repo.display(), crate_id.to_str());
+ let lib = installed_library_in_workspace(crate_id, repo);
debug!("assert_lib_exists: checking whether {:?} exists", lib);
lib.is_some() && {
let libname = lib.get_ref();
fn lib_output_file_name(workspace: &Path, short_name: &str) -> Path {
debug!("lib_output_file_name: given {} and short name {}",
workspace.display(), short_name);
- library_in_workspace(&Path::new(short_name),
- short_name,
+ library_in_workspace(&CrateId::new(short_name),
Build,
- workspace,
- "build",
- &None).expect("lib_output_file_name")
+ workspace).expect("lib_output_file_name")
}
#[cfg(target_os = "linux")]
assert!(exec.exists());
assert!(is_rwx(&exec));
- let lib = installed_library_in_workspace(&temp_pkg_id.path, temp_workspace);
+ let lib = installed_library_in_workspace(&temp_pkg_id, temp_workspace);
debug!("lib = {:?}", lib);
assert!(lib.as_ref().map_or(false, |l| l.exists()));
assert!(lib.as_ref().map_or(false, |l| is_rwx(l)));
assert!(exec.exists());
assert!(is_rwx(&exec));
- let lib = installed_library_in_workspace(&temp_pkg_id.path, temp_workspace);
+ let lib = installed_library_in_workspace(&temp_pkg_id, temp_workspace);
debug!("lib = {:?}", lib);
assert!(lib.as_ref().map_or(false, |l| l.exists()));
assert!(lib.as_ref().map_or(false, |l| is_rwx(l)));
let _built_lib =
built_library_in_workspace(&temp_pkg_id,
&ws).expect("test_install_git: built lib should exist");
- assert_lib_exists(&ws, &temp_pkg_id.path, temp_pkg_id.version.clone());
+ assert_lib_exists(&ws, &temp_pkg_id);
let built_test = built_test_in_workspace(&temp_pkg_id,
&ws).expect("test_install_git: built test should exist");
assert!(built_test.exists());
command_line_test([~"install", format!("{}\\#0.3", local_path)], repo);
- assert!(match installed_library_in_workspace(&Path::new("test_pkg_version"),
+ assert!(match installed_library_in_workspace(&CrateId::new(format!("{}\\#0.3", local_path)),
&repo.join(".rust")) {
Some(p) => {
debug!("installed: {}", p.display());
"#[test] pub fn f() { (); }");
writeFile(&package_dir.join("bench.rs"),
"#[bench] pub fn f() { (); }");
+ add_git_tag(&package_dir, ~"0.0");
- add_git_tag(&package_dir, ~"1.0");
command_line_test([~"install", ~"foo"], foo_repo);
- assert_lib_exists(&foo_repo.join(".rust"), &Path::new("foo"), Some(~"1.0"));
+ assert_lib_exists(&foo_repo.join(".rust"), &CrateId::new("foo"));
}
#[test]
debug!("package_script_with_default_build: {}", source.display());
fs::copy(&source, &dir.join_many(["src", "fancy-lib-0.0", "pkg.rs"]));
command_line_test([~"install", ~"fancy-lib"], dir);
- assert_lib_exists(dir, &Path::new("fancy-lib"), None);
+ assert_lib_exists(dir, &CrateId::new("fancy-lib"));
assert!(target_build_dir(dir).join_many([~"fancy-lib", ~"generated.rs"]).exists());
let generated_path = target_build_dir(dir).join_many([~"fancy-lib", ~"generated.rs"]);
debug!("generated path = {}", generated_path.display());
"fn main() { let _x = (); }");
debug!("install_no_arg: dir = {}", package_dir.display());
command_line_test([~"install"], &package_dir);
- assert_lib_exists(&tmp, &Path::new("foo"), None);
+ assert_lib_exists(&tmp, &CrateId::new("foo"));
}
#[test]
let workspace = create_local_package(&p_id);
let workspace = workspace.path();
command_line_test([~"install", ~"foo"], workspace);
- let foo_lib = installed_library_in_workspace(&p_id.path, workspace);
+ let foo_lib = installed_library_in_workspace(&p_id, workspace);
assert!(foo_lib.is_some());
// Now make `foo` read-only so that subsequent attempts to copy to it will fail
assert!(chmod_read_only(&foo_lib.unwrap()));
foo_path.as_str().unwrap()))]);
command_line_test_with_env(~[~"install"] + if hack_flag { ~[~"--rust-path-hack"] } else { ~[] } +
~[~"foo"], dest_workspace, rust_path);
- assert_lib_exists(dest_workspace, &Path::new("foo"), None);
+ assert_lib_exists(dest_workspace, &CrateId::new("foo"));
assert_executable_exists(dest_workspace, "foo");
assert_built_library_exists(dest_workspace, "foo");
assert_built_executable_exists(dest_workspace, "foo");
- assert!(!lib_exists(workspace, &Path::new("foo"), None));
+ assert!(!lib_exists(workspace, &CrateId::new("foo")));
assert!(!executable_exists(workspace, "foo"));
assert!(!built_library_exists(workspace, "foo"));
assert!(!built_executable_exists(workspace, "foo"));
let rust_path = Some(~[(~"RUST_PATH", dest_workspace.as_str().unwrap().to_owned())]);
command_line_test_with_env([~"install", ~"--rust-path-hack", ~"foo"], &cwd, rust_path);
debug!("Checking that foo exists in {}", dest_workspace.display());
- assert_lib_exists(dest_workspace, &Path::new("foo"), None);
+ assert_lib_exists(dest_workspace, &CrateId::new("foo"));
assert_built_library_exists(dest_workspace, "foo");
- assert!(!lib_exists(&cwd, &Path::new("foo"), None));
+ assert!(!lib_exists(&cwd, &CrateId::new("foo")));
assert!(!built_library_exists(&cwd, "foo"));
}
let rust_path = Some(~[(~"RUST_PATH", dest_workspace.as_str().unwrap().to_owned())]);
command_line_test_with_env([~"install", ~"--rust-path-hack", name.clone()], &subdir, rust_path);
debug!("Checking that {} exists in {}", name, dest_workspace.display());
- assert_lib_exists(dest_workspace, &Path::new("quux"), None);
+ assert_lib_exists(dest_workspace, &CrateId::new("foo/bar/quux"));
assert_built_library_exists(dest_workspace, name);
- assert!(!lib_exists(&subdir, &Path::new("quux"), None));
+ assert!(!lib_exists(&subdir, &CrateId::new("foo/bar/quux")));
assert!(!built_library_exists(&subdir, name));
}
let rust_path = Some(~[(~"RUST_PATH", dest_workspace.as_str().unwrap().to_owned())]);
command_line_test_with_env([~"install", ~"--rust-path-hack"], &source_dir, rust_path);
debug!("Checking that foo exists in {}", dest_workspace.display());
- assert_lib_exists(dest_workspace, &Path::new("foo"), None);
+ assert_lib_exists(dest_workspace, &CrateId::new("foo"));
assert_built_library_exists(dest_workspace, "foo");
- assert!(!lib_exists(&source_dir, &Path::new("foo"), None));
+ assert!(!lib_exists(&source_dir, &CrateId::new("foo")));
assert!(!built_library_exists(cwd, "foo"));
}
workspace, None, BAD_FLAG_CODE);
assert!(!built_executable_exists(workspace, "foo"));
assert!(!object_file_exists(workspace, "foo"));
- assert!(!lib_exists(workspace, &Path::new("foo"), None));
+ assert!(!lib_exists(workspace, &CrateId::new("foo")));
}
}
fs::mkdir_recursive(&foo_dir, io::UserRWX);
fs::mkdir_recursive(&bar_dir, io::UserRWX);
writeFile(&foo_dir.join("lib.rs"),
- "#[crate_id=\"mockgithub.com/mozilla/some_repo/extras/rust-foo#foo:0.0\"];" +
+ "#[crate_id=\"mockgithub.com/mozilla/some_repo/extras/foo\"];" +
"pub fn f() {}");
writeFile(&bar_dir.join("lib.rs"),
- "#[crate_id=\"mockgithub.com/mozilla/some_repo/extras/rust-bar#bar:0.0\"];" +
+ "#[crate_id=\"mockgithub.com/mozilla/some_repo/extras/bar\"];" +
"pub fn g() {}");
debug!("Creating a file in {}", workspace.display());
command_line_test_with_env([~"install", ~"a"],
a_workspace,
environment);
- assert_lib_exists(a_workspace, &Path::new("a"), None);
- assert_lib_exists(b_workspace, &Path::new("b"), None);
- assert_lib_exists(b_workspace, &Path::new("c"), None);
+ assert_lib_exists(a_workspace, &CrateId::new("a"));
+ assert_lib_exists(b_workspace, &CrateId::new("b"));
+ assert_lib_exists(b_workspace, &CrateId::new("c"));
}
#[test]
~"foo"],
workspace);
assert!(workspace.join_many([~"lib", host_triple()]).is_dir());
- assert_lib_exists(workspace, &Path::new("foo"), None);
+ assert_lib_exists(workspace, &CrateId::new("foo"));
assert!(fs::readdir(&workspace.join("lib")).len() == 1);
assert!(workspace.join("bin").is_dir());
assert_executable_exists(workspace, "foo");
command_line_test([~"build", ~"b"], workspace);
command_line_test([~"install", ~"b"], workspace);
assert_executable_exists(workspace, b_id.short_name);
- assert_lib_exists(workspace, &b_id.path, None);
+ assert_lib_exists(workspace, &b_id);
}
#[test]
// and make sure executable was re-installed
command_line_test([~"install", ~"b"], workspace);
assert_executable_exists(workspace, b.short_name);
- assert_lib_exists(workspace, &b.path, None);
+ assert_lib_exists(workspace, &b);
remove_executable_file(&b, workspace);
command_line_test([~"install", ~"b"], workspace);
assert_executable_exists(workspace, b.short_name);
// FIXME #3408: Should be NONEXISTENT_PACKAGE_CODE
dest_workspace, rust_path, COPY_FAILED_CODE);
assert!(!executable_exists(dest_workspace, "bar"));
- assert!(!lib_exists(dest_workspace, &bar_id.path.clone(), bar_id.version.clone()));
+ assert!(!lib_exists(dest_workspace, &bar_id));
assert!(!executable_exists(dest_workspace, "foo"));
- assert!(!lib_exists(dest_workspace, &foo_id.path.clone(), foo_id.version.clone()));
+ assert!(!lib_exists(dest_workspace, &foo_id));
assert!(!executable_exists(foo_workspace, "bar"));
- assert!(!lib_exists(foo_workspace, &bar_id.path.clone(), bar_id.version.clone()));
+ assert!(!lib_exists(foo_workspace, &bar_id));
assert!(!executable_exists(foo_workspace, "foo"));
- assert!(!lib_exists(foo_workspace, &foo_id.path.clone(), foo_id.version.clone()));
+ assert!(!lib_exists(foo_workspace, &foo_id));
}
#[test]
ctx: &'a mut ReadyCtx<'a>,
}
-impl<'a> fold::Folder for CrateSetup<'a> {
+impl<'a> Folder for CrateSetup<'a> {
fn fold_item(&mut self, item: @ast::Item) -> SmallVector<@ast::Item> {
fold_item(item, self)
}
pub fn compile_input(context: &BuildContext,
exec: &mut workcache::Exec,
- pkg_id: &CrateId,
+ crate_id: &CrateId,
in_file: &Path,
workspace: &Path,
deps: &mut DepMap,
// not sure if we should support anything else
let mut out_dir = target_build_dir(workspace);
- out_dir.push(&pkg_id.path);
+ out_dir.push(&crate_id.path);
// Make the output directory if it doesn't exist already
fs::mkdir_recursive(&out_dir, io::UserRWX);
let (mut crate, ast_map) = {
let installer = CrateInstaller {
context: context,
- parent: pkg_id,
+ parent: crate_id,
parent_crate: in_file,
sess: sess,
exec: exec,
if !attr::contains_name(crate.attrs, "crate_id") {
// FIXME (#9639): This needs to handle non-utf8 paths
let crateid_attr =
- attr::mk_name_value_item_str(@"crate_id",
- format!("{}\\#{}",
- pkg_id.path.as_str().unwrap(),
- pkg_id.get_version()).to_managed());
+ attr::mk_name_value_item_str(@"crate_id", crate_id.to_crate_id_str().to_managed());
debug!("crateid attr: {:?}", crateid_attr);
crate.attrs.push(attr::mk_attr(crateid_attr));
what);
// Discover the output
let discovered_output = if what == Lib {
- built_library_in_workspace(pkg_id, workspace) // Huh???
+ built_library_in_workspace(crate_id, workspace) // Huh???
}
else {
result
// Called by build_crates
pub fn compile_crate(ctxt: &BuildContext,
exec: &mut workcache::Exec,
- pkg_id: &CrateId,
+ crate_id: &CrateId,
crate: &Path,
workspace: &Path,
deps: &mut DepMap,
opt: session::OptLevel,
what: OutputType) -> Option<Path> {
debug!("compile_crate: crate={}, workspace={}", crate.display(), workspace.display());
- debug!("compile_crate: short_name = {}, flags =...", pkg_id.to_str());
+ debug!("compile_crate: short_name = {}, flags =...", crate_id.to_str());
for fl in flags.iter() {
debug!("+++ {}", *fl);
}
- compile_input(ctxt, exec, pkg_id, crate, workspace, deps, flags, cfgs, opt, what)
+ compile_input(ctxt, exec, crate_id, crate, workspace, deps, flags, cfgs, opt, what)
}
struct CrateInstaller<'a> {
debug!("Trying to install library {}, rebuilding it",
lib_name.to_str());
// Try to install it
- let pkg_id = CrateId::new(lib_name);
+ let crate_id = CrateId::new(lib_name);
// Find all the workspaces in the RUST_PATH that contain this package.
let workspaces = pkg_parent_workspaces(&self.context.context,
- &pkg_id);
+ &crate_id);
// Three cases:
// (a) `workspaces` is empty. That means there's no local source
// for this package. In that case, we pass the default workspace
error(format!("Package {} depends on {}, but I don't know \
how to find it",
self.parent.path.display(),
- pkg_id.path.display()));
+ crate_id.path.display()));
fail!()
}).inside(|| {
PkgSrc::new(source_workspace.clone(),
// Use the rust_path_hack to search for dependencies iff
// we were already using it
self.context.context.use_rust_path_hack,
- pkg_id.clone())
+ crate_id.clone())
});
let (outputs_disc, inputs_disc) =
self.context.install(