[PATCH 01 of 15] commitctx: explicitly pass `manifest` to _commit_manifest

classic Classic list List threaded Threaded
18 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH 01 of 15] commitctx: explicitly pass `manifest` to _commit_manifest

Pierre-Yves David-2
# HG changeset patch
# User Pierre-Yves David <[hidden email]>
# Date 1596030013 -7200
#      Wed Jul 29 15:40:13 2020 +0200
# Node ID 0ff421a458680435f7a39c770cfa5823961cd314
# Parent  13814622b3b1a46308375a9fb4c6641fa495528f
# EXP-Topic files-change
# Available At https://foss.heptapod.net/octobus/mercurial-devel/
#              hg pull https://foss.heptapod.net/octobus/mercurial-devel/ -r 0ff421a45868
commitctx: explicitly pass `manifest` to _commit_manifest

As pointed out by Yuya Nishihara.

diff --git a/mercurial/commit.py b/mercurial/commit.py
--- a/mercurial/commit.py
+++ b/mercurial/commit.py
@@ -206,7 +206,7 @@ def _process_files(tr, ctx, error=False)
     touched.extend(removed)
 
     files = touched
-    mn = _commit_manifest(tr, linkrev, ctx, mctx, files, added, drop)
+    mn = _commit_manifest(tr, linkrev, ctx, mctx, m, files, added, drop)
 
     return mn, files, filesadded, removed
 
