comparison rust/rhg/src/commands/status.rs @ 49894:678588b01af1

rhg: implement checkexec to support weird filesystems In particular, some of our repos are stored on a fileserver that simulates POSIX permissions poorly, in such a way that prevents the removal of execute permission. This causes rhg show a spurious unclean status, even though python hg reports the repo as clean. We fix this by making rhg implement the ~same checkexec logic that python hg does.
author Arseniy Alekseyev <aalekseyev@janestreet.com>
date Thu, 05 Jan 2023 17:15:03 +0000
parents 37bc3edef76f
children 58074252db3c
comparison
equal deleted inserted replaced
49893:5f664401dd03 49894:678588b01af1
252 }; 252 };
253 } 253 }
254 254
255 let mut dmap = repo.dirstate_map_mut()?; 255 let mut dmap = repo.dirstate_map_mut()?;
256 256
257 let check_exec = hg::checkexec::check_exec(repo.working_directory_path());
258
257 let options = StatusOptions { 259 let options = StatusOptions {
258 // we're currently supporting file systems with exec flags only 260 check_exec,
259 // anyway
260 check_exec: true,
261 list_clean: display_states.clean, 261 list_clean: display_states.clean,
262 list_unknown: display_states.unknown, 262 list_unknown: display_states.unknown,
263 list_ignored: display_states.ignored, 263 list_ignored: display_states.ignored,
264 list_copies, 264 list_copies,
265 collect_traversed_dirs: false, 265 collect_traversed_dirs: false,
310 .into_par_iter() 310 .into_par_iter()
311 .map(|to_check| { 311 .map(|to_check| {
312 unsure_is_modified( 312 unsure_is_modified(
313 working_directory_vfs, 313 working_directory_vfs,
314 store_vfs, 314 store_vfs,
315 check_exec,
315 &manifest, 316 &manifest,
316 &to_check.path, 317 &to_check.path,
317 ) 318 )
318 .map(|modified| (to_check, modified)) 319 .map(|modified| (to_check, modified))
319 }) 320 })
552 /// This meant to be used for those that the dirstate cannot resolve, due 553 /// This meant to be used for those that the dirstate cannot resolve, due
553 /// to time resolution limits. 554 /// to time resolution limits.
554 fn unsure_is_modified( 555 fn unsure_is_modified(
555 working_directory_vfs: hg::vfs::Vfs, 556 working_directory_vfs: hg::vfs::Vfs,
556 store_vfs: hg::vfs::Vfs, 557 store_vfs: hg::vfs::Vfs,
558 check_exec: bool,
557 manifest: &Manifest, 559 manifest: &Manifest,
558 hg_path: &HgPath, 560 hg_path: &HgPath,
559 ) -> Result<bool, HgError> { 561 ) -> Result<bool, HgError> {
560 let vfs = working_directory_vfs; 562 let vfs = working_directory_vfs;
561 let fs_path = hg_path_to_path_buf(hg_path).expect("HgPath conversion"); 563 let fs_path = hg_path_to_path_buf(hg_path).expect("HgPath conversion");
562 let fs_metadata = vfs.symlink_metadata(&fs_path)?; 564 let fs_metadata = vfs.symlink_metadata(&fs_path)?;
563 let is_symlink = fs_metadata.file_type().is_symlink(); 565 let is_symlink = fs_metadata.file_type().is_symlink();
566
567 let entry = manifest
568 .find_by_path(hg_path)?
569 .expect("ambgious file not in p1");
570
564 // TODO: Also account for `FALLBACK_SYMLINK` and `FALLBACK_EXEC` from the 571 // TODO: Also account for `FALLBACK_SYMLINK` and `FALLBACK_EXEC` from the
565 // dirstate 572 // dirstate
566 let fs_flags = if is_symlink { 573 let fs_flags = if is_symlink {
567 Some(b'l') 574 Some(b'l')
568 } else if has_exec_bit(&fs_metadata) { 575 } else if check_exec && has_exec_bit(&fs_metadata) {
569 Some(b'x') 576 Some(b'x')
570 } else { 577 } else {
571 None 578 None
572 }; 579 };
573 580
574 let entry = manifest 581 let entry_flags = if check_exec {
575 .find_by_path(hg_path)? 582 entry.flags
576 .expect("ambgious file not in p1"); 583 } else {
577 if entry.flags != fs_flags { 584 if entry.flags == Some(b'x') {
585 None
586 } else {
587 entry.flags
588 }
589 };
590
591 if entry_flags != fs_flags {
578 return Ok(true); 592 return Ok(true);
579 } 593 }
580 let filelog = hg::filelog::Filelog::open_vfs(&store_vfs, hg_path)?; 594 let filelog = hg::filelog::Filelog::open_vfs(&store_vfs, hg_path)?;
581 let fs_len = fs_metadata.len(); 595 let fs_len = fs_metadata.len();
582 let file_node = entry.node_id()?; 596 let file_node = entry.node_id()?;