mercurial/metadata.py
changeset 45667 0303fc1f43f8
parent 45666 f6811e5bd994
child 45668 47ad23549b81
--- a/mercurial/metadata.py	Tue Sep 29 22:38:08 2020 +0200
+++ b/mercurial/metadata.py	Tue Sep 29 22:46:29 2020 +0200
@@ -230,6 +230,14 @@
     p2 = ctx.p2()
     if p1.rev() == node.nullrev and p2.rev() == node.nullrev:
         return _process_root(ctx)
+    elif p1.rev() != node.nullrev and p2.rev() == node.nullrev:
+        return _process_linear(p1, ctx)
+    elif p1.rev() == node.nullrev and p2.rev() != node.nullrev:
+        # In the wild, one can encounter changeset where p1 is null but p2 is not
+        return _process_linear(p1, ctx, parent=2)
+    elif p1.rev() == p2.rev():
+        # In the wild, one can encounter such "non-merge"
+        return _process_linear(p1, ctx)
     filescopies = computechangesetcopies(ctx)
     filesadded = computechangesetfilesadded(ctx)
     filesremoved = computechangesetfilesremoved(ctx)
@@ -255,6 +263,44 @@
     return md
 
 
+def _process_linear(parent_ctx, children_ctx, parent=1):
+    """compute the appropriate changed files for a changeset with a single parent
+    """
+    md = ChangingFiles()
+    parent_manifest = parent_ctx.manifest()
+    children_manifest = children_ctx.manifest()
+
+    copies_candidate = []
+
+    for filename, d in parent_manifest.diff(children_manifest).items():
+        if d[1][0] is None:
+            # no filenode for the "new" value, file is absent
+            md.mark_removed(filename)
+        else:
+            copies_candidate.append(filename)
+            if d[0][0] is None:
+                # not filenode for the "old" value file was absent
+                md.mark_added(filename)
+            else:
+                # filenode for both "old" and "new"
+                md.mark_touched(filename)
+
+    if parent == 1:
+        copied = md.mark_copied_from_p1
+    elif parent == 2:
+        copied = md.mark_copied_from_p2
+    else:
+        assert False, "bad parent value %d" % parent
+
+    for filename in copies_candidate:
+        copy_info = children_ctx[filename].renamed()
+        if copy_info:
+            source, srcnode = copy_info
+            copied(source, filename)
+
+    return md
+
+
 def computechangesetfilesadded(ctx):
     """return the list of files added in a changeset
     """