effectflag: allow to save effect of change in obsmarkers
authorBoris Feld <boris.feld@octobus.net>
Fri, 19 May 2017 18:43:21 +0200
changeset 2446 4b2f4da124a2
parent 2445 07c5c79fc3d9
child 2447 631ccf45f0bb
effectflag: allow to save effect of change in obsmarkers Obsmarkers lack a precious information, what are the changes between the source and the destination. This could be several thing: - The description has changed, with a amend -e for example - The parent has changed, with a rebase for example - The content has changed, with a amend for example - The meta, like the user, has change, with a amend -u for example Or any combination of them. We hijack the createobsmarkers in order to compute the modification and store the effect flag which is basically a bitfield of the changes list above and we store it in the metadata for the moment. The advantage of computing the flag just before creating the obs marker is that all commands will immediately be compatible and we can start working on the UI display of the flag. As a future optimization, the commands will be able to pass the flag directly or data to help computing them, for example amend knows if the description has changed or rebase now if the parent has changed, virtually removing the overhead. To start simple, this patch add the detection and storage of the effect flag when the description has changed. And hide it behind an experimental flag disabled by default 'experimental.evolution.effect-flags'. More flag will follow.
hgext3rd/evolve/obshistory.py
tests/test-evolve-effectflags.t
--- a/hgext3rd/evolve/obshistory.py	Fri May 19 18:07:56 2017 +0200
+++ b/hgext3rd/evolve/obshistory.py	Fri May 19 18:43:21 2017 +0200
@@ -12,6 +12,7 @@
     commands,
     error,
     graphmod,
+    obsolete,
     node as nodemod,
     scmutil,
 )
@@ -355,3 +356,59 @@
                  label="evolve.node")
 
     fm.plain("\n")
+
+# logic around storing and using effect flags
+DESCCHANGED = 1 << 0 # action changed the description
+
+def geteffectflag(relation):
+    """compute the effect flag by comparing the source and destination"""
+    effects = 0
+
+    source = relation[0]
+
+    for changectx in relation[1]:
+        # Check if description has changed
+        if changectx.description() != source.description():
+            effects |= DESCCHANGED
+
+    return effects
+
+@eh.wrapfunction(obsolete, 'createmarkers')
+def createmarkerswithbits(orig, repo, relations, flag=0, date=None, metadata=None):
+    """compute 'effect-flag' and augment the created markers
+
+    Wrap obsolete.createmarker in order to compute the effect of each
+    relationship and store them as flag in the metadata.
+
+    While we experiment, we store flag in a metadata field. This field is
+    "versionned" to easilly allow moving to other meaning for flags.
+
+    The comparison of description or other infos just before creating the obs
+    marker might induce overhead in some cases. However it is a good place to
+    start since it automatically makes all markers creation recording more
+    meaningful data. In the future, we can introduce way for commands to
+    provide precomputed effect to avoid the overhead.
+    """
+    if not repo.ui.configbool('experimental', 'evolution.effect-flags', False):
+        return orig(repo, relations, flag, date, metadata)
+    if metadata is None:
+        metadata = {}
+    tr = repo.transaction('add-obsolescence-marker')
+    try:
+        for r in relations:
+            # Compute the effect flag for each obsmarker
+            effect = geteffectflag(r)
+
+            # Copy the metadata in order to add them, we copy because the
+            # effect flag might be different per relation
+            m = metadata.copy()
+            # we store the effect even if "0". This disctinct markers created
+            # without the feature with markers recording a no-op.
+            m['ef1'] = "%d" % effect
+
+            # And call obsolete.createmarkers for creating the obsmarker for real
+            orig(repo, [r], flag, date, m)
+
+        tr.close()
+    finally:
+        tr.release()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-evolve-effectflags.t	Fri May 19 18:43:21 2017 +0200
@@ -0,0 +1,39 @@
+Test the 'effect-flags' feature
+
+Global setup
+============
+
+  $ . $TESTDIR/testlib/common.sh
+  $ cat >> $HGRCPATH <<EOF
+  > [ui]
+  > interactive = true
+  > [phases]
+  > publish=False
+  > [extensions]
+  > evolve =
+  > [experimental]
+  > evolution.effect-flags = 1
+  > EOF
+
+  $ hg init $TESTTMP/effect-flags
+  $ cd $TESTTMP/effect-flags
+  $ mkcommit ROOT
+
+Test simple amend touching the description only
+-----------------------------------------------
+
+amend the description only
+
+  $ mkcommit A0
+  $ hg amend -m "A1"
+
+check result
+
+  $ hg debugobsolete
+  471f378eab4c5e25f6c77f785b27c936efb22874 fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e 0 (*) {'ef1': '1', 'user': 'test'} (glob)
+  $ hg obslog .
+  @  fdf9bde5129a (2) A1
+  |
+  x  471f378eab4c (1) A0
+       rewritten by test (*) as fdf9bde5129a (glob)
+