1 use crate::command_prelude::*;
2
3 use cargo::core::{GitReference, SourceId};
4 use cargo::ops;
5 use cargo::util::IntoUrl;
6
cli() -> App7 pub fn cli() -> App {
8 subcommand("install")
9 .about("Install a Rust binary. Default location is $HOME/.cargo/bin")
10 .arg(opt("quiet", "Do not print cargo log messages").short("q"))
11 .arg(Arg::with_name("crate").empty_values(false).multiple(true))
12 .arg(
13 opt("version", "Specify a version to install")
14 .alias("vers")
15 .value_name("VERSION")
16 .requires("crate"),
17 )
18 .arg(
19 opt("git", "Git URL to install the specified crate from")
20 .value_name("URL")
21 .conflicts_with_all(&["path", "index", "registry"]),
22 )
23 .arg(
24 opt("branch", "Branch to use when installing from git")
25 .value_name("BRANCH")
26 .requires("git"),
27 )
28 .arg(
29 opt("tag", "Tag to use when installing from git")
30 .value_name("TAG")
31 .requires("git"),
32 )
33 .arg(
34 opt("rev", "Specific commit to use when installing from git")
35 .value_name("SHA")
36 .requires("git"),
37 )
38 .arg(
39 opt("path", "Filesystem path to local crate to install")
40 .value_name("PATH")
41 .conflicts_with_all(&["git", "index", "registry"]),
42 )
43 .arg(opt(
44 "list",
45 "list all installed packages and their versions",
46 ))
47 .arg_jobs()
48 .arg(opt("force", "Force overwriting existing crates or binaries").short("f"))
49 .arg(opt("no-track", "Do not save tracking information"))
50 .arg_features()
51 .arg_profile("Install artifacts with the specified profile")
52 .arg(opt("debug", "Build in debug mode instead of release mode"))
53 .arg_targets_bins_examples(
54 "Install only the specified binary",
55 "Install all binaries",
56 "Install only the specified example",
57 "Install all examples",
58 )
59 .arg_target_triple("Build for the target triple")
60 .arg_target_dir()
61 .arg(opt("root", "Directory to install packages into").value_name("DIR"))
62 .arg(
63 opt("index", "Registry index to install from")
64 .value_name("INDEX")
65 .requires("crate")
66 .conflicts_with_all(&["git", "path", "registry"]),
67 )
68 .arg(
69 opt("registry", "Registry to use")
70 .value_name("REGISTRY")
71 .requires("crate")
72 .conflicts_with_all(&["git", "path", "index"]),
73 )
74 .arg_message_format()
75 .after_help("Run `cargo help install` for more detailed information.\n")
76 }
77
exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult78 pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
79 if let Some(path) = args.value_of_path("path", config) {
80 config.reload_rooted_at(path)?;
81 } else {
82 // TODO: Consider calling set_search_stop_path(home).
83 config.reload_rooted_at(config.home().clone().into_path_unlocked())?;
84 }
85
86 let krates = args
87 .values_of("crate")
88 .unwrap_or_default()
89 .collect::<Vec<_>>();
90
91 let mut from_cwd = false;
92
93 let source = if let Some(url) = args.value_of("git") {
94 let url = url.into_url()?;
95 let gitref = if let Some(branch) = args.value_of("branch") {
96 GitReference::Branch(branch.to_string())
97 } else if let Some(tag) = args.value_of("tag") {
98 GitReference::Tag(tag.to_string())
99 } else if let Some(rev) = args.value_of("rev") {
100 GitReference::Rev(rev.to_string())
101 } else {
102 GitReference::DefaultBranch
103 };
104 SourceId::for_git(&url, gitref)?
105 } else if let Some(path) = args.value_of_path("path", config) {
106 SourceId::for_path(&path)?
107 } else if krates.is_empty() {
108 from_cwd = true;
109 SourceId::for_path(config.cwd())?
110 } else if let Some(registry) = args.registry(config)? {
111 SourceId::alt_registry(config, ®istry)?
112 } else if let Some(index) = args.value_of("index") {
113 SourceId::for_registry(&index.into_url()?)?
114 } else {
115 SourceId::crates_io(config)?
116 };
117
118 let version = args.value_of("version");
119 let root = args.value_of("root");
120
121 // We only provide workspace information for local crate installation from
122 // one of the following sources:
123 // - From current working directory (only work for edition 2015).
124 // - From a specific local file path.
125 let workspace = if from_cwd || args.is_present("path") {
126 args.workspace(config).ok()
127 } else {
128 None
129 };
130
131 let mut compile_opts = args.compile_options(
132 config,
133 CompileMode::Build,
134 workspace.as_ref(),
135 ProfileChecking::Custom,
136 )?;
137
138 compile_opts.build_config.requested_profile =
139 args.get_profile_name(config, "release", ProfileChecking::Custom)?;
140
141 if args.is_present("list") {
142 ops::install_list(root, config)?;
143 } else {
144 ops::install(
145 config,
146 root,
147 krates,
148 source,
149 from_cwd,
150 version,
151 &compile_opts,
152 args.is_present("force"),
153 args.is_present("no-track"),
154 )?;
155 }
156 Ok(())
157 }
158