Patchwork D11910: rhg: Skip reading the contents of ambiguous files in some cases

login
register
mail settings
Submitter phabricator
Date Dec. 14, 2021, 8:45 p.m.
Message ID <differential-rev-PHID-DREV-srx3noevb4xgvzi3kplj-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/50236/
State New
Headers show

Comments

phabricator - Dec. 14, 2021, 8:45 p.m.
SimonSapin created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  If the size of the file in the working directory does not match the length of
  the filelog data, we know its contents will be different and don’t need to
  read it.
  
  rhg still decodes the filelog revision, which is not needed in some cases.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11910

AFFECTED FILES
  rust/rhg/src/commands/status.rs

CHANGE DETAILS




To: SimonSapin, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/rust/rhg/src/commands/status.rs b/rust/rhg/src/commands/status.rs
--- a/rust/rhg/src/commands/status.rs
+++ b/rust/rhg/src/commands/status.rs
@@ -479,11 +479,23 @@ 
         return Ok(true);
     }
     let filelog = repo.filelog(hg_path)?;
+    let fs_len = fs_metadata.len();
+    // TODO: check `fs_len` here like below, but based on
+    // `RevlogEntry::uncompressed_len` without decompressing the full filelog
+    // contents where possible. This is only valid if the revlog data does not
+    // contain metadata. See how Python’s `revlog.rawsize` calls
+    // `storageutil.filerevisioncopied`.
+    // (Maybe also check for content-modifying flags? See `revlog.size`.)
     let filelog_entry =
         filelog.data_for_node(entry.node_id()?).map_err(|_| {
             HgError::corrupted("filelog missing node from manifest")
         })?;
     let contents_in_p1 = filelog_entry.data()?;
+    if contents_in_p1.len() as u64 != fs_len {
+        // No need to read the file contents:
+        // it cannot be equal if it has a different length.
+        return Ok(true);
+    }
 
     let fs_contents = if is_symlink {
         get_bytes_from_os_string(vfs.read_link(fs_path)?.into_os_string())