@@ -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.
248270fn get_entrypoints (
249271 from : & PackageName ,
0 commit comments