rust/rhg/src/commands/status.rs
changeset 48345 d5a91701f7dc
parent 48344 b6d8eea9872c
child 48349 c12ed33558cb
equal deleted inserted replaced
48344:b6d8eea9872c 48345:d5a91701f7dc
     9 use crate::ui::{Ui, UiError};
     9 use crate::ui::{Ui, UiError};
    10 use crate::utils::path_utils::relativize_paths;
    10 use crate::utils::path_utils::relativize_paths;
    11 use clap::{Arg, SubCommand};
    11 use clap::{Arg, SubCommand};
    12 use hg;
    12 use hg;
    13 use hg::config::Config;
    13 use hg::config::Config;
    14 use hg::dirstate::TruncatedTimestamp;
    14 use hg::dirstate::{has_exec_bit, TruncatedTimestamp};
    15 use hg::errors::HgError;
    15 use hg::errors::HgError;
    16 use hg::manifest::Manifest;
    16 use hg::manifest::Manifest;
    17 use hg::matchers::AlwaysMatcher;
    17 use hg::matchers::AlwaysMatcher;
    18 use hg::repo::Repo;
    18 use hg::repo::Repo;
       
    19 use hg::utils::files::get_bytes_from_os_string;
    19 use hg::utils::hg_path::{hg_path_to_os_string, HgPath};
    20 use hg::utils::hg_path::{hg_path_to_os_string, HgPath};
    20 use hg::{HgPathCow, StatusOptions};
    21 use hg::{HgPathCow, StatusOptions};
    21 use log::{info, warn};
    22 use log::{info, warn};
    22 use std::borrow::Cow;
    23 use std::borrow::Cow;
    23 
    24 
   300 
   301 
   301 /// Check if a file is modified by comparing actual repo store and file system.
   302 /// Check if a file is modified by comparing actual repo store and file system.
   302 ///
   303 ///
   303 /// This meant to be used for those that the dirstate cannot resolve, due
   304 /// This meant to be used for those that the dirstate cannot resolve, due
   304 /// to time resolution limits.
   305 /// to time resolution limits.
   305 ///
       
   306 /// TODO: detect permission bits and similar metadata modifications
       
   307 fn unsure_is_modified(
   306 fn unsure_is_modified(
   308     repo: &Repo,
   307     repo: &Repo,
   309     manifest: &Manifest,
   308     manifest: &Manifest,
   310     hg_path: &HgPath,
   309     hg_path: &HgPath,
   311 ) -> Result<bool, HgError> {
   310 ) -> Result<bool, HgError> {
       
   311     let vfs = repo.working_directory_vfs();
       
   312     let fs_path = hg_path_to_os_string(hg_path).expect("HgPath conversion");
       
   313     let fs_metadata = vfs.symlink_metadata(&fs_path)?;
       
   314     let is_symlink = fs_metadata.file_type().is_symlink();
       
   315     // TODO: Also account for `FALLBACK_SYMLINK` and `FALLBACK_EXEC` from the dirstate
       
   316     let fs_flags = if is_symlink {
       
   317         Some(b'l')
       
   318     } else if has_exec_bit(&fs_metadata) {
       
   319         Some(b'x')
       
   320     } else {
       
   321         None
       
   322     };
       
   323 
   312     let entry = manifest
   324     let entry = manifest
   313         .find_file(hg_path)?
   325         .find_file(hg_path)?
   314         .expect("ambgious file not in p1");
   326         .expect("ambgious file not in p1");
       
   327     if entry.flags != fs_flags {
       
   328         return Ok(true);
       
   329     }
   315     let filelog = repo.filelog(hg_path)?;
   330     let filelog = repo.filelog(hg_path)?;
   316     let filelog_entry =
   331     let filelog_entry =
   317         filelog.data_for_node(entry.node_id()?).map_err(|_| {
   332         filelog.data_for_node(entry.node_id()?).map_err(|_| {
   318             HgError::corrupted("filelog missing node from manifest")
   333             HgError::corrupted("filelog missing node from manifest")
   319         })?;
   334         })?;
   320     let contents_in_p1 = filelog_entry.data()?;
   335     let contents_in_p1 = filelog_entry.data()?;
   321 
   336 
   322     let fs_path = hg_path_to_os_string(hg_path).expect("HgPath conversion");
   337     let fs_contents = if is_symlink {
   323     let fs_contents = repo.working_directory_vfs().read(fs_path)?;
   338         get_bytes_from_os_string(vfs.read_link(fs_path)?.into_os_string())
       
   339     } else {
       
   340         vfs.read(fs_path)?
       
   341     };
   324     return Ok(contents_in_p1 != &*fs_contents);
   342     return Ok(contents_in_p1 != &*fs_contents);
   325 }
   343 }