-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Merged
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
66168ac
old commit adding some support for multi-install
40226f5
update test
durka f2084b7
make SourceConfigMap cloneable
durka 497c297
support installing multiple crates
durka a65fad0
don't print summary of single crate install
durka daf4eab
only print PATH warning once
durka aa201ab
use shell helpers to condense output
durka f78fc7c
add test for failing package
durka 1800c43
don't continue if single install errors
durka 1c7c88a
use top level err handling
durka ce2d69d
nonzero exit code if some crates didn't install
durka File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -55,37 +55,107 @@ 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, scheduled_error) = if krates.len() <= 1 { | ||
install_one(root.clone(), map, krates.into_iter().next(), source_id, vers, opts, | ||
force, true)?; | ||
(true, false) | ||
} 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) => { | ||
::handle_error(e, &mut opts.config.shell()); | ||
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(", "))); | ||
} | ||
if !succeeded.is_empty() || !failed.is_empty() { | ||
opts.config.shell().status("\nSummary:", summary.join(" "))?; | ||
} | ||
|
||
(!succeeded.is_empty(), !failed.is_empty()) | ||
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. Starting to accumulate a slightly worrying number of boolean flags here. :/ |
||
}; | ||
|
||
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()))?; | ||
} | ||
|
||
if scheduled_error { | ||
bail!("some crates failed to install"); | ||
} | ||
|
||
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 +318,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 { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
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 comment
The 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 comment
The reason will be displayed to describe this comment to others. Learn more.
👍