[PATCH 10 of 10] effectflag: detect when diff changed
Christophe de Vienne
christophe at cdevienne.info
Tue Jul 18 09:12:10 EDT 2017
Hello,
As a end-user I encountered some situations were having such information
about changeset not available in my local repo would have help.
The main situation I recall is a colleague doing multiple amend or
rebase of several changesets. On my side I had made other rebase &
amends (lack of communication I guess) and pushed. When he pulled we
ended up with several divergent changeset that were not trivial to sort.
To solve the issue I pulled everything locally and had to compare the
divergent changeset diffs one by one.
Having some more information about obsolete (and not available) cset in
my repository would have help a lot to decide which version of the
changeset to take. Like who did what (amend ? rebase ?).
Le 09/07/2017 à 22:17, quark at fb.com (Jun Wu) a écrit :
> It's not very clear to me that what do we plan to use the effectflags.
>
> I guess the most useful case is divergent resolution, like Alice changes
> message, Bob changes content, so we know what to do. But a chain of changes
> could cancel effects with each other, like:
>
> A0 - (amend by Alice) -> A1 - (amend by Alice) -> A2
> \
> -- (a chain of rewrites by Bob) -> A9
>
> "A0 -> A1" changes diff content, "A1 -> A2" changes diff content. But
> "A0 -> A2" does not necessarily change diff content.
>
> This is a divergent case where A0 has two visible successors: A2 and A9. A2
> does not have diff content change but with effectflags, A2 might be treated
> as having diff content change.
>
> I think we should store the hash of actual diff text as metadata to detect
> diff changes across a chain of rewrites. That hash could be stored in a
> cache.
>
> For other information like branch, desc, meta, parents. Since reading them
> is very fast using changelog, I'm not sure about the benefit of storing them
> in obsmarkers. It might be helpful to provide extra information for nodes
> unknown to local changelog (I'd also argue those markers are meaningless and
> should be hidden from the user, but that's another topic), but I don't think
> this feature is useful for an end-user.
>
>
> Excerpts from Boris Feld's message of 2017-07-07 14:38:39 +0200:
>> # HG changeset patch
>> # User Boris Feld <boris.feld at octobus.net>
>> # Date 1499346007 -7200
>> # Thu Jul 06 15:00:07 2017 +0200
>> # Node ID 449fc1c748c6e058e892a4c940e20137e52e7808
>> # Parent 6a40d87dfedcce4064eb4bcdb131ed4d427fd4de
>> # EXP-Topic effectflag
>> effectflag: detect when diff changed
>>
>> Store in effect flag when the diff changed between the predecessor and
>> its successors.
>>
>> Comparing the diff is not easy because we do not want to incorrectly detect a
>> diff modification when the changeset has only been rebased.
>>
>> diff -r 6a40d87dfedc -r 449fc1c748c6 mercurial/obsutil.py
>> --- a/mercurial/obsutil.py Thu Jul 06 14:58:44 2017 +0200
>> +++ b/mercurial/obsutil.py Thu Jul 06 15:00:07 2017 +0200
>> @@ -542,6 +542,7 @@
>> DESCCHANGED = 1 << 0 # action changed the description
>> METACHANGED = 1 << 1 # action change the meta
>> PARENTCHANGED = 1 << 2 # action change the parent
>> +DIFFCHANGED = 1 << 3 # action change diff introduced by the changeset
>> USERCHANGED = 1 << 4 # the user changed
>> DATECHANGED = 1 << 5 # the date changed
>> BRANCHCHANGED = 1 << 6 # the branch changed
>> @@ -565,6 +566,46 @@
>>
>> return True
>>
>> +def _prepare_hunk(hunk):
>> + """Drop all information but the username and patch"""
>> + cleanunk = []
>> + for line in hunk.splitlines():
>> + if line.startswith(b'# User') or not line.startswith(b'#'):
>> + if line.startswith(b'@@'):
>> + line = b'@@\n'
>> + cleanunk.append(line)
>> + return cleanunk
>> +
>> +def _getdifflines(iterdiff):
>> + """return a cleaned up lines"""
>> + try:
>> + lines = next(iterdiff)
>> + except StopIteration:
>> + return None
>> + return _prepare_hunk(lines)
>> +
>> +def _cmpdiff(leftctx, rightctx):
>> + """return True if both ctx introduce the "same diff"
>> +
>> + This is a first and basic implementation, with many shortcoming.
>> + """
>> +
>> + # Leftctx or right ctx might be filtered, so we need to use the contexts
>> + # with an unfiltered repository to safely compute the diff
>> + leftunfi = leftctx._repo.unfiltered()[leftctx.rev()]
>> + leftdiff = leftunfi.diff(git=1)
>> + rightunfi = rightctx._repo.unfiltered()[rightctx.rev()]
>> + rightdiff = rightunfi.diff(git=1)
>> +
>> + left, right = (0, 0)
>> + while None not in (left, right):
>> + left = _getdifflines(leftdiff)
>> + right = _getdifflines(rightdiff)
>> +
>> + if left != right:
>> + return False
>> + return True
>> +
>> def geteffectflag(relation):
>> """ From an obs-marker relation, compute what changed between the
>> predecessor and the successor.
>> @@ -604,4 +645,12 @@
>> if ctxmeta != srcmeta:
>> effects |= METACHANGED
>>
>> + # Check if at least one of the parent has changed
>> + if changectx.parents() != source.parents():
>> + effects |= PARENTCHANGED
>> +
>> + # Check if the diff has changed
>> + if not _cmpdiff(source, changectx):
>> + effects |= DIFFCHANGED
>> +
>> return effects
>> diff -r 6a40d87dfedc -r 449fc1c748c6 tests/test-obsmarkers-effectflag.t
>> --- a/tests/test-obsmarkers-effectflag.t Thu Jul 06 14:58:44 2017 +0200
>> +++ b/tests/test-obsmarkers-effectflag.t Thu Jul 06 15:00:07 2017 +0200
>> @@ -95,7 +95,7 @@
>>
>> $ hg debugobsolete --rev .
>> d6f4d8b8d3c8cde990f13915bced7f92ce1cc54f 0 {ebfe0333e0d96f68a917afd97c0a0af87f1c3b5f} (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'user': 'test'}
>> - ebfe0333e0d96f68a917afd97c0a0af87f1c3b5f 75781fdbdbf58a987516b00c980bccda1e9ae588 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '0', 'user': 'test'}
>> + ebfe0333e0d96f68a917afd97c0a0af87f1c3b5f 75781fdbdbf58a987516b00c980bccda1e9ae588 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'user': 'test'}
>>
>> amend with multiple effect (desc and meta)
>
--
Christophe de Vienne
More information about the Mercurial-devel
mailing list