11use crate :: command_executor:: CommandExecutor ;
2+ use anyhow:: { anyhow, bail, Context , Result } ;
23use regex:: Regex ;
34use std:: {
45 collections:: hash_map:: DefaultHasher ,
@@ -11,10 +12,11 @@ pub fn versioned_gem_home(
1112 base_dir : & Path ,
1213 envs : & [ ( & str , & str ) ] ,
1314 executor : & dyn CommandExecutor ,
14- ) -> Result < PathBuf , String > {
15+ ) -> Result < PathBuf > {
1516 let output = executor
1617 . execute ( "ruby" , & [ "--version" ] , envs)
17- . map_err ( |e| format ! ( "Failed to detect Ruby version: {e}" ) ) ?;
18+ . map_err ( |e| anyhow:: anyhow!( e) )
19+ . context ( "Failed to detect Ruby version" ) ?;
1820
1921 match output. status {
2022 Some ( 0 ) => {
@@ -24,8 +26,8 @@ pub fn versioned_gem_home(
2426 let version_hash = format ! ( "{:x}" , hasher. finish( ) ) ;
2527 Ok ( base_dir. join ( "gems" ) . join ( version_hash) )
2628 }
27- Some ( status) => Err ( format ! ( "Ruby version check failed with status {status}" ) ) ,
28- None => Err ( "Failed to execute ruby --version" . to_string ( ) ) ,
29+ Some ( status) => bail ! ( "Ruby version check failed with status {status}" ) ,
30+ None => bail ! ( "Failed to execute ruby --version" ) ,
2931 }
3032}
3133
@@ -56,12 +58,12 @@ impl Gemset {
5658 }
5759
5860 /// Returns the full path to a gem binary executable.
59- pub fn gem_bin_path ( & self , bin_name : & str ) -> Result < String , String > {
61+ pub fn gem_bin_path ( & self , bin_name : & str ) -> Result < String > {
6062 let path = self . gem_home . join ( "bin" ) . join ( bin_name) ;
6163
6264 path. to_str ( )
6365 . map ( ToString :: to_string)
64- . ok_or_else ( || format ! ( "Failed to convert path for '{bin_name}'" ) )
66+ . with_context ( || format ! ( "Failed to convert path for '{bin_name}'" ) )
6567 }
6668
6769 pub fn env ( & self ) -> & [ ( String , String ) ] {
@@ -101,7 +103,7 @@ impl Gemset {
101103 } )
102104 }
103105
104- pub fn install_gem ( & self , name : & str ) -> Result < ( ) , String > {
106+ pub fn install_gem ( & self , name : & str ) -> Result < ( ) > {
105107 let args = & [
106108 "--no-user-install" ,
107109 "--no-format-executable" ,
@@ -110,26 +112,26 @@ impl Gemset {
110112 ] ;
111113
112114 self . execute_gem_command ( "install" , args)
113- . map_err ( |e | format ! ( "Failed to install gem '{name}': {e} " ) ) ?;
115+ . with_context ( | | format ! ( "Failed to install gem '{name}'" ) ) ?;
114116
115117 Ok ( ( ) )
116118 }
117119
118- pub fn update_gem ( & self , name : & str ) -> Result < ( ) , String > {
120+ pub fn update_gem ( & self , name : & str ) -> Result < ( ) > {
119121 self . execute_gem_command ( "update" , & [ name] )
120- . map_err ( |e | format ! ( "Failed to update gem '{name}': {e} " ) ) ?;
122+ . with_context ( | | format ! ( "Failed to update gem '{name}'" ) ) ?;
121123 Ok ( ( ) )
122124 }
123125
124- pub fn uninstall_gem ( & self , name : & str , version : & str ) -> Result < ( ) , String > {
126+ pub fn uninstall_gem ( & self , name : & str , version : & str ) -> Result < ( ) > {
125127 let args = & [ name, "--version" , version] ;
126128 self . execute_gem_command ( "uninstall" , args)
127- . map_err ( |e | format ! ( "Failed to uninstall gem '{name}': {e }" ) ) ?;
129+ . with_context ( | | format ! ( "Failed to uninstall gem '{name}' version {version }" ) ) ?;
128130
129131 Ok ( ( ) )
130132 }
131133
132- pub fn installed_gem_version ( & self , name : & str ) -> Result < Option < String > , String > {
134+ pub fn installed_gem_version ( & self , name : & str ) -> Result < Option < String > > {
133135 static GEM_VERSION_REGEX : LazyLock < Regex > =
134136 LazyLock :: new ( || Regex :: new ( r"^(\S+) \((.+)\)$" ) . unwrap ( ) ) ;
135137
@@ -152,23 +154,23 @@ impl Gemset {
152154 Ok ( None )
153155 }
154156
155- pub fn is_outdated_gem ( & self , name : & str ) -> Result < bool , String > {
157+ pub fn is_outdated_gem ( & self , name : & str ) -> Result < bool > {
156158 self . execute_gem_command ( "outdated" , & [ ] ) . map ( |output| {
157159 output
158160 . lines ( )
159161 . any ( |line| line. split_whitespace ( ) . next ( ) . is_some_and ( |n| n == name) )
160162 } )
161163 }
162164
163- fn execute_gem_command ( & self , cmd : & str , args : & [ & str ] ) -> Result < String , String > {
165+ fn execute_gem_command ( & self , cmd : & str , args : & [ & str ] ) -> Result < String > {
164166 let full_args: Vec < & str > = std:: iter:: once ( cmd)
165167 . chain ( std:: iter:: once ( "--norc" ) )
166168 . chain ( args. iter ( ) . copied ( ) )
167169 . collect ( ) ;
168170 let gem_home_str = self
169171 . gem_home
170172 . to_str ( )
171- . ok_or ( "Failed to convert gem_home path to string" ) ?;
173+ . context ( "Failed to convert gem_home path to string" ) ?;
172174
173175 let command_envs = vec ! [ ( "GEM_HOME" , gem_home_str) ] ;
174176
@@ -177,21 +179,22 @@ impl Gemset {
177179 . chain ( self . envs . iter ( ) . map ( |( k, v) | ( k. as_str ( ) , v. as_str ( ) ) ) )
178180 . collect ( ) ;
179181
180- self . command_executor
182+ let output = self
183+ . command_executor
181184 . execute ( "gem" , & full_args, & merged_envs)
182- . and_then ( |output| match output . status {
183- Some ( 0 ) => Ok ( String :: from_utf8_lossy ( & output . stdout ) . into_owned ( ) ) ,
184- Some ( status) => {
185- let stderr = String :: from_utf8_lossy ( & output. stderr ) ;
186- Err ( format ! (
187- "Gem command failed (status: {status}) \n Error: { stderr}" ,
188- ) )
189- }
190- None => {
191- let stderr = String :: from_utf8_lossy ( & output. stderr ) ;
192- Err ( format ! ( "Failed to execute gem command: {stderr}" ) )
193- }
194- } )
185+ . map_err ( |e| anyhow ! ( e ) ) ? ;
186+
187+ match output . status {
188+ Some ( 0 ) => Ok ( String :: from_utf8_lossy ( & output. stdout ) . into_owned ( ) ) ,
189+ Some ( status ) => {
190+ let stderr = String :: from_utf8_lossy ( & output . stderr ) ;
191+ bail ! ( "Gem command failed (status: {status}) \n Error: {stderr}" )
192+ }
193+ None => {
194+ let stderr = String :: from_utf8_lossy ( & output. stderr ) ;
195+ bail ! ( "Failed to execute gem command: {stderr}" )
196+ }
197+ }
195198 }
196199}
197200
@@ -396,9 +399,8 @@ mod tests {
396399
397400 let result = versioned_gem_home ( Path :: new ( "/extension" ) , & [ ] , & executor) ;
398401 assert ! ( result. is_err( ) ) ;
399- assert ! ( result
400- . expect_err( "should return error" )
401- . contains( "Ruby version check failed with status 127" ) ) ;
402+ let error_message = format ! ( "{:#}" , result. expect_err( "should return error" ) ) ;
403+ assert ! ( error_message. contains( "Ruby version check failed with status 127" ) ) ;
402404 }
403405
404406 #[ test]
@@ -413,9 +415,8 @@ mod tests {
413415
414416 let result = versioned_gem_home ( Path :: new ( "/extension" ) , & [ ] , & executor) ;
415417 assert ! ( result. is_err( ) ) ;
416- assert ! ( result
417- . expect_err( "should return error" )
418- . contains( "Failed to detect Ruby version" ) ) ;
418+ let error_message = format ! ( "{:#}" , result. expect_err( "should return error" ) ) ;
419+ assert ! ( error_message. contains( "Failed to detect Ruby version" ) ) ;
419420 }
420421
421422 #[ test]
@@ -534,6 +535,7 @@ mod tests {
534535 assert ! ( result. is_err( ) ) ;
535536 assert ! ( result
536537 . unwrap_err( )
538+ . to_string( )
537539 . contains( "Failed to install gem 'ruby-lsp'" ) ) ;
538540 }
539541
@@ -574,6 +576,7 @@ mod tests {
574576 assert ! ( result. is_err( ) ) ;
575577 assert ! ( result
576578 . unwrap_err( )
579+ . to_string( )
577580 . contains( "Failed to update gem 'ruby-lsp'" ) ) ;
578581 }
579582
@@ -667,6 +670,7 @@ mod tests {
667670 assert ! ( result. is_err( ) ) ;
668671 assert ! ( result
669672 . unwrap_err( )
673+ . to_string( )
670674 . contains( "Gem command failed (status: 127)" ) ) ;
671675 }
672676
@@ -734,6 +738,7 @@ mod tests {
734738 assert ! ( result. is_err( ) ) ;
735739 assert ! ( result
736740 . unwrap_err( )
741+ . to_string( )
737742 . contains( "Gem command failed (status: 1)" ) ) ;
738743 }
739744
@@ -782,6 +787,7 @@ mod tests {
782787 assert ! ( result. is_err( ) ) ;
783788 assert ! ( result
784789 . unwrap_err( )
790+ . to_string( )
785791 . contains( "Failed to uninstall gem 'solargraph'" ) ) ;
786792 }
787793
@@ -800,7 +806,7 @@ mod tests {
800806 let gemset = create_gemset ( None , mock_executor) ;
801807 let result = gemset. uninstall_gem ( gem_name, gem_version) ;
802808 assert ! ( result. is_err( ) ) ;
803- let error_message = result. unwrap_err ( ) ;
809+ let error_message = format ! ( "{:#}" , result. unwrap_err( ) ) ;
804810 assert ! ( error_message. contains( "Failed to uninstall gem 'solargraph'" ) ) ;
805811 assert ! ( error_message. contains( "Command not found: gem" ) ) ;
806812 }
0 commit comments