changeset 48510:b005d07ded7d

rhg: Skip reading the contents of ambiguous files in some cases 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. Differential Revision: https://phab.mercurial-scm.org/D11910
author Simon Sapin <simon.sapin@octobus.net>
date Tue, 14 Dec 2021 20:36:36 +0100
parents 3eb3aef6d3bf
children a4d8de93023c
files rust/rhg/src/commands/status.rs
diffstat 1 files changed, 12 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/rust/rhg/src/commands/status.rs	Tue Dec 14 19:47:33 2021 +0100
+++ b/rust/rhg/src/commands/status.rs	Tue Dec 14 20:36:36 2021 +0100
@@ -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())