-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cargo install multiple crates #4216
Changes from 9 commits
66168ac
40226f5
f2084b7
497c297
a65fad0
daf4eab
aa201ab
f78fc7c
1800c43
1c7c88a
ce2d69d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -55,37 +55,103 @@ impl Drop for Transaction { | |
} | ||
|
||
pub fn install(root: Option<&str>, | ||
krate: Option<&str>, | ||
krates: Vec<&str>, | ||
source_id: &SourceId, | ||
vers: Option<&str>, | ||
opts: &ops::CompileOptions, | ||
force: bool) -> CargoResult<()> { | ||
let root = resolve_root(root, opts.config)?; | ||
let map = SourceConfigMap::new(opts.config)?; | ||
|
||
let installed_anything = if krates.len() <= 1 { | ||
install_one(root.clone(), map, krates.into_iter().next(), source_id, vers, opts, | ||
force, true)?; | ||
true | ||
} else { | ||
let mut succeeded = vec![]; | ||
let mut failed = vec![]; | ||
let mut first = true; | ||
for krate in krates { | ||
let root = root.clone(); | ||
let map = map.clone(); | ||
match install_one(root, map, Some(krate), source_id, vers, opts, force, first) { | ||
Ok(()) => succeeded.push(krate), | ||
Err(e) => { | ||
opts.config.shell().error(e)?; | ||
failed.push(krate) | ||
} | ||
} | ||
first = false; | ||
} | ||
|
||
let mut summary = vec![]; | ||
if !succeeded.is_empty() { | ||
summary.push(format!("Successfully installed {}!", succeeded.join(", "))); | ||
} | ||
if !failed.is_empty() { | ||
summary.push(format!("Failed to install {} (see error(s) above).", failed.join(", "))); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this schedule an error to be returned at the top level, to ensure that cargo returns a nonzero exit status? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now if there are failures it looks like this:
and exits with 101. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
} | ||
if !succeeded.is_empty() || !failed.is_empty() { | ||
opts.config.shell().status("\nSummary:", summary.join(" "))?; | ||
} | ||
|
||
!succeeded.is_empty() | ||
}; | ||
|
||
if installed_anything { | ||
// Print a warning that if this directory isn't in PATH that they won't be | ||
// able to run these commands. | ||
let dst = metadata(opts.config, &root)?.parent().join("bin"); | ||
let path = env::var_os("PATH").unwrap_or(OsString::new()); | ||
for path in env::split_paths(&path) { | ||
if path == dst { | ||
return Ok(()) | ||
} | ||
} | ||
|
||
opts.config.shell().warn(&format!("be sure to add `{}` to your PATH to be \ | ||
able to run the installed binaries", | ||
dst.display()))?; | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
fn install_one(root: Filesystem, | ||
map: SourceConfigMap, | ||
krate: Option<&str>, | ||
source_id: &SourceId, | ||
vers: Option<&str>, | ||
opts: &ops::CompileOptions, | ||
force: bool, | ||
is_first_install: bool) -> CargoResult<()> { | ||
|
||
let config = opts.config; | ||
let root = resolve_root(root, config)?; | ||
let map = SourceConfigMap::new(config)?; | ||
|
||
let (pkg, source) = if source_id.is_git() { | ||
select_pkg(GitSource::new(source_id, config), | ||
krate, vers, config, &mut |git| git.read_packages())? | ||
krate, vers, config, is_first_install, | ||
&mut |git| git.read_packages())? | ||
} else if source_id.is_path() { | ||
let path = source_id.url().to_file_path().ok() | ||
.expect("path sources must have a valid path"); | ||
let path = source_id.url().to_file_path() | ||
.map_err(|()| CargoError::from("path sources must have a valid path"))?; | ||
let mut src = PathSource::new(&path, source_id, config); | ||
src.update().chain_err(|| { | ||
format!("`{}` is not a crate root; specify a crate to \ | ||
install from crates.io, or use --path or --git to \ | ||
specify an alternate source", path.display()) | ||
})?; | ||
select_pkg(PathSource::new(&path, source_id, config), | ||
krate, vers, config, &mut |path| path.read_packages())? | ||
krate, vers, config, is_first_install, | ||
&mut |path| path.read_packages())? | ||
} else { | ||
select_pkg(map.load(source_id)?, | ||
krate, vers, config, | ||
krate, vers, config, is_first_install, | ||
&mut |_| Err("must specify a crate to install from \ | ||
crates.io, or use --path or --git to \ | ||
specify alternate source".into()))? | ||
}; | ||
|
||
|
||
let mut td_opt = None; | ||
let overidden_target_dir = if source_id.is_path() { | ||
None | ||
|
@@ -248,30 +314,22 @@ pub fn install(root: Option<&str>, | |
fs::remove_dir_all(&target_dir)?; | ||
} | ||
|
||
// Print a warning that if this directory isn't in PATH that they won't be | ||
// able to run these commands. | ||
let path = env::var_os("PATH").unwrap_or(OsString::new()); | ||
for path in env::split_paths(&path) { | ||
if path == dst { | ||
return Ok(()) | ||
} | ||
} | ||
|
||
config.shell().warn(&format!("be sure to add `{}` to your PATH to be \ | ||
able to run the installed binaries", | ||
dst.display()))?; | ||
Ok(()) | ||
} | ||
|
||
fn select_pkg<'a, T>(mut source: T, | ||
name: Option<&str>, | ||
vers: Option<&str>, | ||
config: &Config, | ||
needs_update: bool, | ||
list_all: &mut FnMut(&mut T) -> CargoResult<Vec<Package>>) | ||
-> CargoResult<(Package, Box<Source + 'a>)> | ||
where T: Source + 'a | ||
{ | ||
source.update()?; | ||
if needs_update { | ||
source.update()?; | ||
} | ||
|
||
match name { | ||
Some(name) => { | ||
let vers = match vers { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this'll want to use the top-level error handling functions in Cargo in the root
src/cargo/lib.rs
, there's a lot of contextual information in this error that the rawDisplay
impl doesn't print out.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated to use
::handle_error
, I assume that's what you meant?