Mercurial > hg
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()?; |