11// IO error
22// A wrapper around the tokio IO functions that adds the path to the error message, instead of the uninformative std::io::Error.
33
4+ use eyre:: { Context , ContextCompat , Result , eyre} ;
45use std:: {
56 io:: { ErrorKind , Write } ,
67 path:: Path ,
@@ -181,17 +182,34 @@ fn sync_write(
181182 std:: io:: Result :: Ok ( ( ) )
182183}
183184
184- pub fn is_same_disk ( old_dir : & Path , new_dir : & Path ) -> Result < bool , IOError > {
185+ pub fn is_same_disk ( old_dir : & Path , new_dir : & Path ) -> Result < bool > {
185186 #[ cfg( unix) ]
186187 {
187188 use std:: os:: unix:: fs:: MetadataExt ;
188- Ok ( old_dir. metadata ( ) ?. dev ( ) == new_dir. metadata ( ) ?. dev ( ) )
189+
190+ use eyre:: eyre;
191+
192+ // we need to use `symlink_metadata` instead of `metadata`, because
193+ // if this file is a symlink, we need to query the symlink file itself,
194+ // rather than the target.
195+ // downloaded JREs use symlinks to point to certain stuff like LICENSE
196+ // files.
197+ // this fixes moving JRE dirs.
198+
199+ let old_meta = std:: fs:: symlink_metadata ( old_dir)
200+ . wrap_err_with ( || eyre ! ( "getting meta of old dir {old_dir:?}" ) ) ?;
201+ let new_meta = std:: fs:: symlink_metadata ( new_dir)
202+ . wrap_err_with ( || eyre ! ( "getting meta of new dir {new_dir:?}" ) ) ?;
203+
204+ Ok ( old_meta. dev ( ) == new_meta. dev ( ) )
189205 }
190206
191207 #[ cfg( windows) ]
192208 {
193- let old_dir = canonicalize ( old_dir) ?;
194- let new_dir = canonicalize ( new_dir) ?;
209+ let old_dir = canonicalize ( old_dir)
210+ . wrap_err_with ( || eyre ! ( "canonicalizing {old_dir:?}" ) ) ?;
211+ let new_dir = canonicalize ( new_dir)
212+ . wrap_err_with ( || eyre ! ( "canonicalizing {new_dir:?}" ) ) ?;
195213
196214 let old_component = old_dir. components ( ) . next ( ) ;
197215 let new_component = new_dir. components ( ) . next ( ) ;
@@ -209,39 +227,62 @@ pub fn is_same_disk(old_dir: &Path, new_dir: &Path) -> Result<bool, IOError> {
209227pub async fn rename_or_move (
210228 from : impl AsRef < std:: path:: Path > ,
211229 to : impl AsRef < std:: path:: Path > ,
212- ) -> Result < ( ) , IOError > {
230+ ) -> Result < ( ) > {
213231 let from = from. as_ref ( ) ;
214232 let to = to. as_ref ( ) ;
215233
216- if to
234+ let to_parent = to
217235 . parent ( )
218- . map_or ( Ok ( false ) , |to_dir| is_same_disk ( from, to_dir) ) ?
219- {
236+ . wrap_err_with ( || eyre ! ( "getting parent of `to` dir {to:?}" ) ) ?;
237+ let same_disk = is_same_disk ( from, to_parent) . wrap_err_with ( || {
238+ eyre ! ( "checking if `to_parent` ({to_parent:?}) and `from` ({from:?}) are on the same disk" )
239+ } ) ?;
240+
241+ if same_disk {
220242 tokio:: fs:: rename ( from, to)
221243 . await
222244 . map_err ( |e| IOError :: IOPathError {
223245 source : e,
224246 path : from. to_string_lossy ( ) . to_string ( ) ,
225247 } )
248+ . wrap_err_with ( || eyre ! ( "moving {from:?} to {to:?} on same disk" ) )
226249 } else {
227- move_recursive ( from, to) . await
250+ move_recursive ( from, to) . await . with_context ( || {
251+ eyre ! ( "moving {from:?} to {to:?} on different disks" )
252+ } )
228253 }
229254}
230255
231256#[ async_recursion:: async_recursion]
232- async fn move_recursive ( from : & Path , to : & Path ) -> Result < ( ) , IOError > {
257+ async fn move_recursive ( from : & Path , to : & Path ) -> Result < ( ) > {
233258 if from. is_file ( ) {
234- copy ( from, to) . await ?;
235- remove_file ( from) . await ?;
259+ copy ( from, to)
260+ . await
261+ . wrap_err_with ( || eyre ! ( "copying {from:?} to {to:?}" ) ) ?;
262+ remove_file ( from) . await . wrap_err_with ( || {
263+ eyre ! ( "removing {from:?} after copying to {to:?}" )
264+ } ) ?;
236265 return Ok ( ( ) ) ;
237266 }
238267
239- create_dir ( to) . await ?;
268+ create_dir ( to)
269+ . await
270+ . wrap_err_with ( || eyre ! ( "creating dir for {to:?}" ) ) ?;
240271
241- let mut dir = read_dir ( from) . await ?;
242- while let Some ( entry) = dir. next_entry ( ) . await ? {
272+ let mut dir = read_dir ( from)
273+ . await
274+ . wrap_err_with ( || eyre ! ( "reading dir {from:?}" ) ) ?;
275+ while let Some ( entry) = dir
276+ . next_entry ( )
277+ . await
278+ . wrap_err_with ( || eyre ! ( "reading dir entry in {from:?}" ) ) ?
279+ {
243280 let new_path = to. join ( entry. file_name ( ) ) ;
244- move_recursive ( & entry. path ( ) , & new_path) . await ?;
281+ move_recursive ( & entry. path ( ) , & new_path)
282+ . await
283+ . with_context ( || {
284+ eyre ! ( "moving {:?} to {new_path:?}" , entry. path( ) )
285+ } ) ?;
245286 }
246287
247288 Ok ( ( ) )
0 commit comments