##// END OF EJS Templates
rhg: fix race when an ambiguous file is deleted on disk...
Raphaël Gomès -
r51121:8fcd5302 stable
parent child Browse files
Show More
@@ -299,25 +299,45 b' pub fn run(invocation: &crate::CliInvoca'
299 .unsure
299 .unsure
300 .into_par_iter()
300 .into_par_iter()
301 .map(|to_check| {
301 .map(|to_check| {
302 unsure_is_modified(
302 // The compiler seems to get a bit confused with complex
303 // inference when using a parallel iterator + map
304 // + map_err + collect, so let's just inline some of the
305 // logic.
306 match unsure_is_modified(
303 working_directory_vfs,
307 working_directory_vfs,
304 store_vfs,
308 store_vfs,
305 &manifest,
309 &manifest,
306 &to_check.path,
310 &to_check.path,
307 )
311 ) {
308 .map(|modified| (to_check, modified))
312 Err(HgError::IoError { .. }) => {
313 // IO errors most likely stem from the file being
314 // deleted even though we know it's in the
315 // dirstate.
316 Ok((to_check, UnsureOutcome::Deleted))
317 }
318 Ok(outcome) => Ok((to_check, outcome)),
319 Err(e) => Err(e),
320 }
309 })
321 })
310 .collect::<Result<_, _>>()?;
322 .collect::<Result<_, _>>()?;
311 for (status_path, is_modified) in res.into_iter() {
323 for (status_path, outcome) in res.into_iter() {
312 if is_modified {
324 match outcome {
313 if display_states.modified {
325 UnsureOutcome::Clean => {
314 ds_status.modified.push(status_path);
326 if display_states.clean {
327 ds_status.clean.push(status_path.clone());
328 }
329 fixup.push(status_path.path.into_owned())
315 }
330 }
316 } else {
331 UnsureOutcome::Modified => {
317 if display_states.clean {
332 if display_states.modified {
318 ds_status.clean.push(status_path.clone());
333 ds_status.modified.push(status_path);
334 }
319 }
335 }
320 fixup.push(status_path.path.into_owned())
336 UnsureOutcome::Deleted => {
337 if display_states.deleted {
338 ds_status.deleted.push(status_path);
339 }
340 }
321 }
341 }
322 }
342 }
323 }
343 }
@@ -557,6 +577,16 b" impl DisplayStatusPaths<'_> {"
557 }
577 }
558 }
578 }
559
579
580 /// Outcome of the additional check for an ambiguous tracked file
581 enum UnsureOutcome {
582 /// The file is actually clean
583 Clean,
584 /// The file has been modified
585 Modified,
586 /// The file was deleted on disk (or became another type of fs entry)
587 Deleted,
588 }
589
560 /// Check if a file is modified by comparing actual repo store and file system.
590 /// Check if a file is modified by comparing actual repo store and file system.
561 ///
591 ///
562 /// This meant to be used for those that the dirstate cannot resolve, due
592 /// This meant to be used for those that the dirstate cannot resolve, due
@@ -566,7 +596,7 b' fn unsure_is_modified('
566 store_vfs: hg::vfs::Vfs,
596 store_vfs: hg::vfs::Vfs,
567 manifest: &Manifest,
597 manifest: &Manifest,
568 hg_path: &HgPath,
598 hg_path: &HgPath,
569 ) -> Result<bool, HgError> {
599 ) -> Result<UnsureOutcome, HgError> {
570 let vfs = working_directory_vfs;
600 let vfs = working_directory_vfs;
571 let fs_path = hg_path_to_path_buf(hg_path).expect("HgPath conversion");
601 let fs_path = hg_path_to_path_buf(hg_path).expect("HgPath conversion");
572 let fs_metadata = vfs.symlink_metadata(&fs_path)?;
602 let fs_metadata = vfs.symlink_metadata(&fs_path)?;
@@ -585,7 +615,7 b' fn unsure_is_modified('
585 .find_by_path(hg_path)?
615 .find_by_path(hg_path)?
586 .expect("ambgious file not in p1");
616 .expect("ambgious file not in p1");
587 if entry.flags != fs_flags {
617 if entry.flags != fs_flags {
588 return Ok(true);
618 return Ok(UnsureOutcome::Modified);
589 }
619 }
590 let filelog = hg::filelog::Filelog::open_vfs(&store_vfs, hg_path)?;
620 let filelog = hg::filelog::Filelog::open_vfs(&store_vfs, hg_path)?;
591 let fs_len = fs_metadata.len();
621 let fs_len = fs_metadata.len();
@@ -599,7 +629,7 b' fn unsure_is_modified('
599 if filelog_entry.file_data_len_not_equal_to(fs_len) {
629 if filelog_entry.file_data_len_not_equal_to(fs_len) {
600 // No need to read file contents:
630 // No need to read file contents:
601 // it cannot be equal if it has a different length.
631 // it cannot be equal if it has a different length.
602 return Ok(true);
632 return Ok(UnsureOutcome::Modified);
603 }
633 }
604
634
605 let p1_filelog_data = filelog_entry.data()?;
635 let p1_filelog_data = filelog_entry.data()?;
@@ -607,7 +637,7 b' fn unsure_is_modified('
607 if p1_contents.len() as u64 != fs_len {
637 if p1_contents.len() as u64 != fs_len {
608 // No need to read file contents:
638 // No need to read file contents:
609 // it cannot be equal if it has a different length.
639 // it cannot be equal if it has a different length.
610 return Ok(true);
640 return Ok(UnsureOutcome::Modified);
611 }
641 }
612
642
613 let fs_contents = if is_symlink {
643 let fs_contents = if is_symlink {
@@ -615,7 +645,12 b' fn unsure_is_modified('
615 } else {
645 } else {
616 vfs.read(fs_path)?
646 vfs.read(fs_path)?
617 };
647 };
618 Ok(p1_contents != &*fs_contents)
648
649 Ok(if p1_contents != &*fs_contents {
650 UnsureOutcome::Modified
651 } else {
652 UnsureOutcome::Clean
653 })
619 }
654 }
620
655
621 fn print_pattern_file_warning(
656 fn print_pattern_file_warning(
General Comments 0
You need to be logged in to leave comments. Login now