Skip to content

Commit 24d196c

Browse files
committed
Allow cargo() to fail, and further doc fixes
Signed-off-by: Jorge Prendes <jorge.prendes@gmail.com>
1 parent 86b6ad3 commit 24d196c

6 files changed

Lines changed: 98 additions & 87 deletions

File tree

src/cargo.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,16 @@ pub trait CargoCmd {
2525
fn checked_status(&mut self) -> Result<()>;
2626
}
2727

28-
pub fn cargo() -> Command {
29-
let cargo = env::var_os("CARGO").unwrap_or_else(|| "cargo".into());
28+
pub fn cargo() -> Result<Command> {
29+
let cargo = match env::var_os("CARGO") {
30+
Some(cargo) => Path::new(&cargo).canonicalize()?,
31+
None => which::which("cargo")?.canonicalize()?,
32+
};
3033
let mut cmd = Command::new(cargo);
3134
if let Some(rustup_toolchain) = env::var_os("RUSTUP_TOOLCHAIN") {
3235
cmd.env("RUSTUP_TOOLCHAIN", rustup_toolchain);
3336
}
34-
cmd
37+
Ok(cmd)
3538
}
3639

3740
pub struct CheckedOutput {

src/cli.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ fn resolve_target_dir(
111111
env: &HashMap<OsString, OsString>,
112112
cwd: &PathBuf,
113113
) -> Result<PathBuf> {
114-
let output = cargo()
114+
let output = cargo()?
115115
.env_clear()
116116
.envs(env.iter())
117117
.current_dir(cwd)
@@ -129,7 +129,7 @@ fn resolve_target_dir(
129129
}
130130

131131
fn resolve_target(env: &HashMap<OsString, OsString>, cwd: &PathBuf) -> Result<String> {
132-
let output = cargo()
132+
let output = cargo()?
133133
.env_clear()
134134
.envs(env.iter())
135135
.current_dir(cwd)

src/command.rs

Lines changed: 81 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::path::Path;
77
use std::process::{Command, CommandArgs, CommandEnvs};
88
use std::{env, iter};
99

10-
use anyhow::Context;
10+
use anyhow::{Context, Result};
1111

1212
use crate::CargoCommandExt;
1313
use crate::cargo::{CargoCmd as _, cargo};
@@ -28,10 +28,10 @@ use crate::cargo::{CargoCmd as _, cargo};
2828
///
2929
/// Basic usage:
3030
///
31-
/// ```rust
31+
/// ```rust,no_run
3232
/// use cargo_hyperlight::CargoCommand;
3333
///
34-
/// let mut command = CargoCommand::new();
34+
/// let mut command = CargoCommand::new().unwrap();
3535
/// command.arg("build").arg("--release");
3636
/// command.exec(); // This will replace the current process
3737
/// ```
@@ -41,7 +41,7 @@ use crate::cargo::{CargoCmd as _, cargo};
4141
/// ```rust
4242
/// use cargo_hyperlight::CargoCommand;
4343
///
44-
/// let mut command = CargoCommand::new();
44+
/// let mut command = CargoCommand::new().unwrap();
4545
/// command
4646
/// .current_dir("/path/to/project")
4747
/// .env("CARGO_TARGET_DIR", "/custom/target")
@@ -58,17 +58,11 @@ impl Debug for CargoCommand {
5858
}
5959
}
6060

61-
impl Default for CargoCommand {
62-
fn default() -> Self {
63-
Self::new()
64-
}
65-
}
66-
6761
impl CargoCommand {
6862
/// Constructs a new `CargoCommand` for launching the cargo program.
6963
///
7064
/// The value of the `CARGO` environment variable is used if it is set; otherwise, the
71-
/// default `cargo` from binary `PATH` is used.
65+
/// default `cargo` from the system PATH is used.
7266
/// If `RUSTUP_TOOLCHAIN` is set in the environment, it is also propagated to the
7367
/// child process to ensure correct functioning of the rustup wrappers.
7468
///
@@ -77,34 +71,42 @@ impl CargoCommand {
7771
/// - Inherits the current process's environment
7872
/// - Inherits the current process's working directory
7973
///
74+
/// # Errors
75+
///
76+
/// This function will return an error if:
77+
/// - If the `CARGO` environment variable is set but it specifies an invalid path
78+
/// - If the `CARGO` environment variable is not set and the `cargo` program cannot be found in the system PATH
79+
///
8080
/// # Examples
8181
///
8282
/// Basic usage:
8383
///
8484
/// ```rust
8585
/// use cargo_hyperlight::CargoCommand;
8686
///
87-
/// let command = CargoCommand::new();
87+
/// let command = CargoCommand::new().unwrap();
8888
/// ```
89-
pub fn new() -> Self {
90-
CargoCommand {
91-
command: cargo(),
89+
pub fn new() -> Result<Self> {
90+
Ok(CargoCommand {
91+
command: cargo()?,
9292
clear_env: false,
93-
}
93+
})
9494
}
9595

9696
/// Adds an argument to pass to the cargo program.
9797
///
9898
/// Only one argument can be passed per use. So instead of:
9999
///
100100
/// ```no_run
101-
/// command.arg("-C /path/to/repo");
101+
/// # let mut command = cargo_hyperlight::CargoCommand::new().unwrap();
102+
/// command.arg("--features some_feature");
102103
/// ```
103104
///
104105
/// usage would be:
105106
///
106107
/// ```no_run
107-
/// command.arg("-C").arg("/path/to/repo");
108+
/// # let mut command = cargo_hyperlight::CargoCommand::new().unwrap();
109+
/// command.arg("--features").arg("some_feature");
108110
/// ```
109111
///
110112
/// To pass multiple arguments see [`args`].
@@ -123,9 +125,10 @@ impl CargoCommand {
123125
/// use cargo_hyperlight::CargoCommand;
124126
///
125127
/// CargoCommand::new()
126-
/// .arg("build")
127-
/// .arg("--release")
128-
/// .exec();
128+
/// .unwrap()
129+
/// .arg("build")
130+
/// .arg("--release")
131+
/// .exec();
129132
/// ```
130133
pub fn arg(&mut self, arg: impl AsRef<OsStr>) -> &mut Self {
131134
self.command.arg(arg.as_ref());
@@ -150,16 +153,9 @@ impl CargoCommand {
150153
/// use cargo_hyperlight::CargoCommand;
151154
///
152155
/// CargoCommand::new()
153-
/// .args(["build", "--release"])
154-
/// .exec();
155-
/// ```
156-
///
157-
/// ```no_run
158-
/// use cargo_hyperlight::CargoCommand;
159-
///
160-
/// CargoCommand::new()
161-
/// .args(&["build", "--release"])
162-
/// .exec();
156+
/// .unwrap()
157+
/// .args(["build", "--release"])
158+
/// .exec();
163159
/// ```
164160
pub fn args(&mut self, args: impl IntoIterator<Item = impl AsRef<OsStr>>) -> &mut Self {
165161
self.command.args(args);
@@ -168,14 +164,6 @@ impl CargoCommand {
168164

169165
/// Sets the working directory for the child process.
170166
///
171-
/// # Platform-specific behavior
172-
///
173-
/// If the program path is relative (e.g., `"./script.sh"`), it's ambiguous
174-
/// whether it should be interpreted relative to the parent's working
175-
/// directory or relative to `current_dir`. The behavior in this case is
176-
/// platform specific and unstable, and it's recommended to use
177-
/// [`canonicalize`] to get an absolute program path instead.
178-
///
179167
/// # Examples
180168
///
181169
/// Basic usage:
@@ -184,9 +172,10 @@ impl CargoCommand {
184172
/// use cargo_hyperlight::CargoCommand;
185173
///
186174
/// CargoCommand::new()
187-
/// .current_dir("/bin")
188-
/// .arg("build")
189-
/// .exec();
175+
/// .unwrap()
176+
/// .current_dir("path/to/project")
177+
/// .arg("build")
178+
/// .exec();
190179
/// ```
191180
///
192181
/// [`canonicalize`]: std::fs::canonicalize
@@ -201,9 +190,9 @@ impl CargoCommand {
201190
/// or overwrite a variable if it already exists.
202191
///
203192
/// Child processes will inherit environment variables from their parent process by
204-
/// default (unless [`env_clear`] is used), including variables set with this method.
205-
/// Environment variable mappings added or updated with this method will take
206-
/// precedence over inherited variables.
193+
/// default. Environment variables explicitly set using [`env`] take precedence
194+
/// over inherited variables. You can disable environment variable inheritance entirely
195+
/// using [`env_clear`] or for a single key using [`env_remove`].
207196
///
208197
/// Note that environment variable names are case-insensitive (but
209198
/// case-preserving) on Windows and case-sensitive on all other platforms.
@@ -216,12 +205,15 @@ impl CargoCommand {
216205
/// use cargo_hyperlight::CargoCommand;
217206
///
218207
/// CargoCommand::new()
219-
/// .env("PATH", "/bin")
220-
/// .arg("build")
221-
/// .exec();
208+
/// .unwrap()
209+
/// .env("CARGO_TARGET_DIR", "/path/to/target")
210+
/// .arg("build")
211+
/// .exec();
222212
/// ```
223213
///
214+
/// [`env`]: CargoCommand::env
224215
/// [`env_clear`]: CargoCommand::env_clear
216+
/// [`env_remove`]: CargoCommand::env_remove
225217
pub fn env(&mut self, key: impl AsRef<OsStr>, value: impl AsRef<OsStr>) -> &mut Self {
226218
self.command.env(key, value);
227219
self
@@ -232,6 +224,8 @@ impl CargoCommand {
232224
/// This method will remove all environment variables from the child process,
233225
/// including those that would normally be inherited from the parent process.
234226
/// Environment variables can be added back individually using [`env`].
227+
///
228+
/// If `RUSTUP_TOOLCHAIN` was set in the parent process, it will be preserved.
235229
///
236230
/// # Examples
237231
///
@@ -241,10 +235,11 @@ impl CargoCommand {
241235
/// use cargo_hyperlight::CargoCommand;
242236
///
243237
/// CargoCommand::new()
244-
/// .env_clear()
245-
/// .env("PATH", "/bin")
246-
/// .arg("build")
247-
/// .exec();
238+
/// .unwrap()
239+
/// .env_clear()
240+
/// .env("CARGO_TARGET_DIR", "/path/to/target")
241+
/// .arg("build")
242+
/// .exec();
248243
/// ```
249244
///
250245
/// [`env`]: CargoCommand::env
@@ -280,9 +275,10 @@ impl CargoCommand {
280275
/// use cargo_hyperlight::CargoCommand;
281276
///
282277
/// CargoCommand::new()
283-
/// .env_remove("PATH")
284-
/// .arg("build")
285-
/// .exec();
278+
/// .unwrap()
279+
/// .env_remove("CARGO_TARGET_DIR")
280+
/// .arg("build")
281+
/// .exec();
286282
/// ```
287283
pub fn env_remove(&mut self, key: impl AsRef<OsStr>) -> &mut Self {
288284
self.command.env_remove(key);
@@ -297,9 +293,9 @@ impl CargoCommand {
297293
/// implementing `IntoIterator` with the appropriate item type.
298294
///
299295
/// Child processes will inherit environment variables from their parent process by
300-
/// default (unless [`env_clear`] is used), including variables set with this method.
301-
/// Environment variable mappings added or updated with this method will take
302-
/// precedence over inherited variables.
296+
/// default. Environment variables explicitly set using [`env`] take precedence
297+
/// over inherited variables. You can disable environment variable inheritance entirely
298+
/// using [`env_clear`] or for a single key using [`env_remove`].
303299
///
304300
/// Note that environment variable names are case-insensitive (but
305301
/// case-preserving) on Windows and case-sensitive on all other platforms.
@@ -313,25 +309,32 @@ impl CargoCommand {
313309
/// use cargo_hyperlight::CargoCommand;
314310
///
315311
/// let mut envs = HashMap::new();
316-
/// envs.insert("PATH", "/bin");
317-
/// envs.insert("CARGO_HOME", "/tmp/cargo");
312+
/// envs.insert("CARGO_TARGET_DIR", "/path/to/target");
313+
/// envs.insert("CARGO_HOME", "/path/to/.cargo");
318314
///
319315
/// CargoCommand::new()
320-
/// .envs(&envs)
321-
/// .arg("build")
322-
/// .exec();
316+
/// .unwrap()
317+
/// .envs(&envs)
318+
/// .arg("build")
319+
/// .exec();
323320
/// ```
324321
///
325322
/// ```no_run
326323
/// use cargo_hyperlight::CargoCommand;
327324
///
328325
/// CargoCommand::new()
329-
/// .envs([("PATH", "/bin"), ("CARGO_HOME", "/tmp/cargo")])
330-
/// .arg("build")
331-
/// .exec();
326+
/// .unwrap()
327+
/// .envs([
328+
/// ("CARGO_TARGET_DIR", "/path/to/target"),
329+
/// ("CARGO_HOME", "/path/to/.cargo"),
330+
/// ])
331+
/// .arg("build")
332+
/// .exec();
332333
/// ```
333334
///
335+
/// [`env`]: CargoCommand::env
334336
/// [`env_clear`]: CargoCommand::env_clear
337+
/// [`env_remove`]: CargoCommand::env_remove
335338
pub fn envs(
336339
&mut self,
337340
envs: impl IntoIterator<Item = (impl AsRef<OsStr>, impl AsRef<OsStr>)>,
@@ -350,7 +353,7 @@ impl CargoCommand {
350353
/// ```no_run
351354
/// use cargo_hyperlight::CargoCommand;
352355
///
353-
/// let mut command = CargoCommand::new();
356+
/// let mut command = CargoCommand::new().unwrap();
354357
/// command.arg("build").arg("--release");
355358
///
356359
/// let args: Vec<&std::ffi::OsStr> = command.get_args().collect();
@@ -373,11 +376,11 @@ impl CargoCommand {
373376
/// use std::path::Path;
374377
/// use cargo_hyperlight::CargoCommand;
375378
///
376-
/// let mut command = CargoCommand::new();
379+
/// let mut command = CargoCommand::new().unwrap();
377380
/// assert_eq!(command.get_current_dir(), None);
378381
///
379-
/// command.current_dir("/bin");
380-
/// assert_eq!(command.get_current_dir(), Some(Path::new("/bin")));
382+
/// command.current_dir("/tmp");
383+
/// assert_eq!(command.get_current_dir(), Some(Path::new("/tmp")));
381384
/// ```
382385
pub fn get_current_dir(&self) -> Option<&Path> {
383386
self.command.get_current_dir()
@@ -400,9 +403,9 @@ impl CargoCommand {
400403
/// use std::ffi::OsStr;
401404
/// use cargo_hyperlight::CargoCommand;
402405
///
403-
/// let mut command = CargoCommand::new();
404-
/// command.env("CARGO_HOME", "/tmp/cargo");
405-
/// command.env_remove("PATH");
406+
/// let mut command = CargoCommand::new().unwrap();
407+
/// command.env("CARGO_HOME", "/path/to/.cargo");
408+
/// command.env_remove("CARGO_TARGET_DIR");
406409
///
407410
/// for (key, value) in command.get_envs() {
408411
/// println!("{key:?} => {value:?}");
@@ -444,8 +447,8 @@ impl CargoCommand {
444447
/// ```no_run
445448
/// use cargo_hyperlight::CargoCommand;
446449
///
447-
/// let command = CargoCommand::new();
448-
/// println!("Program: {}", command.get_program().to_string_lossy());
450+
/// let command = CargoCommand::new().unwrap();
451+
/// println!("Program: {:?}", command.get_program());
449452
/// ```
450453
pub fn get_program(&self) -> &OsStr {
451454
self.command.get_program()
@@ -463,7 +466,7 @@ impl CargoCommand {
463466
/// Executes a cargo command as a child process, waiting for it to finish and
464467
/// collecting its exit status.
465468
///
466-
/// By default, stdin, stdout and stderr are inherited from the parent.
469+
/// The process stdin, stdout and stderr are inherited from the parent.
467470
///
468471
/// # Examples
469472
///
@@ -473,6 +476,7 @@ impl CargoCommand {
473476
/// use cargo_hyperlight::CargoCommand;
474477
///
475478
/// let result = CargoCommand::new()
479+
/// .unwrap()
476480
/// .arg("build")
477481
/// .status();
478482
///
@@ -510,6 +514,7 @@ impl CargoCommand {
510514
/// use cargo_hyperlight::CargoCommand;
511515
///
512516
/// CargoCommand::new()
517+
/// .unwrap()
513518
/// .arg("build")
514519
/// .exec(); // This will never return
515520
/// ```

0 commit comments

Comments
 (0)