|
1 | | -use std::{env, path::PathBuf}; |
| 1 | +use std::env; |
| 2 | +use std::path::{Path, PathBuf}; |
2 | 3 |
|
3 | 4 | use crate::cargo::Subcommand; |
4 | 5 | use crate::errors::Result; |
| 6 | +use crate::file::PathExt; |
5 | 7 | use crate::rustc::TargetList; |
6 | 8 | use crate::shell::{self, MessageInfo}; |
7 | 9 | use crate::Target; |
@@ -104,36 +106,73 @@ fn is_value_arg(arg: &str, field: &str) -> Option<ArgKind> { |
104 | 106 | fn parse_next_arg<T>( |
105 | 107 | arg: String, |
106 | 108 | out: &mut Vec<String>, |
107 | | - parse: impl Fn(&str) -> T, |
| 109 | + parse: impl Fn(&str) -> Result<T>, |
| 110 | + store_cb: impl Fn(String) -> Result<String>, |
108 | 111 | iter: &mut impl Iterator<Item = String>, |
109 | | -) -> Option<T> { |
| 112 | +) -> Result<Option<T>> { |
110 | 113 | out.push(arg); |
111 | 114 | match iter.next() { |
112 | 115 | Some(next) => { |
113 | | - let result = parse(&next); |
114 | | - out.push(next); |
115 | | - Some(result) |
| 116 | + let result = parse(&next)?; |
| 117 | + out.push(store_cb(next)?); |
| 118 | + Ok(Some(result)) |
116 | 119 | } |
117 | | - None => None, |
| 120 | + None => Ok(None), |
118 | 121 | } |
119 | 122 | } |
120 | 123 |
|
121 | | -fn parse_equal_arg<T>(arg: String, out: &mut Vec<String>, parse: impl Fn(&str) -> T) -> T { |
122 | | - let result = parse(arg.split_once('=').expect("argument should contain `=`").1); |
123 | | - out.push(arg); |
| 124 | +fn parse_equal_arg<T>( |
| 125 | + arg: String, |
| 126 | + out: &mut Vec<String>, |
| 127 | + parse: impl Fn(&str) -> Result<T>, |
| 128 | + store_cb: impl Fn(String) -> Result<String>, |
| 129 | +) -> Result<T> { |
| 130 | + let (first, second) = arg.split_once('=').expect("argument should contain `=`"); |
| 131 | + let result = parse(second)?; |
| 132 | + out.push(format!("{first}={}", store_cb(second.to_owned())?)); |
124 | 133 |
|
125 | | - result |
| 134 | + Ok(result) |
126 | 135 | } |
127 | 136 |
|
128 | | -fn parse_manifest_path(path: &str) -> Option<PathBuf> { |
| 137 | +fn parse_manifest_path(path: &str) -> Result<Option<PathBuf>> { |
129 | 138 | let p = PathBuf::from(path); |
130 | | - env::current_dir().ok().map(|cwd| cwd.join(p)) |
| 139 | + Ok(absolute_path(p).ok()) |
131 | 140 | } |
132 | 141 |
|
133 | 142 | fn parse_target_dir(path: &str) -> Result<PathBuf> { |
134 | 143 | absolute_path(PathBuf::from(path)) |
135 | 144 | } |
136 | 145 |
|
| 146 | +fn identity(arg: String) -> Result<String> { |
| 147 | + Ok(arg) |
| 148 | +} |
| 149 | + |
| 150 | +fn str_to_owned(arg: &str) -> Result<String> { |
| 151 | + Ok(arg.to_owned()) |
| 152 | +} |
| 153 | + |
| 154 | +#[allow(clippy::needless_return)] |
| 155 | +fn store_manifest_path(path: String) -> Result<String> { |
| 156 | + let p = Path::new(&path); |
| 157 | + if p.is_absolute() { |
| 158 | + #[cfg(target_os = "windows")] |
| 159 | + { |
| 160 | + return p.as_wslpath(); |
| 161 | + } |
| 162 | + #[cfg(not(target_os = "windows"))] |
| 163 | + { |
| 164 | + use crate::file::ToUtf8; |
| 165 | + return p.to_utf8().map(ToOwned::to_owned); |
| 166 | + } |
| 167 | + } else { |
| 168 | + p.as_posix() |
| 169 | + } |
| 170 | +} |
| 171 | + |
| 172 | +fn store_target_dir(_: String) -> Result<String> { |
| 173 | + Ok("/target".to_owned()) |
| 174 | +} |
| 175 | + |
137 | 176 | pub fn parse(target_list: &TargetList) -> Result<Args> { |
138 | 177 | let mut channel = None; |
139 | 178 | let mut target = None; |
@@ -164,57 +203,68 @@ pub fn parse(target_list: &TargetList) -> Result<Args> { |
164 | 203 | } else if let Some(kind) = is_value_arg(&arg, "--color") { |
165 | 204 | color = match kind { |
166 | 205 | ArgKind::Next => { |
167 | | - match parse_next_arg(arg, &mut all, ToOwned::to_owned, &mut args) { |
| 206 | + match parse_next_arg(arg, &mut all, str_to_owned, identity, &mut args)? { |
168 | 207 | Some(c) => Some(c), |
169 | 208 | None => shell::invalid_color(None), |
170 | 209 | } |
171 | 210 | } |
172 | | - ArgKind::Equal => Some(parse_equal_arg(arg, &mut all, ToOwned::to_owned)), |
| 211 | + ArgKind::Equal => Some(parse_equal_arg(arg, &mut all, str_to_owned, identity)?), |
173 | 212 | }; |
174 | 213 | } else if let Some(kind) = is_value_arg(&arg, "--manifest-path") { |
175 | 214 | manifest_path = match kind { |
176 | | - ArgKind::Next => { |
177 | | - parse_next_arg(arg, &mut all, parse_manifest_path, &mut args).flatten() |
| 215 | + ArgKind::Next => parse_next_arg( |
| 216 | + arg, |
| 217 | + &mut all, |
| 218 | + parse_manifest_path, |
| 219 | + store_manifest_path, |
| 220 | + &mut args, |
| 221 | + )? |
| 222 | + .flatten(), |
| 223 | + ArgKind::Equal => { |
| 224 | + parse_equal_arg(arg, &mut all, parse_manifest_path, store_manifest_path)? |
178 | 225 | } |
179 | | - ArgKind::Equal => parse_equal_arg(arg, &mut all, parse_manifest_path), |
180 | 226 | }; |
181 | 227 | } else if let ("+", ch) = arg.split_at(1) { |
182 | 228 | channel = Some(ch.to_owned()); |
183 | 229 | } else if let Some(kind) = is_value_arg(&arg, "--target") { |
| 230 | + let parse_target = |t: &str| Ok(Target::from(t, target_list)); |
184 | 231 | target = match kind { |
185 | 232 | ArgKind::Next => { |
186 | | - parse_next_arg(arg, &mut all, |t| Target::from(t, target_list), &mut args) |
| 233 | + parse_next_arg(arg, &mut all, parse_target, identity, &mut args)? |
187 | 234 | } |
188 | | - ArgKind::Equal => Some(parse_equal_arg(arg, &mut all, |t| { |
189 | | - Target::from(t, target_list) |
190 | | - })), |
| 235 | + ArgKind::Equal => Some(parse_equal_arg(arg, &mut all, parse_target, identity)?), |
191 | 236 | }; |
192 | 237 | } else if let Some(kind) = is_value_arg(&arg, "--features") { |
193 | 238 | match kind { |
194 | 239 | ArgKind::Next => { |
195 | | - let next = parse_next_arg(arg, &mut all, ToOwned::to_owned, &mut args); |
| 240 | + let next = |
| 241 | + parse_next_arg(arg, &mut all, str_to_owned, identity, &mut args)?; |
196 | 242 | if let Some(feature) = next { |
197 | 243 | features.push(feature); |
198 | 244 | } |
199 | 245 | } |
200 | 246 | ArgKind::Equal => { |
201 | | - features.push(parse_equal_arg(arg, &mut all, ToOwned::to_owned)); |
| 247 | + features.push(parse_equal_arg(arg, &mut all, str_to_owned, identity)?); |
202 | 248 | } |
203 | 249 | } |
204 | 250 | } else if let Some(kind) = is_value_arg(&arg, "--target-dir") { |
205 | 251 | match kind { |
206 | 252 | ArgKind::Next => { |
207 | | - all.push(arg); |
208 | | - if let Some(td) = args.next() { |
209 | | - target_dir = Some(parse_target_dir(&td)?); |
210 | | - all.push("/target".to_owned()); |
211 | | - } |
| 253 | + target_dir = parse_next_arg( |
| 254 | + arg, |
| 255 | + &mut all, |
| 256 | + parse_target_dir, |
| 257 | + store_target_dir, |
| 258 | + &mut args, |
| 259 | + )?; |
212 | 260 | } |
213 | 261 | ArgKind::Equal => { |
214 | | - target_dir = Some(parse_target_dir( |
215 | | - arg.split_once('=').expect("argument should contain `=`").1, |
| 262 | + target_dir = Some(parse_equal_arg( |
| 263 | + arg, |
| 264 | + &mut all, |
| 265 | + parse_target_dir, |
| 266 | + store_target_dir, |
216 | 267 | )?); |
217 | | - all.push("--target-dir=/target".into()); |
218 | 268 | } |
219 | 269 | } |
220 | 270 | } else { |
|
0 commit comments