changeset 51915:6223892833db

revlogutils: teach issue6528 filtering about grandparents During dynamic filtering, we should assume that the current repository is correct. Therefore the parents of the delta base can tell us if that parent has metadata without having to build the whole text.
author Joerg Sonnenberger <joerg@bec.de>
date Sat, 20 Jul 2024 03:04:48 +0200
parents 3dbbb7d913a9
children 1d6982827c4b
files mercurial/revlogutils/rewrite.py
diffstat 1 files changed, 27 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/revlogutils/rewrite.py	Sat Jul 20 00:43:08 2024 +0200
+++ b/mercurial/revlogutils/rewrite.py	Sat Jul 20 03:04:48 2024 +0200
@@ -618,12 +618,17 @@
     delta = lambda: rl._inner._chunk(filerev)
     full_text = lambda: rl.rawdata(filerev)
     parent_revs = lambda: rl.parentrevs(filerev)
+    # This function is used by repair_issue6528, but not by
+    # filter_delta_issue6528. As such, we do not want to trust
+    # parent revisions of the delta base to decide whether
+    # the delta base has metadata.
     return _is_revision_affected_fast_inner(
         is_censored,
         delta_base,
         delta,
         full_text,
         parent_revs,
+        None,  # don't trust the parent revisions
         filerev,
         metadata_cache,
     )
@@ -635,6 +640,7 @@
     delta,
     full_text,
     parent_revs,
+    deltabase_parentrevs,
     filerev,
     metadata_cache,
 ):
@@ -659,12 +665,25 @@
     delta_parent = delta_base()
     parent_has_metadata = metadata_cache.get(delta_parent)
     if parent_has_metadata is None:
-        return _is_revision_affected_inner(
-            full_text,
-            parent_revs,
-            filerev,
-            metadata_cache,
-        )
+        if deltabase_parentrevs is not None:
+            deltabase_parentrevs = deltabase_parentrevs()
+            if deltabase_parentrevs == (nullrev, nullrev):
+                # Need to check the content itself as there is no flag.
+                parent_has_metadata = None
+            elif deltabase_parentrevs[0] == nullrev:
+                # Second parent is !null, assume repository is correct
+                # and has flagged this file revision as having metadata.
+                parent_has_metadata = True
+            elif deltabase_parentrevs[1] == nullrev:
+                # First parent is !null, so assume it has no metadata.
+                parent_has_metadata = False
+        if parent_has_metadata is None:
+            return _is_revision_affected_inner(
+                full_text,
+                parent_revs,
+                filerev,
+                metadata_cache,
+            )
 
     chunk = delta()
     if not len(chunk):
@@ -766,9 +785,9 @@
         p2_rev = revlog.rev(p2_node)
 
         is_censored = lambda: bool(flags & REVIDX_ISCENSORED)
-        delta_base = lambda: revlog.rev(delta_base)
         delta_base = lambda: base_rev
         parent_revs = lambda: (p1_rev, p2_rev)
+        deltabase_parentrevs = lambda: revlog.parentrevs(base_rev)
 
         def full_text():
             # note: being able to reuse the full text computation in the
@@ -794,6 +813,7 @@
             lambda: delta,
             full_text,
             parent_revs,
+            deltabase_parentrevs,
             rev,
             metadata_cache,
         )