@@ -347,7 +347,7 @@ def _filecommit(
     return fnode, touched
 
 
-def _commit_manifest(tr, linkrev, ctx, mctx, files, added, drop):
+def _commit_manifest(tr, linkrev, ctx, mctx, manifest, files, added, drop):
     """make a new manifest entry (or reuse a new one)
 
     given an initialised manifest context and precomputed list of
@@ -370,8 +370,6 @@ def _commit_manifest(tr, linkrev, ctx, m
 
     m1 = m1ctx.read()
 
-    manifest = mctx.read()
-
     if not files:
         # if no "files" actually changed in terms of the changelog,
         # try hard to detect unmodified manifest entry so that the

_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

[PATCH 02 of 15] commitctx: create the new extra dict on its own line

Pierre-Yves David-2
# HG changeset patch
# User Pierre-Yves David <[hidden email]>
# Date 1595681995 -7200
#      Sat Jul 25 14:59:55 2020 +0200
# Node ID a926f7ac92a4024511389ea5c5d9a8e8eae065d4
# Parent  0ff421a458680435f7a39c770cfa5823961cd314
# EXP-Topic files-change
# Available At https://foss.heptapod.net/octobus/mercurial-devel/
#              hg pull https://foss.heptapod.net/octobus/mercurial-devel/ -r a926f7ac92a4
commitctx: create the new extra dict on its own line

A trivial move to make the next changeset easier to read.

diff --git a/mercurial/commit.py b/mercurial/commit.py
--- a/mercurial/commit.py
+++ b/mercurial/commit.py
@@ -67,6 +67,8 @@ def commitctx(repo, ctx, error=False, or
         r = _prepare_files(tr, ctx, error=error, origctx=origctx)
         mn, files, p1copies, p2copies, filesadded, filesremoved = r
 
+        extra = ctx.extra().copy()
+
         # update changelog
         repo.ui.note(_(b"committing changelog\n"))
         repo.changelog.delayupdate(tr)
@@ -79,7 +81,7 @@ def commitctx(repo, ctx, error=False, or
             p2.node(),
             user,
             ctx.date(),
-            ctx.extra().copy(),
+            extra,
             p1copies,
             p2copies,
             filesadded,

_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

[PATCH 03 of 15] commitctx: extract copy information encoding into extra into commit.py

Pierre-Yves David-2
In reply to this post by Pierre-Yves David-2
# HG changeset patch
# User Pierre-Yves David <[hidden email]>
# Date 1595682805 -7200
#      Sat Jul 25 15:13:25 2020 +0200
# Node ID 3e4e9837d03bd1345438e69ae154b72daa5cee6b
# Parent  a926f7ac92a4024511389ea5c5d9a8e8eae065d4
# EXP-Topic files-change
# Available At https://foss.heptapod.net/octobus/mercurial-devel/
#              hg pull https://foss.heptapod.net/octobus/mercurial-devel/ -r 3e4e9837d03b
commitctx: extract copy information encoding into extra into commit.py

The encoding of copy information into extra has multiple subcases and become
quite complicated (eg: empty list can be explicitly or implicitly stored for
example). In addition, it is niche experimental feature since as it affect the
hash, it is only suitable for user who don't mercurial for storage server side
(ie: Google).

Having this complexity part of the changelog will get in the way of further
cleanup. We could have to either move more of that logic into the changelog or
to move or extract more of the logic at the higher level. We take the second
approach and start gather logic in dedicated function in commit.py.

diff --git a/mercurial/changelog.py b/mercurial/changelog.py
--- a/mercurial/changelog.py
+++ b/mercurial/changelog.py
@@ -561,43 +561,21 @@ class changelog(revlog.revlog):
                 )
         sortedfiles = sorted(files)
         sidedata = None
-        if extra is not None:
-            for name in (
-                b'p1copies',
-                b'p2copies',
-                b'filesadded',
-                b'filesremoved',
-            ):
-                extra.pop(name, None)
-        if p1copies is not None:
-            p1copies = metadata.encodecopies(sortedfiles, p1copies)
-        if p2copies is not None:
-            p2copies = metadata.encodecopies(sortedfiles, p2copies)
-        if filesadded is not None:
-            filesadded = metadata.encodefileindices(sortedfiles, filesadded)
-        if filesremoved is not None:
-            filesremoved = metadata.encodefileindices(sortedfiles, filesremoved)
-        if self._copiesstorage == b'extra':
-            extrasentries = p1copies, p2copies, filesadded, filesremoved
-            if extra is None and any(x is not None for x in extrasentries):
-                extra = {}
-            if p1copies is not None:
-                extra[b'p1copies'] = p1copies
-            if p2copies is not None:
-                extra[b'p2copies'] = p2copies
-            if filesadded is not None:
-                extra[b'filesadded'] = filesadded
-            if filesremoved is not None:
-                extra[b'filesremoved'] = filesremoved
-        elif self._copiesstorage == b'changeset-sidedata':
+        if self._copiesstorage == b'changeset-sidedata':
             sidedata = {}
             if p1copies:
+                p1copies = metadata.encodecopies(sortedfiles, p1copies)
                 sidedata[sidedatamod.SD_P1COPIES] = p1copies
             if p2copies:
+                p2copies = metadata.encodecopies(sortedfiles, p2copies)
                 sidedata[sidedatamod.SD_P2COPIES] = p2copies
             if filesadded:
+                filesadded = metadata.encodefileindices(sortedfiles, filesadded)
                 sidedata[sidedatamod.SD_FILESADDED] = filesadded
             if filesremoved:
+                filesremoved = metadata.encodefileindices(
+                    sortedfiles, filesremoved
+                )
                 sidedata[sidedatamod.SD_FILESREMOVED] = filesremoved
             if not sidedata:
                 sidedata = None
diff --git a/mercurial/commit.py b/mercurial/commit.py
--- a/mercurial/commit.py
+++ b/mercurial/commit.py
@@ -69,6 +69,20 @@ def commitctx(repo, ctx, error=False, or
 
         extra = ctx.extra().copy()
 
+        files = sorted(files)
+        if extra is not None:
+            for name in (
+                b'p1copies',
+                b'p2copies',
+                b'filesadded',
+                b'filesremoved',
+            ):
+                extra.pop(name, None)
+        if repo.changelog._copiesstorage == b'extra':
+            extra = _extra_with_copies(
+                repo, extra, files, p1copies, p2copies, filesadded, filesremoved
+            )
+
         # update changelog
         repo.ui.note(_(b"committing changelog\n"))
         repo.changelog.delayupdate(tr)
@@ -407,3 +421,25 @@ def _commit_manifest(tr, linkrev, ctx, m
         mn = p1.manifestnode()
 
     return mn
+
+
+def _extra_with_copies(
+    repo, extra, files, p1copies, p2copies, filesadded, filesremoved
+):
+    """encode copy information into a `extra` dictionnary"""
+    extrasentries = p1copies, p2copies, filesadded, filesremoved
+    if extra is None and any(x is not None for x in extrasentries):
+        extra = {}
+    if p1copies is not None:
+        p1copies = metadata.encodecopies(files, p1copies)
+        extra[b'p1copies'] = p1copies
+    if p2copies is not None:
+        p2copies = metadata.encodecopies(files, p2copies)
+        extra[b'p2copies'] = p2copies
+    if filesadded is not None:
+        filesadded = metadata.encodefileindices(files, filesadded)
+        extra[b'filesadded'] = filesadded
+    if filesremoved is not None:
+        filesremoved = metadata.encodefileindices(files, filesremoved)
+        extra[b'filesremoved'] = filesremoved
+    return extra

_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

[PATCH 04 of 15] commitctx: rename files to touched in a couple of place

Pierre-Yves David-2
In reply to this post by Pierre-Yves David-2
# HG changeset patch
# User Pierre-Yves David <[hidden email]>
# Date 1595684025 -7200
#      Sat Jul 25 15:33:45 2020 +0200
# Node ID abdea95834b108e194df0f686f01fb4fd1847691
# Parent  3e4e9837d03bd1345438e69ae154b72daa5cee6b
# EXP-Topic files-change
# Available At https://foss.heptapod.net/octobus/mercurial-devel/
#              hg pull https://foss.heptapod.net/octobus/mercurial-devel/ -r abdea95834b1
commitctx: rename files to touched in a couple of place

This is a clearer word that we will use increasingly over this series. It also
make the old variable name available to another usage :-)

diff --git a/mercurial/commit.py b/mercurial/commit.py
--- a/mercurial/commit.py
+++ b/mercurial/commit.py
@@ -132,22 +132,22 @@ def _prepare_files(tr, ctx, error=False,
         # reuse an existing manifest revision
         repo.ui.debug(b'reusing known manifest\n')
         mn = ctx.manifestnode()
-        files = ctx.files()
+        touched = ctx.files()
         if writechangesetcopy:
             filesadded = ctx.filesadded()
             filesremoved = ctx.filesremoved()
     elif not ctx.files():
         repo.ui.debug(b'reusing manifest from p1 (no file change)\n')
         mn = p1.manifestnode()
-        files = []
+        touched = []
     else:
-        mn, files, added, removed = _process_files(tr, ctx, error=error)
+        mn, touched, added, removed = _process_files(tr, ctx, error=error)
         if writechangesetcopy:
             filesremoved = removed
             filesadded = added
 
     if origctx and origctx.manifestnode() == mn:
-        files = origctx.files()
+        touched = origctx.files()
 
     if not writefilecopymeta:
         # If writing only to changeset extras, use None to indicate that
@@ -159,7 +159,7 @@ def _prepare_files(tr, ctx, error=False,
         filesadded = filesadded or None
         filesremoved = filesremoved or None
 
-    return mn, files, p1copies, p2copies, filesadded, filesremoved
+    return mn, touched, p1copies, p2copies, filesadded, filesremoved
 
 
 def _process_files(tr, ctx, error=False):

_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

[PATCH 05 of 15] commitctx: gather more code dealing with copy-in-extra

Pierre-Yves David-2
In reply to this post by Pierre-Yves David-2
# HG changeset patch
# User Pierre-Yves David <[hidden email]>
# Date 1595684225 -7200
#      Sat Jul 25 15:37:05 2020 +0200
# Node ID 6b4ada6dca3ff5591c5dea32ffbe2fa22f4e5ed7
# Parent  abdea95834b108e194df0f686f01fb4fd1847691
# EXP-Topic files-change
# Available At https://foss.heptapod.net/octobus/mercurial-devel/
#              hg pull https://foss.heptapod.net/octobus/mercurial-devel/ -r 6b4ada6dca3f
commitctx: gather more code dealing with copy-in-extra

Now that we have a function that deal with the copy-in-extra special case, we
can gather more code meant to deal with this special case. Making the rest of
the code simpler.

diff --git a/mercurial/commit.py b/mercurial/commit.py
--- a/mercurial/commit.py
+++ b/mercurial/commit.py
@@ -149,16 +149,6 @@ def _prepare_files(tr, ctx, error=False,
     if origctx and origctx.manifestnode() == mn:
         touched = origctx.files()
 
-    if not writefilecopymeta:
-        # If writing only to changeset extras, use None to indicate that
-        # no entry should be written. If writing to both, write an empty
-        # entry to prevent the reader from falling back to reading
-        # filelogs.
-        p1copies = p1copies or None
-        p2copies = p2copies or None
-        filesadded = filesadded or None
-        filesremoved = filesremoved or None
-
     return mn, touched, p1copies, p2copies, filesadded, filesremoved
 
 
@@ -427,6 +417,16 @@ def _extra_with_copies(
     repo, extra, files, p1copies, p2copies, filesadded, filesremoved
 ):
     """encode copy information into a `extra` dictionnary"""
+    if not _write_copy_meta(repo)[1]:
+        # If writing only to changeset extras, use None to indicate that
+        # no entry should be written. If writing to both, write an empty
+        # entry to prevent the reader from falling back to reading
+        # filelogs.
+        p1copies = p1copies or None
+        p2copies = p2copies or None
+        filesadded = filesadded or None
+        filesremoved = filesremoved or None
+
     extrasentries = p1copies, p2copies, filesadded, filesremoved
     if extra is None and any(x is not None for x in extrasentries):
         extra = {}

_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

[PATCH 06 of 15] commitctx: return a richer object from _prepare_files

Pierre-Yves David-2
In reply to this post by Pierre-Yves David-2
# HG changeset patch
# User Pierre-Yves David <[hidden email]>
# Date 1595684952 -7200
#      Sat Jul 25 15:49:12 2020 +0200
# Node ID 88cc2b7a810243e8c101933fd99778ce772ac316
# Parent  6b4ada6dca3ff5591c5dea32ffbe2fa22f4e5ed7
# EXP-Topic files-change
# Available At https://foss.heptapod.net/octobus/mercurial-devel/
#              hg pull https://foss.heptapod.net/octobus/mercurial-devel/ -r 88cc2b7a8102
commitctx: return a richer object from _prepare_files

Instead of returning a lot of different list, we introduce a rich object that
hold all the file related information. The unique object help with data
consistency and simply functions arguments and return.

In the rest of this series we will increase usage of this object to simplify
more code.

diff --git a/mercurial/commit.py b/mercurial/commit.py
--- a/mercurial/commit.py
+++ b/mercurial/commit.py
@@ -64,12 +64,10 @@ def commitctx(repo, ctx, error=False, or
     user = ctx.user()
 
     with repo.lock(), repo.transaction(b"commit") as tr:
-        r = _prepare_files(tr, ctx, error=error, origctx=origctx)
-        mn, files, p1copies, p2copies, filesadded, filesremoved = r
+        mn, files = _prepare_files(tr, ctx, error=error, origctx=origctx)
 
         extra = ctx.extra().copy()
 
-        files = sorted(files)
         if extra is not None:
             for name in (
                 b'p1copies',
@@ -79,16 +77,14 @@ def commitctx(repo, ctx, error=False, or
             ):
                 extra.pop(name, None)
         if repo.changelog._copiesstorage == b'extra':
-            extra = _extra_with_copies(
-                repo, extra, files, p1copies, p2copies, filesadded, filesremoved
-            )
+            extra = _extra_with_copies(repo, extra, files)
 
         # update changelog
         repo.ui.note(_(b"committing changelog\n"))
         repo.changelog.delayupdate(tr)
         n = repo.changelog.add(
             mn,
-            files,
+            files.touched,
             ctx.description(),
             tr,
             p1.node(),
@@ -96,10 +92,10 @@ def commitctx(repo, ctx, error=False, or
             user,
             ctx.date(),
             extra,
-            p1copies,
-            p2copies,
-            filesadded,
-            filesremoved,
+            files.copied_from_p1,
+            files.copied_from_p2,
+            files.added,
+            files.removed,
         )
         xp1, xp2 = p1.hex(), p2 and p2.hex() or b''
         repo.hook(
@@ -149,7 +145,19 @@ def _prepare_files(tr, ctx, error=False,
     if origctx and origctx.manifestnode() == mn:
         touched = origctx.files()
 
-    return mn, touched, p1copies, p2copies, filesadded, filesremoved
+    files = metadata.ChangingFiles()
+    if touched:
+        files.update_touched(touched)
+    if p1copies:
+        files.update_copies_from_p1(p1copies)
+    if p2copies:
+        files.update_copies_from_p2(p2copies)
+    if filesadded:
+        files.update_added(filesadded)
+    if filesremoved:
+        files.update_removed(filesremoved)
+
+    return mn, files
 
 
 def _process_files(tr, ctx, error=False):
@@ -413,10 +421,13 @@ def _commit_manifest(tr, linkrev, ctx, m
     return mn
 
 
-def _extra_with_copies(
-    repo, extra, files, p1copies, p2copies, filesadded, filesremoved
-):
+def _extra_with_copies(repo, extra, files):
     """encode copy information into a `extra` dictionnary"""
+    p1copies = files.copied_from_p1
+    p2copies = files.copied_from_p2
+    filesadded = files.added
+    filesremoved = files.removed
+    files = sorted(files.touched)
     if not _write_copy_meta(repo)[1]:
         # If writing only to changeset extras, use None to indicate that
         # no entry should be written. If writing to both, write an empty
diff --git a/mercurial/metadata.py b/mercurial/metadata.py
--- a/mercurial/metadata.py
+++ b/mercurial/metadata.py
@@ -22,6 +22,79 @@ from .revlogutils import (
 )
 
 
+class ChangingFiles(object):
+    """A class recording the changes made to a file by a revision
+    """
+
+    def __init__(
+        self, touched=(), added=(), removed=(), p1_copies=(), p2_copies=(),
+    ):
+        self._added = set(added)
+        self._removed = set(removed)
+        self._touched = set(touched)
+        self._touched.update(self._added)
+        self._touched.update(self._removed)
+        self._p1_copies = dict(p1_copies)
+        self._p2_copies = dict(p2_copies)
+
+    @property
+    def added(self):
+        return frozenset(self._added)
+
+    def mark_added(self, filename):
+        self._added.add(filename)
+        self._touched.add(filename)
+
+    def update_added(self, filenames):
+        for f in filenames:
+            self.mark_added(f)
+
+    @property
+    def removed(self):
+        return frozenset(self._removed)
+
+    def mark_removed(self, filename):
+        self._removed.add(filename)
+        self._touched.add(filename)
+
+    def update_removed(self, filenames):
+        for f in filenames:
+            self.mark_removed(f)
+
+    @property
+    def touched(self):
+        return frozenset(self._touched)
+
+    def mark_touched(self, filename):
+        self._touched.add(filename)
+
+    def update_touched(self, filenames):
+        for f in filenames:
+            self.mark_touched(f)
+
+    @property
+    def copied_from_p1(self):
+        return self._p1_copies.copy()
+
+    def mark_copied_from_p1(self, source, dest):
+        self._p1_copies[dest] = source
+
+    def update_copies_from_p1(self, copies):
+        for dest, source in copies.items():
+            self.mark_copied_from_p1(source, dest)
+
+    @property
+    def copied_from_p2(self):
+        return self._p2_copies.copy()
+
+    def mark_copied_from_p2(self, source, dest):
+        self._p2_copies[dest] = source
+
+    def update_copies_from_p2(self, copies):
+        for dest, source in copies.items():
+            self.mark_copied_from_p2(source, dest)
+
+
 def computechangesetfilesadded(ctx):
     """return the list of files added in a changeset
     """

_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

[PATCH 07 of 15] commitctx: directly pass a ChangingFiles object to changelog.add

Pierre-Yves David-2
In reply to this post by Pierre-Yves David-2
# HG changeset patch
# User Pierre-Yves David <[hidden email]>
# Date 1595685309 -7200
#      Sat Jul 25 15:55:09 2020 +0200
# Node ID a728c320f0d7c71c733524969e728e533e2d34d6
# Parent  88cc2b7a810243e8c101933fd99778ce772ac316
# EXP-Topic files-change
# Available At https://foss.heptapod.net/octobus/mercurial-devel/
#              hg pull https://foss.heptapod.net/octobus/mercurial-devel/ -r a728c320f0d7
commitctx: directly pass a ChangingFiles object to changelog.add

We pass the rich object to the changelog and it read the field it needs.

diff --git a/mercurial/changelog.py b/mercurial/changelog.py
--- a/mercurial/changelog.py
+++ b/mercurial/changelog.py
@@ -524,10 +524,6 @@ class changelog(revlog.revlog):
         user,
         date=None,
         extra=None,
-        p1copies=None,
-        p2copies=None,
-        filesadded=None,
-        filesremoved=None,
     ):
         # Convert to UTF-8 encoded bytestrings as the very first
         # thing: calling any method on a localstr object will turn it
@@ -559,19 +555,23 @@ class changelog(revlog.revlog):
                 raise error.StorageError(
                     _(b'the name \'%s\' is reserved') % branch
                 )
-        sortedfiles = sorted(files)
+        sortedfiles = sorted(files.touched)
         sidedata = None
         if self._copiesstorage == b'changeset-sidedata':
             sidedata = {}
+            p1copies = files.copied_from_p1
             if p1copies:
                 p1copies = metadata.encodecopies(sortedfiles, p1copies)
                 sidedata[sidedatamod.SD_P1COPIES] = p1copies
+            p2copies = files.copied_from_p2
             if p2copies:
                 p2copies = metadata.encodecopies(sortedfiles, p2copies)
                 sidedata[sidedatamod.SD_P2COPIES] = p2copies
+            filesadded = files.added
             if filesadded:
                 filesadded = metadata.encodefileindices(sortedfiles, filesadded)
                 sidedata[sidedatamod.SD_FILESADDED] = filesadded
+            filesremoved = files.removed
             if filesremoved:
                 filesremoved = metadata.encodefileindices(
                     sortedfiles, filesremoved
diff --git a/mercurial/commit.py b/mercurial/commit.py
--- a/mercurial/commit.py
+++ b/mercurial/commit.py
@@ -84,7 +84,7 @@ def commitctx(repo, ctx, error=False, or
         repo.changelog.delayupdate(tr)
         n = repo.changelog.add(
             mn,
-            files.touched,
+            files,
             ctx.description(),
             tr,
             p1.node(),
@@ -92,10 +92,6 @@ def commitctx(repo, ctx, error=False, or
             user,
             ctx.date(),
             extra,
-            files.copied_from_p1,
-            files.copied_from_p2,
-            files.added,
-            files.removed,
         )
         xp1, xp2 = p1.hex(), p2 and p2.hex() or b''
         repo.hook(
diff --git a/tests/test-convert-identity.t b/tests/test-convert-identity.t
--- a/tests/test-convert-identity.t
+++ b/tests/test-convert-identity.t
@@ -8,9 +8,10 @@ versions.
   > convert =
   > EOF
   $ cat <<'EOF' > changefileslist.py
-  > from mercurial import (changelog, extensions)
+  > from mercurial import (changelog, extensions, metadata)
   > def wrap(orig, clog, manifest, files, *args, **kwargs):
-  >   return orig(clog, manifest, [b"a"], *args, **kwargs)
+  >   files = metadata.ChangingFiles(touched=[b"a"])
+  >   return orig(clog, manifest, files, *args, **kwargs)
   > def extsetup(ui):
   >   extensions.wrapfunction(changelog.changelog, 'add', wrap)
   > EOF

_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

[PATCH 08 of 15] commitctx: extract sidedata encoding inside its own function

Pierre-Yves David-2
In reply to this post by Pierre-Yves David-2
# HG changeset patch
# User Pierre-Yves David <[hidden email]>
# Date 1595685746 -7200
#      Sat Jul 25 16:02:26 2020 +0200
# Node ID 72d5e455f4d09cf58d1094120a6528a8591e614b
# Parent  a728c320f0d7c71c733524969e728e533e2d34d6
# EXP-Topic files-change
# Available At https://foss.heptapod.net/octobus/mercurial-devel/
#              hg pull https://foss.heptapod.net/octobus/mercurial-devel/ -r 72d5e455f4d0
commitctx: extract sidedata encoding inside its own function

This part of the code is quite independent from the rest. Thank to the new
ChangingFiles object, moving with the rest of the sidedata code (in metadata.py)
is simple.

The changelog.add method is simply passing the `files` object to the new
function. It will be easy to increase/change the data we gather and encode
without impacting the changelog method.

diff --git a/mercurial/changelog.py b/mercurial/changelog.py
--- a/mercurial/changelog.py
+++ b/mercurial/changelog.py
@@ -558,27 +558,7 @@ class changelog(revlog.revlog):
         sortedfiles = sorted(files.touched)
         sidedata = None
         if self._copiesstorage == b'changeset-sidedata':
-            sidedata = {}
-            p1copies = files.copied_from_p1
-            if p1copies:
-                p1copies = metadata.encodecopies(sortedfiles, p1copies)
-                sidedata[sidedatamod.SD_P1COPIES] = p1copies
-            p2copies = files.copied_from_p2
-            if p2copies:
-                p2copies = metadata.encodecopies(sortedfiles, p2copies)
-                sidedata[sidedatamod.SD_P2COPIES] = p2copies
-            filesadded = files.added
-            if filesadded:
-                filesadded = metadata.encodefileindices(sortedfiles, filesadded)
-                sidedata[sidedatamod.SD_FILESADDED] = filesadded
-            filesremoved = files.removed
-            if filesremoved:
-                filesremoved = metadata.encodefileindices(
-                    sortedfiles, filesremoved
-                )
-                sidedata[sidedatamod.SD_FILESREMOVED] = filesremoved
-            if not sidedata:
-                sidedata = None
+            sidedata = metadata.encode_copies_sidedata(files)
 
         if extra:
             extra = encodeextra(extra)
diff --git a/mercurial/metadata.py b/mercurial/metadata.py
--- a/mercurial/metadata.py
+++ b/mercurial/metadata.py
@@ -254,6 +254,30 @@ def decodefileindices(files, data):
         return None
 
 
+def encode_copies_sidedata(files):
+    sortedfiles = sorted(files.touched)
+    sidedata = {}
+    p1copies = files.copied_from_p1
+    if p1copies:
+        p1copies = encodecopies(sortedfiles, p1copies)
+        sidedata[sidedatamod.SD_P1COPIES] = p1copies
+    p2copies = files.copied_from_p2
+    if p2copies:
+        p2copies = encodecopies(sortedfiles, p2copies)
+        sidedata[sidedatamod.SD_P2COPIES] = p2copies
+    filesadded = files.added
+    if filesadded:
+        filesadded = encodefileindices(sortedfiles, filesadded)
+        sidedata[sidedatamod.SD_FILESADDED] = filesadded
+    filesremoved = files.removed
+    if filesremoved:
+        filesremoved = encodefileindices(sortedfiles, filesremoved)
+        sidedata[sidedatamod.SD_FILESREMOVED] = filesremoved
+    if not sidedata:
+        sidedata = None
+    return sidedata
+
+
 def _getsidedata(srcrepo, rev):
     ctx = srcrepo[rev]
     filescopies = computechangesetcopies(ctx)

_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

[PATCH 09 of 15] commitctx: directly gather p1 and p2 copies in `files`

Pierre-Yves David-2
In reply to this post by Pierre-Yves David-2
# HG changeset patch
# User Pierre-Yves David <[hidden email]>
# Date 1595686058 -7200
#      Sat Jul 25 16:07:38 2020 +0200
# Node ID 520fbac6d2d2ac49604bd408c0e64c13355ff6dd
# Parent  72d5e455f4d09cf58d1094120a6528a8591e614b
# EXP-Topic files-change
# Available At https://foss.heptapod.net/octobus/mercurial-devel/
#              hg pull https://foss.heptapod.net/octobus/mercurial-devel/ -r 520fbac6d2d2
commitctx: directly gather p1 and p2 copies in `files`

The only thing we do with the p1copies and p2copies is to pass them around, we
we can gather them later and directly stored them in the `ChangingFiles` object.

diff --git a/mercurial/commit.py b/mercurial/commit.py
--- a/mercurial/commit.py
+++ b/mercurial/commit.py
@@ -115,10 +115,6 @@ def _prepare_files(tr, ctx, error=False,
 
     writechangesetcopy, writefilecopymeta = _write_copy_meta(repo)
 
-    p1copies, p2copies = None, None
-    if writechangesetcopy:
-        p1copies = ctx.p1copies()
-        p2copies = ctx.p2copies()
     filesadded, filesremoved = None, None
     if ctx.manifestnode():
         # reuse an existing manifest revision
@@ -144,10 +140,9 @@ def _prepare_files(tr, ctx, error=False,
     files = metadata.ChangingFiles()
     if touched:
         files.update_touched(touched)
-    if p1copies:
-        files.update_copies_from_p1(p1copies)
-    if p2copies:
-        files.update_copies_from_p2(p2copies)
+    if writechangesetcopy:
+        files.update_copies_from_p1(ctx.p1copies())
+        files.update_copies_from_p2(ctx.p2copies())
     if filesadded:
         files.update_added(filesadded)
     if filesremoved:

_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

[PATCH 10 of 15] commitctx: no longer make the storage and added/removed file optional

Pierre-Yves David-2
In reply to this post by Pierre-Yves David-2
# HG changeset patch
# User Pierre-Yves David <[hidden email]>
# Date 1595686397 -7200
#      Sat Jul 25 16:13:17 2020 +0200
# Node ID 9d1d1cb2d9583aaf7c34d51808b309df9a55a12c
# Parent  520fbac6d2d2ac49604bd408c0e64c13355ff6dd
# EXP-Topic files-change
# Available At https://foss.heptapod.net/octobus/mercurial-devel/
#              hg pull https://foss.heptapod.net/octobus/mercurial-devel/ -r 9d1d1cb2d958
commitctx: no longer make the storage and added/removed file optional

The code using this variable is always using other, stricter, condition before
using these value. So it is safe to always carry them along.

diff --git a/mercurial/commit.py b/mercurial/commit.py
--- a/mercurial/commit.py
+++ b/mercurial/commit.py
@@ -129,10 +129,8 @@ def _prepare_files(tr, ctx, error=False,
         mn = p1.manifestnode()
         touched = []
     else:
-        mn, touched, added, removed = _process_files(tr, ctx, error=error)
-        if writechangesetcopy:
-            filesremoved = removed
-            filesadded = added
+        r = _process_files(tr, ctx, error=error)
+        mn, touched, filesadded, filesremoved = r
 
     if origctx and origctx.manifestnode() == mn:
         touched = origctx.files()

_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

[PATCH 11 of 15] commitctx: create the ChangingFiles object directly in the various case

Pierre-Yves David-2
In reply to this post by Pierre-Yves David-2
# HG changeset patch
# User Pierre-Yves David <[hidden email]>
# Date 1595686412 -7200
#      Sat Jul 25 16:13:32 2020 +0200
# Node ID 3bcb3b9adf1f0b5eb0ab6b4964b756162cc269b5
# Parent  9d1d1cb2d9583aaf7c34d51808b309df9a55a12c
# EXP-Topic files-change
# Available At https://foss.heptapod.net/octobus/mercurial-devel/
#              hg pull https://foss.heptapod.net/octobus/mercurial-devel/ -r 3bcb3b9adf1f
commitctx: create the ChangingFiles object directly in the various case

No need to compute all data then create the object, we can create it early and
directly store data in it. We start simple by moving create higher in the
function, but the end goal is to eventually move the creation inside the
`_process_files` function to take advantage of the object there.

diff --git a/mercurial/commit.py b/mercurial/commit.py
--- a/mercurial/commit.py
+++ b/mercurial/commit.py
@@ -115,36 +115,36 @@ def _prepare_files(tr, ctx, error=False,
 
     writechangesetcopy, writefilecopymeta = _write_copy_meta(repo)
 
-    filesadded, filesremoved = None, None
     if ctx.manifestnode():
         # reuse an existing manifest revision
         repo.ui.debug(b'reusing known manifest\n')
         mn = ctx.manifestnode()
-        touched = ctx.files()
+        files = metadata.ChangingFiles()
+        files.update_touched(ctx.files())
         if writechangesetcopy:
-            filesadded = ctx.filesadded()
-            filesremoved = ctx.filesremoved()
+            files.update_added(ctx.filesadded())
+            files.update_removed(ctx.filesremoved())
     elif not ctx.files():
         repo.ui.debug(b'reusing manifest from p1 (no file change)\n')
         mn = p1.manifestnode()
-        touched = []
+        files = metadata.ChangingFiles()
     else:
-        r = _process_files(tr, ctx, error=error)
-        mn, touched, filesadded, filesremoved = r
+        mn, touched, added, removed = _process_files(tr, ctx, error=error)
+        files = metadata.ChangingFiles()
+        files.update_touched(touched)
+        if added:
+            files.update_added(added)
+        if removed:
+            files.update_removed(removed)
 
     if origctx and origctx.manifestnode() == mn:
-        touched = origctx.files()
+        origfiles = origctx.files()
+        assert files.touched.issubset(origfiles)
+        files.update_touched(origfiles)
 
-    files = metadata.ChangingFiles()
-    if touched:
-        files.update_touched(touched)
     if writechangesetcopy:
         files.update_copies_from_p1(ctx.p1copies())
         files.update_copies_from_p2(ctx.p2copies())
-    if filesadded:
-        files.update_added(filesadded)
-    if filesremoved:
-        files.update_removed(filesremoved)
 
     return mn, files
 

_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

[PATCH 12 of 15] commitctx: move ChangingFiles creation directly inside `_process_files`

Pierre-Yves David-2
In reply to this post by Pierre-Yves David-2
# HG changeset patch
# User Pierre-Yves David <[hidden email]>
# Date 1595687642 -7200
#      Sat Jul 25 16:34:02 2020 +0200
# Node ID 3a8c3c3dcf9dbe0c8c154048ff57ca68193eb9c9
# Parent  3bcb3b9adf1f0b5eb0ab6b4964b756162cc269b5
# EXP-Topic files-change
# Available At https://foss.heptapod.net/octobus/mercurial-devel/
#              hg pull https://foss.heptapod.net/octobus/mercurial-devel/ -r 3a8c3c3dcf9d
commitctx: move ChangingFiles creation directly inside `_process_files`

As announced, we move it there. We focus on the signature change first, we will
update the code afterward.

diff --git a/mercurial/commit.py b/mercurial/commit.py
--- a/mercurial/commit.py
+++ b/mercurial/commit.py
@@ -129,13 +129,7 @@ def _prepare_files(tr, ctx, error=False,
         mn = p1.manifestnode()
         files = metadata.ChangingFiles()
     else:
-        mn, touched, added, removed = _process_files(tr, ctx, error=error)
-        files = metadata.ChangingFiles()
-        files.update_touched(touched)
-        if added:
-            files.update_added(added)
-        if removed:
-            files.update_removed(removed)
+        mn, files = _process_files(tr, ctx, error=error)
 
     if origctx and origctx.manifestnode() == mn:
         origfiles = origctx.files()
@@ -211,7 +205,11 @@ def _process_files(tr, ctx, error=False)
     files = touched
     mn = _commit_manifest(tr, linkrev, ctx, mctx, m, files, added, drop)
 
-    return mn, files, filesadded, removed
+    files = metadata.ChangingFiles(
+        touched=files, added=filesadded, removed=removed
+    )
+
+    return mn, files
 
 
 def _filecommit(

_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

[PATCH 13 of 15] commitctx: create the `ChangingFiles` object sooner

Pierre-Yves David-2
In reply to this post by Pierre-Yves David-2
# HG changeset patch
# User Pierre-Yves David <[hidden email]>
# Date 1596034111 -7200
#      Wed Jul 29 16:48:31 2020 +0200
# Node ID d1faf95bdf57bf8d1054b2ea717d24052a7692c1
# Parent  3a8c3c3dcf9dbe0c8c154048ff57ca68193eb9c9
# EXP-Topic files-change
# Available At https://foss.heptapod.net/octobus/mercurial-devel/
#              hg pull https://foss.heptapod.net/octobus/mercurial-devel/ -r d1faf95bdf57
commitctx: create the `ChangingFiles` object sooner

Let us change the `_commit_manifest` call before other changes.

diff --git a/mercurial/commit.py b/mercurial/commit.py
--- a/mercurial/commit.py
+++ b/mercurial/commit.py
@@ -202,12 +202,10 @@ def _process_files(tr, ctx, error=False)
 
     touched.extend(removed)
 
-    files = touched
-    mn = _commit_manifest(tr, linkrev, ctx, mctx, m, files, added, drop)
-
     files = metadata.ChangingFiles(
-        touched=files, added=filesadded, removed=removed
+        touched=touched, added=filesadded, removed=removed
     )
+    mn = _commit_manifest(tr, linkrev, ctx, mctx, m, files.touched, added, drop)
 
     return mn, files
 

_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

[PATCH 14 of 15] commitctx: directly updated the set of removed files

Pierre-Yves David-2
In reply to this post by Pierre-Yves David-2
# HG changeset patch
# User Pierre-Yves David <[hidden email]>
# Date 1595960349 -7200
#      Tue Jul 28 20:19:09 2020 +0200
# Node ID 8a38230c8e7b189066e0d58d8134228917368fd7
# Parent  d1faf95bdf57bf8d1054b2ea717d24052a7692c1
# EXP-Topic files-change
# Available At https://foss.heptapod.net/octobus/mercurial-devel/
#              hg pull https://foss.heptapod.net/octobus/mercurial-devel/ -r 8a38230c8e7b
commitctx: directly updated the set of removed files

The change is non-trivial so I made it in its own changeset.

diff --git a/mercurial/commit.py b/mercurial/commit.py
--- a/mercurial/commit.py
+++ b/mercurial/commit.py
@@ -191,20 +191,20 @@ def _process_files(tr, ctx, error=False)
                 repo.ui.warn(_(b"trouble committing %s!\n") % uipathfn(f))
             raise
 
+    files = metadata.ChangingFiles(touched=touched, added=filesadded)
     # update manifest
     removed = [f for f in removed if f in m1 or f in m2]
     drop = sorted([f for f in removed if f in m])
     for f in drop:
         del m[f]
-    if p2.rev() != nullrev:
+    if p2.rev() == nullrev:
+        files.update_removed(removed)
+    else:
         rf = metadata.get_removal_filter(ctx, (p1, p2, m1, m2))
-        removed = [f for f in removed if not rf(f)]
+        for f in removed:
+            if not rf(f):
+                files.mark_removed(f)
 
-    touched.extend(removed)
-
-    files = metadata.ChangingFiles(
-        touched=touched, added=filesadded, removed=removed
-    )
     mn = _commit_manifest(tr, linkrev, ctx, mctx, m, files.touched, added, drop)
 
     return mn, files

_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

[PATCH 15 of 15] commitctx: directly update the touched and added set of files

Pierre-Yves David-2
In reply to this post by Pierre-Yves David-2
# HG changeset patch
# User Pierre-Yves David <[hidden email]>
# Date 1595960466 -7200
#      Tue Jul 28 20:21:06 2020 +0200
# Node ID 2261f89274125f99c47463b7b485c3ecfb7becbd
# Parent  8a38230c8e7b189066e0d58d8134228917368fd7
# EXP-Topic files-change
# Available At https://foss.heptapod.net/octobus/mercurial-devel/
#              hg pull https://foss.heptapod.net/octobus/mercurial-devel/ -r 2261f8927412
commitctx: directly update the touched and added set of files

Instead of going through intermediate variable, we can simply use the
ChangingFiles object. The object will take care of the consistency.

diff --git a/mercurial/commit.py b/mercurial/commit.py
--- a/mercurial/commit.py
+++ b/mercurial/commit.py
@@ -158,11 +158,11 @@ def _process_files(tr, ctx, error=False)
     m1 = m1ctx.read()
     m2 = m2ctx.read()
 
+    files = metadata.ChangingFiles()
+
     # check in files
     added = []
-    filesadded = []
     removed = list(ctx.removed())
-    touched = []
     linkrev = len(repo)
     repo.ui.note(_(b"committing files:\n"))
     uipathfn = scmutil.getuipathfn(repo)
@@ -178,9 +178,10 @@ def _process_files(tr, ctx, error=False)
                     repo, fctx, m1, m2, linkrev, tr, writefilecopymeta,
                 )
                 if is_touched:
-                    touched.append(f)
                     if is_touched == 'added':
-                        filesadded.append(f)
+                        files.mark_added(f)
+                    else:
+                        files.mark_touched(f)
                 m.setflag(f, fctx.flags())
         except OSError:
             repo.ui.warn(_(b"trouble committing %s!\n") % uipathfn(f))
@@ -191,7 +192,6 @@ def _process_files(tr, ctx, error=False)
                 repo.ui.warn(_(b"trouble committing %s!\n") % uipathfn(f))
             raise
 
-    files = metadata.ChangingFiles(touched=touched, added=filesadded)
     # update manifest
     removed = [f for f in removed if f in m1 or f in m2]
     drop = sorted([f for f in removed if f in m])

_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 01 of 15] commitctx: explicitly pass `manifest` to _commit_manifest

Pulkit Goyal
In reply to this post by Pierre-Yves David-2
On Wed, Jul 29, 2020 at 10:44 PM Pierre-Yves David
<[hidden email]> wrote:

>
> # HG changeset patch
> # User Pierre-Yves David <[hidden email]>
> # Date 1596030013 -7200
> #      Wed Jul 29 15:40:13 2020 +0200
> # Node ID 0ff421a458680435f7a39c770cfa5823961cd314
> # Parent  13814622b3b1a46308375a9fb4c6641fa495528f
> # EXP-Topic files-change
> # Available At https://foss.heptapod.net/octobus/mercurial-devel/
> #              hg pull https://foss.heptapod.net/octobus/mercurial-devel/ -r 0ff421a45868
> commitctx: explicitly pass `manifest` to _commit_manifest
>
> As pointed out by Yuya Nishihara.

Queued 1 to 5, many thanks!
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 06 of 15] commitctx: return a richer object from _prepare_files

Yuya Nishihara
In reply to this post by Pierre-Yves David-2
On Wed, 29 Jul 2020 18:57:36 +0200, Pierre-Yves David wrote:

> # HG changeset patch
> # User Pierre-Yves David <[hidden email]>
> # Date 1595684952 -7200
> #      Sat Jul 25 15:49:12 2020 +0200
> # Node ID 88cc2b7a810243e8c101933fd99778ce772ac316
> # Parent  6b4ada6dca3ff5591c5dea32ffbe2fa22f4e5ed7
> # EXP-Topic files-change
> # Available At https://foss.heptapod.net/octobus/mercurial-devel/
> #              hg pull https://foss.heptapod.net/octobus/mercurial-devel/ -r 88cc2b7a8102
> commitctx: return a richer object from _prepare_files

Queued the remainder, thanks.

> +class ChangingFiles(object):
> +    """A class recording the changes made to a file by a revision
> +    """
> +
> +    def __init__(
> +        self, touched=(), added=(), removed=(), p1_copies=(), p2_copies=(),
> +    ):
> +        self._added = set(added)
> +        self._removed = set(removed)
> +        self._touched = set(touched)
> +        self._touched.update(self._added)
> +        self._touched.update(self._removed)
> +        self._p1_copies = dict(p1_copies)
> +        self._p2_copies = dict(p2_copies)
> +
> +    @property
> +    def added(self):
> +        return frozenset(self._added)

I generally avoid using @property function that does non-trivial work per call.
Does this frozenset business really matter?

> +    def mark_added(self, filename):
> +        self._added.add(filename)
> +        self._touched.add(filename)

> +    def mark_copied_from_p1(self, source, dest):
> +        self._p1_copies[dest] = source

It doesn't make sense that mark_added() updates both added and touched,
but mark_copied() doesn't.

Since ChangingFiles is basically a data object, I think sanity check can be
split into a function, and called occasionally e.g. before serializing the
metadata.
_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 06 of 15] commitctx: return a richer object from _prepare_files

Augie Fackler-2
In reply to this post by Pierre-Yves David-2


> On Jul 29, 2020, at 12:57, Pierre-Yves David <[hidden email]> wrote:
>
> # HG changeset patch
> # User Pierre-Yves David <[hidden email]>
> # Date 1595684952 -7200
> #      Sat Jul 25 15:49:12 2020 +0200
> # Node ID 88cc2b7a810243e8c101933fd99778ce772ac316
> # Parent  6b4ada6dca3ff5591c5dea32ffbe2fa22f4e5ed7
> # EXP-Topic files-change
> # Available At https://foss.heptapod.net/octobus/mercurial-devel/
> #              hg pull https://foss.heptapod.net/octobus/mercurial-devel/ -r 88cc2b7a8102
> commitctx: return a richer object from _prepare_files
>
> Instead of returning a lot of different list, we introduce a rich object that
> hold all the file related information. The unique object help with data
> consistency and simply functions arguments and return.
>
> In the rest of this series we will increase usage of this object to simplify
> more code.
>
> diff --git a/mercurial/commit.py b/mercurial/commit.py
> --- a/mercurial/commit.py
> +++ b/mercurial/commit.py
> @@ -64,12 +64,10 @@ def commitctx(repo, ctx, error=False, or
>     user = ctx.user()
>
>     with repo.lock(), repo.transaction(b"commit") as tr:
> -        r = _prepare_files(tr, ctx, error=error, origctx=origctx)
> -        mn, files, p1copies, p2copies, filesadded, filesremoved = r
> +        mn, files = _prepare_files(tr, ctx, error=error, origctx=origctx)
>
>         extra = ctx.extra().copy()
>
> -        files = sorted(files)
>         if extra is not None:
>             for name in (
>                 b'p1copies',
> @@ -79,16 +77,14 @@ def commitctx(repo, ctx, error=False, or
>             ):
>                 extra.pop(name, None)
>         if repo.changelog._copiesstorage == b'extra':
> -            extra = _extra_with_copies(
> -                repo, extra, files, p1copies, p2copies, filesadded, filesremoved
> -            )
> +            extra = _extra_with_copies(repo, extra, files)
>
>         # update changelog
>         repo.ui.note(_(b"committing changelog\n"))
>         repo.changelog.delayupdate(tr)
>         n = repo.changelog.add(
>             mn,
> -            files,
> +            files.touched,
>             ctx.description(),
>             tr,
>             p1.node(),
> @@ -96,10 +92,10 @@ def commitctx(repo, ctx, error=False, or
>             user,
>             ctx.date(),
>             extra,
> -            p1copies,
> -            p2copies,
> -            filesadded,
> -            filesremoved,
> +            files.copied_from_p1,
> +            files.copied_from_p2,
> +            files.added,
> +            files.removed,
>         )
>         xp1, xp2 = p1.hex(), p2 and p2.hex() or b''
>         repo.hook(
> @@ -149,7 +145,19 @@ def _prepare_files(tr, ctx, error=False,
>     if origctx and origctx.manifestnode() == mn:
>         touched = origctx.files()
>
> -    return mn, touched, p1copies, p2copies, filesadded, filesremoved
> +    files = metadata.ChangingFiles()
> +    if touched:
> +        files.update_touched(touched)
> +    if p1copies:
> +        files.update_copies_from_p1(p1copies)
> +    if p2copies:
> +        files.update_copies_from_p2(p2copies)
> +    if filesadded:
> +        files.update_added(filesadded)
> +    if filesremoved:
> +        files.update_removed(filesremoved)
> +
> +    return mn, files
>
>
> def _process_files(tr, ctx, error=False):
> @@ -413,10 +421,13 @@ def _commit_manifest(tr, linkrev, ctx, m
>     return mn
>
>
> -def _extra_with_copies(
> -    repo, extra, files, p1copies, p2copies, filesadded, filesremoved
> -):
> +def _extra_with_copies(repo, extra, files):
>     """encode copy information into a `extra` dictionnary"""
> +    p1copies = files.copied_from_p1
> +    p2copies = files.copied_from_p2
> +    filesadded = files.added
> +    filesremoved = files.removed
> +    files = sorted(files.touched)
>     if not _write_copy_meta(repo)[1]:
>         # If writing only to changeset extras, use None to indicate that
>         # no entry should be written. If writing to both, write an empty
> diff --git a/mercurial/metadata.py b/mercurial/metadata.py
> --- a/mercurial/metadata.py
> +++ b/mercurial/metadata.py
> @@ -22,6 +22,79 @@ from .revlogutils import (
> )
>
>
> +class ChangingFiles(object):

Could much of this have been an attr.s instead? I'm not sure I'd worry too hard about frozen* types, but YMMV.

> +    """A class recording the changes made to a file by a revision
> +    """
> +
> +    def __init__(
> +        self, touched=(), added=(), removed=(), p1_copies=(), p2_copies=(),
> +    ):

I'd like a follow-up on this change for this __init__: these should be None, not the empty-tuple. The way the function is constructed now pytype and mypy will both be _very_ confused (or wrong!) about what this function expects: they'll interpret this as "tuple of stuff" when it looks like it should mostly be "optional set or dict" of stuff?

> +        self._added = set(added)
> +        self._removed = set(removed)
> +        self._touched = set(touched)
> +        self._touched.update(self._added)
> +        self._touched.update(self._removed)
> +        self._p1_copies = dict(p1_copies)
> +        self._p2_copies = dict(p2_copies)
> +
> +    @property
> +    def added(self):
> +        return frozenset(self._added)
> +
> +    def mark_added(self, filename):
> +        self._added.add(filename)
> +        self._touched.add(filename)
> +
> +    def update_added(self, filenames):
> +        for f in filenames:
> +            self.mark_added(f)
> +
> +    @property
> +    def removed(self):
> +        return frozenset(self._removed)
> +
> +    def mark_removed(self, filename):
> +        self._removed.add(filename)
> +        self._touched.add(filename)
> +
> +    def update_removed(self, filenames):
> +        for f in filenames:
> +            self.mark_removed(f)
> +
> +    @property
> +    def touched(self):
> +        return frozenset(self._touched)
> +
> +    def mark_touched(self, filename):
> +        self._touched.add(filename)
> +
> +    def update_touched(self, filenames):
> +        for f in filenames:
> +            self.mark_touched(f)
> +
> +    @property
> +    def copied_from_p1(self):
> +        return self._p1_copies.copy()
> +
> +    def mark_copied_from_p1(self, source, dest):
> +        self._p1_copies[dest] = source
> +
> +    def update_copies_from_p1(self, copies):
> +        for dest, source in copies.items():
> +            self.mark_copied_from_p1(source, dest)
> +
> +    @property
> +    def copied_from_p2(self):
> +        return self._p2_copies.copy()
> +
> +    def mark_copied_from_p2(self, source, dest):
> +        self._p2_copies[dest] = source
> +
> +    def update_copies_from_p2(self, copies):
> +        for dest, source in copies.items():
> +            self.mark_copied_from_p2(source, dest)
> +
> +
> def computechangesetfilesadded(ctx):
>     """return the list of files added in a changeset
>     """
>
> _______________________________________________
> Mercurial-devel mailing list
> [hidden email]
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel

_______________________________________________
Mercurial-devel mailing list
[hidden email]
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel