Skip to content

Commit d866c58

Browse files
authored
Refactor uv tool run hint into separate function (#11069)
1 parent 3af3af5 commit d866c58

File tree

1 file changed

+63
-41
lines changed
  • crates/uv/src/commands/tool

1 file changed

+63
-41
lines changed

crates/uv/src/commands/tool/run.rs

Lines changed: 63 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -193,47 +193,14 @@ pub(crate) async fn run(
193193
let handle = match process.spawn() {
194194
Ok(handle) => Ok(handle),
195195
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
196-
match get_entrypoints(&from.name, &site_packages) {
197-
Ok(entrypoints) => {
198-
writeln!(
199-
printer.stdout(),
200-
"The executable `{}` was not found.",
201-
executable.cyan(),
202-
)?;
203-
if entrypoints.is_empty() {
204-
warn_user!(
205-
"Package `{}` does not provide any executables.",
206-
from.name.red()
207-
);
208-
} else {
209-
warn_user!(
210-
"An executable named `{}` is not provided by package `{}`.",
211-
executable.cyan(),
212-
from.name.red()
213-
);
214-
writeln!(
215-
printer.stdout(),
216-
"The following executables are provided by `{}`:",
217-
from.name.green()
218-
)?;
219-
for (name, _) in entrypoints {
220-
writeln!(printer.stdout(), "- {}", name.cyan())?;
221-
}
222-
let suggested_command = format!(
223-
"{} --from {} <EXECUTABLE_NAME>",
224-
invocation_source, from.name
225-
);
226-
writeln!(
227-
printer.stdout(),
228-
"Consider using `{}` instead.",
229-
suggested_command.green()
230-
)?;
231-
}
232-
return Ok(ExitStatus::Failure);
233-
}
234-
Err(err) => {
235-
warn!("Failed to get entrypoints for `{from}`: {err}");
236-
}
196+
if let Some(exit_status) = hint_on_not_found(
197+
executable,
198+
&from,
199+
&site_packages,
200+
invocation_source,
201+
printer,
202+
)? {
203+
return Ok(exit_status);
237204
}
238205
Err(err)
239206
}
@@ -244,6 +211,61 @@ pub(crate) async fn run(
244211
run_to_completion(handle).await
245212
}
246213

214+
/// Show a hint when a command fails due to a missing executable.
215+
///
216+
/// Returns an exit status if the caller should exit after hinting.
217+
fn hint_on_not_found(
218+
executable: &str,
219+
from: &Requirement,
220+
site_packages: &SitePackages,
221+
invocation_source: ToolRunCommand,
222+
printer: Printer,
223+
) -> anyhow::Result<Option<ExitStatus>> {
224+
match get_entrypoints(&from.name, site_packages) {
225+
Ok(entrypoints) => {
226+
writeln!(
227+
printer.stdout(),
228+
"The executable `{}` was not found.",
229+
executable.cyan(),
230+
)?;
231+
if entrypoints.is_empty() {
232+
warn_user!(
233+
"Package `{}` does not provide any executables.",
234+
from.name.red()
235+
);
236+
} else {
237+
warn_user!(
238+
"An executable named `{}` is not provided by package `{}`.",
239+
executable.cyan(),
240+
from.name.red()
241+
);
242+
writeln!(
243+
printer.stdout(),
244+
"The following executables are provided by `{}`:",
245+
from.name.green()
246+
)?;
247+
for (name, _) in entrypoints {
248+
writeln!(printer.stdout(), "- {}", name.cyan())?;
249+
}
250+
let suggested_command = format!(
251+
"{} --from {} <EXECUTABLE_NAME>",
252+
invocation_source, from.name
253+
);
254+
writeln!(
255+
printer.stdout(),
256+
"Consider using `{}` instead.",
257+
suggested_command.green()
258+
)?;
259+
}
260+
Ok(Some(ExitStatus::Failure))
261+
}
262+
Err(err) => {
263+
warn!("Failed to get entrypoints for `{from}`: {err}");
264+
Ok(None)
265+
}
266+
}
267+
}
268+
247269
/// Return the entry points for the specified package.
248270
fn get_entrypoints(
249271
from: &PackageName,

0 commit comments

Comments
 (0)