[PATCH v5] histedit: make histedit aware of obsolescense not stored in state (issue4800)

Pierre-Yves David pierre-yves.david at ens-lyon.org
Tue Feb 23 17:48:17 EST 2016



On 02/23/2016 10:40 PM, Kostia Balytskyi wrote:
> # HG changeset patch
> # User Kostia Balytskyi <ikostia at fb.com>
> # Date 1456263516 0
> #      Tue Feb 23 21:38:36 2016 +0000
> # Node ID 9129dbd7a1780c66bd212b16e2c08e2ecab20976
> # Parent  28e1694ca60056d609ae2c8e0ad5cb2891416ea3
> histedit: make histedit aware of obsolescense not stored in state (issue4800)
>
> Before this change, when histedit exited to interactive session (during edit
> command for example), user could introduce obsolescence markers that would not
> be known to histedit. For example, user could've amended one of the commits.
> The fact of this amendment would not be stored in histedit's state file
> and later, when histedit would try to process all the replacements,
> one of the final successors (in histedit's opinion) would turn out to be hidden.
> This behavior is described in issue4800. This commit fixes it.
>
> diff --git a/hgext/histedit.py b/hgext/histedit.py
> --- a/hgext/histedit.py
> +++ b/hgext/histedit.py
> @@ -173,6 +173,7 @@
>   import errno
>   import os
>   import sys
> +import itertools
>
>   from mercurial import bundle2
>   from mercurial import cmdutil
> @@ -1386,13 +1387,48 @@
>                   hint=_('use "drop %s" to discard, see also: '
>                          '"hg help -e histedit.config"') % missing[0][:12])
>
> +def adjustreplacementsfrommarkers(repo, oldreplacements):
> +    """Adjust replacements from obsolescense markers
> +
> +    Replacements structure is originally generated based on
> +    histedit's state and does not account for changes that are
> +    not recorded there. This function fixes that by adding
> +    data read from obsolescense markers"""
> +    if not obsolete.isenabled(repo, obsolete.createmarkersopt):
> +        return oldreplacements
> +
> +    unfi = repo.unfiltered()
> +    newreplacements = list(oldreplacements)
> +    oldsuccs = itertools.imap(lambda r: r[1], oldreplacements)

So the value of itertools is low

   oldsuccss = [r[1] for r in oldreplacements] #shorted and clearer.

Are you okay with see that replace inflight ?

> +    # successors that have already been added to succstocheck once
> +    seensuccs = set().union(*oldsuccs)

We should document your trick here. it's smart but fairly obscure.

A comment can probably be introduced in flight if you provide it here.

> +    succstocheck = list(seensuccs)
> +    while succstocheck:
> +        n = succstocheck.pop()
> +        try:
> +            ctx = unfi[n]
> +        except error.RepoError:
> +            # node unknown locally, should be treated as replaced
> +            newreplacements.append((n, ()))
> +            continue
> +
> +        for marker in obsolete.successormarkers(ctx):
> +            nsuccs = marker.succnodes()
> +            newreplacements.append((n, nsuccs))
> +            for nsucc in nsuccs:
> +                if nsucc not in seensuccs:
> +                    seensuccs.add(nsucc)
> +                    succstocheck.append(nsucc)
> +
> +    return newreplacements
> +
>   def processreplacement(state):
>       """process the list of replacements to return
>
>       1) the final mapping between original and created nodes
>       2) the list of temporary node created by histedit
>       3) the list of new commit created by histedit"""
> -    replacements = state.replacements
> +    replacements = adjustreplacementsfrommarkers(state.repo, state.replacements)
>       allsuccs = set()
>       replaced = set()
>       fullmapping = {}
> diff --git a/tests/test-histedit-obsolete.t b/tests/test-histedit-obsolete.t
> --- a/tests/test-histedit-obsolete.t
> +++ b/tests/test-histedit-obsolete.t
> @@ -14,6 +14,36 @@
>     > rebase=
>     > EOF
>
> +Test that histedit learns about obsoletions not stored in histedit state
> +  $ hg init boo
> +  $ cd boo
> +  $ echo a > a
> +  $ hg ci -Am a
> +  adding a
> +  $ echo a > b
> +  $ echo a > c
> +  $ echo a > c
> +  $ hg ci -Am b
> +  adding b
> +  adding c
> +  $ echo a > d
> +  $ hg ci -Am c
> +  adding d
> +  $ echo "pick `hg log -r 0 -T '{node|short}'`" > plan
> +  $ echo "pick `hg log -r 2 -T '{node|short}'`" >> plan
> +  $ echo "edit `hg log -r 1 -T '{node|short}'`" >> plan
> +  $ hg histedit -r 'all()' --commands plan
> +  Editing (1b2d564fad96), you may commit or record as needed now.
> +  (hg histedit --continue to resume)
> +  [1]
> +  $ hg st
> +  A b
> +  A c
> +  ? plan
> +  $ hg commit --amend b
> +  $ hg histedit --continue
> +  $ cd ..
> +
>     $ hg init base
>     $ cd base
>
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
>

-- 
Pierre-Yves David


More information about the Mercurial-devel mailing list