changing-files: document the various sets
authorPierre-Yves David <pierre-yves.david@octobus.net>
Thu, 17 Sep 2020 11:21:13 +0200
changeset 45506 1f50bcc96595
parent 45505 e3df1f560d9a
child 45507 df87821081ee
changing-files: document the various sets The content of some sets (eg: added, removed) is not always obvious so we document them.
mercurial/metadata.py
--- a/mercurial/metadata.py	Fri Sep 18 10:48:43 2020 -0400
+++ b/mercurial/metadata.py	Thu Sep 17 11:21:13 2020 +0200
@@ -23,7 +23,20 @@
 
 
 class ChangingFiles(object):
-    """A class recording the changes made to a file by a revision
+    """A class recording the changes made to a file by a changeset
+
+    Actions performed on files are gathered into 3 sets:
+
+    - added:   files actively added in the changeset.
+    - removed: files removed in the revision
+    - touched: files affected by the merge
+
+    and copies information is held by 2 mappings
+
+    - copied_from_p1: {"<new-name>": "<source-name-in-p1>"} mapping for copies
+    - copied_from_p2: {"<new-name>": "<source-name-in-p2>"} mapping for copies
+
+    See their inline help for details.
     """
 
     def __init__(
@@ -39,6 +52,15 @@
 
     @property
     def added(self):
+        """files actively added in the changeset
+
+        Any file present in that revision that was absent in all the changeset's
+        parents.
+
+        In case of merge, this means a file absent in one of the parents but
+        existing in the other will *not* be contained in this set. (They were
+        added by an ancestor)
+        """
         return frozenset(self._added)
 
     def mark_added(self, filename):
@@ -51,6 +73,38 @@
 
     @property
     def removed(self):
+        """files actively removed by the changeset
+
+        In case of merge this will only contain the set of files removing "new"
+        content. For any file absent in the current changeset:
+
+        a) If the file exists in both parents, it is clearly "actively" removed
+        by this changeset.
+
+        b) If a file exists in only one parent and in none of the common
+        ancestors, then the file was newly added in one of the merged branches
+        and then got "actively" removed.
+
+        c) If a file exists in only one parent and at least one of the common
+        ancestors using the same filenode, then the file was unchanged on one
+        side and deleted on the other side. The merge "passively" propagated
+        that deletion, but didn't "actively" remove the file. In this case the
+        file is *not* included in the `removed` set.
+
+        d) If a file exists in only one parent and at least one of the common
+        ancestors using a different filenode, then the file was changed on one
+        side and removed on the other side. The merge process "actively"
+        decided to drop the new change and delete the file. Unlike in the
+        previous case, (c), the file included in the `removed` set.
+
+        Summary table for merge:
+
+        case | exists in parents | exists in gca || removed
+         (a) |       both        |     *         ||   yes
+         (b) |       one         |     none      ||   yes
+         (c) |       one         | same filenode ||   no
+         (d) |       one         |  new filenode ||   yes
+        """
         return frozenset(self._removed)
 
     def mark_removed(self, filename):
@@ -63,6 +117,7 @@
 
     @property
     def touched(self):
+        """files either actively modified, added or removed"""
         return frozenset(self._touched)
 
     def mark_touched(self, filename):