Patchwork [4,of,4,evolve-ext] evolve: add --rev option to the evolve command

login
register
mail settings
Submitter Laurent Charignon
Date May 5, 2015, 9:29 p.m.
Message ID <0e29ac55b21ab929cca0.1430861388@lcharignon-mbp.local>
Download mbox | patch
Permalink /patch/8910/
State Changes Requested
Headers show

Comments

Laurent Charignon - May 5, 2015, 9:29 p.m.
# HG changeset patch
# User Laurent Charignon <lcharignon@fb.com>
# Date 1430861159 25200
#      Tue May 05 14:25:59 2015 -0700
# Node ID 0e29ac55b21ab929cca0d68045a98c490a6bac23
# Parent  0af82f6387fce507cd856aa0866534af0be65c98
evolve: add --rev option to the evolve command

This patch is part of a series of patches to refactor the evolve method and
make it more readable. We introduce a new --rev flag to specify a revset
where to solve the troubles instead of looking from the parent changeset.
All add a test checks that --rev  works with several commits
Pierre-Yves David - May 5, 2015, 10:18 p.m.
On 05/05/2015 02:29 PM, Laurent Charignon wrote:
> # HG changeset patch
> # User Laurent Charignon <lcharignon@fb.com>
> # Date 1430861159 25200
> #      Tue May 05 14:25:59 2015 -0700
> # Node ID 0e29ac55b21ab929cca0d68045a98c490a6bac23
> # Parent  0af82f6387fce507cd856aa0866534af0be65c98
> evolve: add --rev option to the evolve command
>
> This patch is part of a series of patches to refactor the evolve method and
> make it more readable. We introduce a new --rev flag to specify a revset
> where to solve the troubles instead of looking from the parent changeset.
> All add a test checks that --rev  works with several commits
>
> diff --git a/hgext/evolve.py b/hgext/evolve.py
> --- a/hgext/evolve.py
> +++ b/hgext/evolve.py
> @@ -1213,12 +1213,14 @@
>       else:
>           ui.write_err(_('no troubled changesets\n'))
>           return 1
> +
>   @command('^evolve|stabilize|solve',
>       [('n', 'dry-run', False,
>           'do not perform actions, just print what would be done'),
>        ('', 'confirm', False,
>           'ask for confirmation before performing the action'),
>       ('A', 'any', False, 'also consider troubled changesets unrelated to current working directory'),
> +    ('r', 'rev', '', 'revset to find troubles in'),

Not sure if using "revset" is very clear here. you usually just talk 
about "revs". What about

  'revisions to be evolved'

or

  'solves troubles of theses revisions'

>       ('a', 'all', False, 'evolve all troubled changesets in the repo '
>                           '(implies any)'),
>       ('c', 'continue', False, 'continue an interrupted evolution'),
> @@ -1249,12 +1251,14 @@
>       The working directory is updated to the newly created revision.
>       """
>
> +    # Options
>       contopt = opts['continue']
>       anyopt = opts['any']
>       allopt = opts['all']
>       startnode = repo['.']
>       dryrunopt = opts['dry_run']
>       confirmopt = opts['confirm']
> +    revopt = opts['rev']
>       ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'evolve')
>       troubled = set(repo.revs('troubled()'))
>
> @@ -1264,7 +1268,7 @@
>       showprogress = allopt
>
>       def progresscb():
> -        if allopt:
> +        if revopt or allopt:
>               ui.progress('evolve', seen, unit='changesets', total=count)
>
>       def cleanup(ui, repo, startnode, showprogress):
> @@ -1281,9 +1285,25 @@
>               raise util.Abort('cannot specify both "--all" and "--continue"')
>           graftcmd = commands.table['graft'][0]
>           return graftcmd(ui, repo, old_obsolete=True, **{'continue': True})
> -
> +    # Rev specified on the commands line
> +    if revopt:
> +        revs = set(repo.revs(revopt))
> +        troubled = set(repo.revs('troubled()'))
> +        _revs = revs & troubled
> +        if not _revs:
> +            ui.write_err("No troubled changes in the specified revset")
> +        else:
> +            # For the progress bar to show
> +            count = len(_revs)
> +            for rev in _revs:
> +                progresscb()
> +                _solveone(ui, repo, repo[rev], dryrunopt, confirmopt,
> +                        progresscb)
> +                seen += 1
> +            progresscb()
> +            cleanup(ui, repo, startnode, showprogress)
> +            return

I'm a bit sad to see a whole new block added instead of moving to a:

1) list revision we need to evolve
1.a) if --rev, then use this list (well, all unstable in it).
1.b) if --all, then use all unstables.
2.c) else just pick the next one.

This approach would probably cause a couple of issue where evolve won't 
evolve everything (case where stuff are evolved in the wrong order, 
multiple troubles on a revision, etc), but is would more in the right 
direction.

I would be okay with evolve --all "regressing" for such corner case 
during a couple of revision in such case is it help moving in the right 
direction and we have the rest of the stack making things up to a 
sensible behavior.
In all case you planning to unify the case soon, taking the above corner 
case in consideration ?

(also, usual growling about 'return' statement in the middle of a function)


>       nexttrouble = _picknexttroubled(ui, repo, anyopt or allopt)
> -
>       # No trouble to resolve
>       if not nexttrouble:
>           return handlenotrouble(ui, repo, startnode, dryrunopt)
> diff --git a/tests/test-evolve.t b/tests/test-evolve.t
> --- a/tests/test-evolve.t
> +++ b/tests/test-evolve.t
> @@ -887,3 +887,140 @@
>     working directory is now at f37ed7a60f43
>     $ ls .hg/bookmarks*
>     .hg/bookmarks
> +
> +Possibility to select what trouble to solve first, asking for bumped before
> +divergent
> +  $ hg up 10
> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  $ hg revert -r 11 --all
> +  reverting a
> +  $ hg log -G --template '{rev} [{branch}] {desc|firstline}\n'
> +  o  11 [mybranch] a2
> +  |
> +  @  10 [default] a1__
> +  |
> +  | o  9 [mybranch] a3
> +  | |
> +  | x  8 [mybranch] a2
> +  | |
> +  | x  7 [default] a1_
> +  |/
> +  o  0 [default] a0
> +
> +  $ echo "hello world" > newfile
> +  $ hg add newfile
> +  $ hg commit -m "add new file bumped" -o 11
> +  $ hg phase --hidden --public 11
> +  1 new bumped changesets
> +  $ hg glog
> +  @  12	: add new file bumped - test
> +  |
> +  | o  11	: a2 - test
> +  |/
> +  o  10	testbookmark: a1__ - test
> +  |
> +  | o  9	: a3 - test
> +  | |
> +  | x  8	: a2 - test
> +  | |
> +  | x  7	: a1_ - test
> +  |/
> +  o  0	: a0 - test
> +
> +
> +Now we have a bumped and an unstable changeset, we solve the bumped first
> +normally the unstable changeset would be solve first
> +
> +  $ hg glog
> +  @  12	: add new file bumped - test
> +  |
> +  | o  11	: a2 - test
> +  |/
> +  o  10	testbookmark: a1__ - test
> +  |
> +  | o  9	: a3 - test
> +  | |
> +  | x  8	: a2 - test
> +  | |
> +  | x  7	: a1_ - test
> +  |/
> +  o  0	: a0 - test
> +
> +  $ hg evolve -r 12 --hidden

You should not need the --hidden there.

> +  recreate:[12] add new file bumped
> +  atop:[11] a2
> +  computing new diff
> +  committed as d66b1e328488
> +  working directory is now at d66b1e328488
> +  $ hg evolve --any
> +  move:[9] a3
> +  atop:[13] bumped update to f37ed7a60f43:
> +  working directory is now at 7d2ce5f38f9b
> +Check that we can resolve troubles in a revset with more than one commit

What is the current implementation behavior is there is multiple 
troubles on a the changeset in --rev. What is your final plan?

> +  $ hg up 14 -C
> +  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  $ mkcommit gg
> +  $ hg up 14
> +  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
> +  $ mkcommit gh
> +  created new head
> +  $ hg up 14
> +  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
> +  $ echo "newline\nnewline" >> a
> +  $ hg glog
> +  o  16	: add gh - test
> +  |
> +  | o  15	: add gg - test
> +  |/
> +  @  14	: a3 - test
> +  |
> +  o  13	: bumped update to f37ed7a60f43: - test
> +  |
> +  o  11	: a2 - test
> +  |
> +  o  10	testbookmark: a1__ - test
> +  |
> +  o  0	: a0 - test
> +
> +  $ hg amend
> +  2 new unstable changesets
> +  $ hg glog
> +  @  18	: a3 - test
> +  |
> +  | o  16	: add gh - test
> +  | |
> +  | | o  15	: add gg - test
> +  | |/
> +  | x  14	: a3 - test
> +  |/
> +  o  13	: bumped update to f37ed7a60f43: - test
> +  |
> +  o  11	: a2 - test
> +  |
> +  o  10	testbookmark: a1__ - test
> +  |
> +  o  0	: a0 - test
> +
> +  $ hg evolve --rev "14::" --hidden

Same non-necessary --hidden things

> +  move:[16] add gh
> +  atop:[18] a3
> +  move:[15] add gg
> +  atop:[18] a3
> +  working directory is now at 10ffdd7e3cc9
> +  $ hg glog
> +  @  20	: add gg - test
> +  |
> +  | o  19	: add gh - test
> +  |/
> +  o  18	: a3 - test
> +  |
> +  o  13	: bumped update to f37ed7a60f43: - test
> +  |
> +  o  11	: a2 - test
> +  |
> +  o  10	testbookmark: a1__ - test
> +  |
> +  o  0	: a0 - test
> +
> +
> +
Laurent Charignon - May 5, 2015, 10:52 p.m.
On 5/5/15, 3:18 PM, "Pierre-Yves David" <pierre-yves.david@ens-lyon.org>
wrote:

>
>
>On 05/05/2015 02:29 PM, Laurent Charignon wrote:
>> # HG changeset patch
>> # User Laurent Charignon <lcharignon@fb.com>
>> # Date 1430861159 25200
>> #      Tue May 05 14:25:59 2015 -0700
>> # Node ID 0e29ac55b21ab929cca0d68045a98c490a6bac23
>> # Parent  0af82f6387fce507cd856aa0866534af0be65c98
>> evolve: add --rev option to the evolve command
>>
>> This patch is part of a series of patches to refactor the evolve method
>>and
>> make it more readable. We introduce a new --rev flag to specify a revset
>> where to solve the troubles instead of looking from the parent
>>changeset.
>> All add a test checks that --rev  works with several commits
>>
>> diff --git a/hgext/evolve.py b/hgext/evolve.py
>> --- a/hgext/evolve.py
>> +++ b/hgext/evolve.py
>> @@ -1213,12 +1213,14 @@
>>       else:
>>           ui.write_err(_('no troubled changesets\n'))
>>           return 1
>> +
>>   @command('^evolve|stabilize|solve',
>>       [('n', 'dry-run', False,
>>           'do not perform actions, just print what would be done'),
>>        ('', 'confirm', False,
>>           'ask for confirmation before performing the action'),
>>       ('A', 'any', False, 'also consider troubled changesets unrelated
>>to current working directory'),
>> +    ('r', 'rev', '', 'revset to find troubles in'),
>
>Not sure if using "revset" is very clear here. you usually just talk
>about "revs". What about
>
>  'revisions to be evolved'
>
>or
>
>  'solves troubles of theses revisions'
>
>>       ('a', 'all', False, 'evolve all troubled changesets in the repo '
>>                           '(implies any)'),
>>       ('c', 'continue', False, 'continue an interrupted evolution'),
>> @@ -1249,12 +1251,14 @@
>>       The working directory is updated to the newly created revision.
>>       """
>>
>> +    # Options
>>       contopt = opts['continue']
>>       anyopt = opts['any']
>>       allopt = opts['all']
>>       startnode = repo['.']
>>       dryrunopt = opts['dry_run']
>>       confirmopt = opts['confirm']
>> +    revopt = opts['rev']
>>       ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'evolve')
>>       troubled = set(repo.revs('troubled()'))
>>
>> @@ -1264,7 +1268,7 @@
>>       showprogress = allopt
>>
>>       def progresscb():
>> -        if allopt:
>> +        if revopt or allopt:
>>               ui.progress('evolve', seen, unit='changesets',
>>total=count)
>>
>>       def cleanup(ui, repo, startnode, showprogress):
>> @@ -1281,9 +1285,25 @@
>>               raise util.Abort('cannot specify both "--all" and
>>"--continue"')
>>           graftcmd = commands.table['graft'][0]
>>           return graftcmd(ui, repo, old_obsolete=True, **{'continue':
>>True})
>> -
>> +    # Rev specified on the commands line
>> +    if revopt:
>> +        revs = set(repo.revs(revopt))
>> +        troubled = set(repo.revs('troubled()'))
>> +        _revs = revs & troubled
>> +        if not _revs:
>> +            ui.write_err("No troubled changes in the specified revset")
>> +        else:
>> +            # For the progress bar to show
>> +            count = len(_revs)
>> +            for rev in _revs:
>> +                progresscb()
>> +                _solveone(ui, repo, repo[rev], dryrunopt, confirmopt,
>> +                        progresscb)
>> +                seen += 1
>> +            progresscb()
>> +            cleanup(ui, repo, startnode, showprogress)
>> +            return
>
>I'm a bit sad to see a whole new block added instead of moving to a:
>
>1) list revision we need to evolve
>1.a) if --rev, then use this list (well, all unstable in it).
>1.b) if --all, then use all unstables.
>2.c) else just pick the next one.
>
>This approach would probably cause a couple of issue where evolve won't
>evolve everything (case where stuff are evolved in the wrong order,
>multiple troubles on a revision, etc), but is would more in the right
>direction.
>
>I would be okay with evolve --all "regressing" for such corner case
>during a couple of revision in such case is it help moving in the right
>direction and we have the rest of the stack making things up to a
>sensible behavior.
>In all case you planning to unify the case soon, taking the above corner
>case in consideration ?

I am actually doing exactly what you describe in the patch series coming
up after :).
I just wanted to do it bit by bit as we usually do.

>
>(also, usual growling about 'return' statement in the middle of a
>function)
>
>
>>       nexttrouble = _picknexttroubled(ui, repo, anyopt or allopt)
>> -
>>       # No trouble to resolve
>>       if not nexttrouble:
>>           return handlenotrouble(ui, repo, startnode, dryrunopt)
>> diff --git a/tests/test-evolve.t b/tests/test-evolve.t
>> --- a/tests/test-evolve.t
>> +++ b/tests/test-evolve.t
>> @@ -887,3 +887,140 @@
>>     working directory is now at f37ed7a60f43
>>     $ ls .hg/bookmarks*
>>     .hg/bookmarks
>> +
>> +Possibility to select what trouble to solve first, asking for bumped
>>before
>> +divergent
>> +  $ hg up 10
>> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
>> +  $ hg revert -r 11 --all
>> +  reverting a
>> +  $ hg log -G --template '{rev} [{branch}] {desc|firstline}\n'
>> +  o  11 [mybranch] a2
>> +  |
>> +  @  10 [default] a1__
>> +  |
>> +  | o  9 [mybranch] a3
>> +  | |
>> +  | x  8 [mybranch] a2
>> +  | |
>> +  | x  7 [default] a1_
>> +  |/
>> +  o  0 [default] a0
>> +
>> +  $ echo "hello world" > newfile
>> +  $ hg add newfile
>> +  $ hg commit -m "add new file bumped" -o 11
>> +  $ hg phase --hidden --public 11
>> +  1 new bumped changesets
>> +  $ hg glog
>> +  @  12	: add new file bumped - test
>> +  |
>> +  | o  11	: a2 - test
>> +  |/
>> +  o  10	testbookmark: a1__ - test
>> +  |
>> +  | o  9	: a3 - test
>> +  | |
>> +  | x  8	: a2 - test
>> +  | |
>> +  | x  7	: a1_ - test
>> +  |/
>> +  o  0	: a0 - test
>> +
>> +
>> +Now we have a bumped and an unstable changeset, we solve the bumped
>>first
>> +normally the unstable changeset would be solve first
>> +
>> +  $ hg glog
>> +  @  12	: add new file bumped - test
>> +  |
>> +  | o  11	: a2 - test
>> +  |/
>> +  o  10	testbookmark: a1__ - test
>> +  |
>> +  | o  9	: a3 - test
>> +  | |
>> +  | x  8	: a2 - test
>> +  | |
>> +  | x  7	: a1_ - test
>> +  |/
>> +  o  0	: a0 - test
>> +
>> +  $ hg evolve -r 12 --hidden
>
>You should not need the --hidden there.
>
>> +  recreate:[12] add new file bumped
>> +  atop:[11] a2
>> +  computing new diff
>> +  committed as d66b1e328488
>> +  working directory is now at d66b1e328488
>> +  $ hg evolve --any
>> +  move:[9] a3
>> +  atop:[13] bumped update to f37ed7a60f43:
>> +  working directory is now at 7d2ce5f38f9b
>> +Check that we can resolve troubles in a revset with more than one
>>commit
>
>What is the current implementation behavior is there is multiple
>troubles on a the changeset in --rev. What is your final plan?
>
>> +  $ hg up 14 -C
>> +  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
>> +  $ mkcommit gg
>> +  $ hg up 14
>> +  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
>> +  $ mkcommit gh
>> +  created new head
>> +  $ hg up 14
>> +  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
>> +  $ echo "newline\nnewline" >> a
>> +  $ hg glog
>> +  o  16	: add gh - test
>> +  |
>> +  | o  15	: add gg - test
>> +  |/
>> +  @  14	: a3 - test
>> +  |
>> +  o  13	: bumped update to f37ed7a60f43: - test
>> +  |
>> +  o  11	: a2 - test
>> +  |
>> +  o  10	testbookmark: a1__ - test
>> +  |
>> +  o  0	: a0 - test
>> +
>> +  $ hg amend
>> +  2 new unstable changesets
>> +  $ hg glog
>> +  @  18	: a3 - test
>> +  |
>> +  | o  16	: add gh - test
>> +  | |
>> +  | | o  15	: add gg - test
>> +  | |/
>> +  | x  14	: a3 - test
>> +  |/
>> +  o  13	: bumped update to f37ed7a60f43: - test
>> +  |
>> +  o  11	: a2 - test
>> +  |
>> +  o  10	testbookmark: a1__ - test
>> +  |
>> +  o  0	: a0 - test
>> +
>> +  $ hg evolve --rev "14::" --hidden
>
>Same non-necessary --hidden things
>
>> +  move:[16] add gh
>> +  atop:[18] a3
>> +  move:[15] add gg
>> +  atop:[18] a3
>> +  working directory is now at 10ffdd7e3cc9
>> +  $ hg glog
>> +  @  20	: add gg - test
>> +  |
>> +  | o  19	: add gh - test
>> +  |/
>> +  o  18	: a3 - test
>> +  |
>> +  o  13	: bumped update to f37ed7a60f43: - test
>> +  |
>> +  o  11	: a2 - test
>> +  |
>> +  o  10	testbookmark: a1__ - test
>> +  |
>> +  o  0	: a0 - test
>> +
>> +
>> +
>
>-- 
>Pierre-Yves David
Pierre-Yves David - May 5, 2015, 11:56 p.m.
On 05/05/2015 03:52 PM, Laurent Charignon wrote:
>
>
> On 5/5/15, 3:18 PM, "Pierre-Yves David" <pierre-yves.david@ens-lyon.org>
> wrote:
>
>>
>>
>> On 05/05/2015 02:29 PM, Laurent Charignon wrote:
>>> # HG changeset patch
>>> # User Laurent Charignon <lcharignon@fb.com>
>>> # Date 1430861159 25200
>>> #      Tue May 05 14:25:59 2015 -0700
>>> # Node ID 0e29ac55b21ab929cca0d68045a98c490a6bac23
>>> # Parent  0af82f6387fce507cd856aa0866534af0be65c98
>>> evolve: add --rev option to the evolve command
>>>
>>> This patch is part of a series of patches to refactor the evolve method
>>> and
>>> make it more readable. We introduce a new --rev flag to specify a revset
>>> where to solve the troubles instead of looking from the parent
>>> changeset.
>>> All add a test checks that --rev  works with several commits
>>>
>>> diff --git a/hgext/evolve.py b/hgext/evolve.py
>>> --- a/hgext/evolve.py
>>> +++ b/hgext/evolve.py
>>> @@ -1213,12 +1213,14 @@
>>>        else:
>>>            ui.write_err(_('no troubled changesets\n'))
>>>            return 1
>>> +
>>>    @command('^evolve|stabilize|solve',
>>>        [('n', 'dry-run', False,
>>>            'do not perform actions, just print what would be done'),
>>>         ('', 'confirm', False,
>>>            'ask for confirmation before performing the action'),
>>>        ('A', 'any', False, 'also consider troubled changesets unrelated
>>> to current working directory'),
>>> +    ('r', 'rev', '', 'revset to find troubles in'),
>>
>> Not sure if using "revset" is very clear here. you usually just talk
>> about "revs". What about
>>
>>   'revisions to be evolved'
>>
>> or
>>
>>   'solves troubles of theses revisions'
>>
>>>        ('a', 'all', False, 'evolve all troubled changesets in the repo '
>>>                            '(implies any)'),
>>>        ('c', 'continue', False, 'continue an interrupted evolution'),
>>> @@ -1249,12 +1251,14 @@
>>>        The working directory is updated to the newly created revision.
>>>        """
>>>
>>> +    # Options
>>>        contopt = opts['continue']
>>>        anyopt = opts['any']
>>>        allopt = opts['all']
>>>        startnode = repo['.']
>>>        dryrunopt = opts['dry_run']
>>>        confirmopt = opts['confirm']
>>> +    revopt = opts['rev']
>>>        ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'evolve')
>>>        troubled = set(repo.revs('troubled()'))
>>>
>>> @@ -1264,7 +1268,7 @@
>>>        showprogress = allopt
>>>
>>>        def progresscb():
>>> -        if allopt:
>>> +        if revopt or allopt:
>>>                ui.progress('evolve', seen, unit='changesets',
>>> total=count)
>>>
>>>        def cleanup(ui, repo, startnode, showprogress):
>>> @@ -1281,9 +1285,25 @@
>>>                raise util.Abort('cannot specify both "--all" and
>>> "--continue"')
>>>            graftcmd = commands.table['graft'][0]
>>>            return graftcmd(ui, repo, old_obsolete=True, **{'continue':
>>> True})
>>> -
>>> +    # Rev specified on the commands line
>>> +    if revopt:
>>> +        revs = set(repo.revs(revopt))
>>> +        troubled = set(repo.revs('troubled()'))
>>> +        _revs = revs & troubled
>>> +        if not _revs:
>>> +            ui.write_err("No troubled changes in the specified revset")
>>> +        else:
>>> +            # For the progress bar to show
>>> +            count = len(_revs)
>>> +            for rev in _revs:
>>> +                progresscb()
>>> +                _solveone(ui, repo, repo[rev], dryrunopt, confirmopt,
>>> +                        progresscb)
>>> +                seen += 1
>>> +            progresscb()
>>> +            cleanup(ui, repo, startnode, showprogress)
>>> +            return
>>
>> I'm a bit sad to see a whole new block added instead of moving to a:
>>
>> 1) list revision we need to evolve
>> 1.a) if --rev, then use this list (well, all unstable in it).
>> 1.b) if --all, then use all unstables.
>> 2.c) else just pick the next one.
>>
>> This approach would probably cause a couple of issue where evolve won't
>> evolve everything (case where stuff are evolved in the wrong order,
>> multiple troubles on a revision, etc), but is would more in the right
>> direction.
>>
>> I would be okay with evolve --all "regressing" for such corner case
>> during a couple of revision in such case is it help moving in the right
>> direction and we have the rest of the stack making things up to a
>> sensible behavior.
>> In all case you planning to unify the case soon, taking the above corner
>> case in consideration ?
>
> I am actually doing exactly what you describe in the patch series coming
> up after :).
> I just wanted to do it bit by bit as we usually do.

Deal!

Patch

diff --git a/hgext/evolve.py b/hgext/evolve.py
--- a/hgext/evolve.py
+++ b/hgext/evolve.py
@@ -1213,12 +1213,14 @@ 
     else:
         ui.write_err(_('no troubled changesets\n'))
         return 1
+
 @command('^evolve|stabilize|solve',
     [('n', 'dry-run', False,
         'do not perform actions, just print what would be done'),
      ('', 'confirm', False,
         'ask for confirmation before performing the action'),
     ('A', 'any', False, 'also consider troubled changesets unrelated to current working directory'),
+    ('r', 'rev', '', 'revset to find troubles in'),
     ('a', 'all', False, 'evolve all troubled changesets in the repo '
                         '(implies any)'),
     ('c', 'continue', False, 'continue an interrupted evolution'),
@@ -1249,12 +1251,14 @@ 
     The working directory is updated to the newly created revision.
     """
 
+    # Options
     contopt = opts['continue']
     anyopt = opts['any']
     allopt = opts['all']
     startnode = repo['.']
     dryrunopt = opts['dry_run']
     confirmopt = opts['confirm']
+    revopt = opts['rev']
     ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'evolve')
     troubled = set(repo.revs('troubled()'))
 
@@ -1264,7 +1268,7 @@ 
     showprogress = allopt
 
     def progresscb():
-        if allopt:
+        if revopt or allopt:
             ui.progress('evolve', seen, unit='changesets', total=count)
 
     def cleanup(ui, repo, startnode, showprogress):
@@ -1281,9 +1285,25 @@ 
             raise util.Abort('cannot specify both "--all" and "--continue"')
         graftcmd = commands.table['graft'][0]
         return graftcmd(ui, repo, old_obsolete=True, **{'continue': True})
-
+    # Rev specified on the commands line
+    if revopt:
+        revs = set(repo.revs(revopt))
+        troubled = set(repo.revs('troubled()'))
+        _revs = revs & troubled
+        if not _revs:
+            ui.write_err("No troubled changes in the specified revset")
+        else:
+            # For the progress bar to show
+            count = len(_revs)
+            for rev in _revs:
+                progresscb()
+                _solveone(ui, repo, repo[rev], dryrunopt, confirmopt, 
+                        progresscb)
+                seen += 1
+            progresscb()
+            cleanup(ui, repo, startnode, showprogress)
+            return
     nexttrouble = _picknexttroubled(ui, repo, anyopt or allopt)
- 
     # No trouble to resolve
     if not nexttrouble:
         return handlenotrouble(ui, repo, startnode, dryrunopt)
diff --git a/tests/test-evolve.t b/tests/test-evolve.t
--- a/tests/test-evolve.t
+++ b/tests/test-evolve.t
@@ -887,3 +887,140 @@ 
   working directory is now at f37ed7a60f43
   $ ls .hg/bookmarks*
   .hg/bookmarks
+
+Possibility to select what trouble to solve first, asking for bumped before
+divergent
+  $ hg up 10
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg revert -r 11 --all
+  reverting a
+  $ hg log -G --template '{rev} [{branch}] {desc|firstline}\n'
+  o  11 [mybranch] a2
+  |
+  @  10 [default] a1__
+  |
+  | o  9 [mybranch] a3
+  | |
+  | x  8 [mybranch] a2
+  | |
+  | x  7 [default] a1_
+  |/
+  o  0 [default] a0
+  
+  $ echo "hello world" > newfile
+  $ hg add newfile
+  $ hg commit -m "add new file bumped" -o 11
+  $ hg phase --hidden --public 11
+  1 new bumped changesets
+  $ hg glog
+  @  12	: add new file bumped - test
+  |
+  | o  11	: a2 - test
+  |/
+  o  10	testbookmark: a1__ - test
+  |
+  | o  9	: a3 - test
+  | |
+  | x  8	: a2 - test
+  | |
+  | x  7	: a1_ - test
+  |/
+  o  0	: a0 - test
+  
+
+Now we have a bumped and an unstable changeset, we solve the bumped first
+normally the unstable changeset would be solve first
+
+  $ hg glog
+  @  12	: add new file bumped - test
+  |
+  | o  11	: a2 - test
+  |/
+  o  10	testbookmark: a1__ - test
+  |
+  | o  9	: a3 - test
+  | |
+  | x  8	: a2 - test
+  | |
+  | x  7	: a1_ - test
+  |/
+  o  0	: a0 - test
+  
+  $ hg evolve -r 12 --hidden
+  recreate:[12] add new file bumped
+  atop:[11] a2
+  computing new diff
+  committed as d66b1e328488
+  working directory is now at d66b1e328488
+  $ hg evolve --any
+  move:[9] a3
+  atop:[13] bumped update to f37ed7a60f43:
+  working directory is now at 7d2ce5f38f9b
+Check that we can resolve troubles in a revset with more than one commit
+  $ hg up 14 -C
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ mkcommit gg
+  $ hg up 14 
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ mkcommit gh
+  created new head
+  $ hg up 14 
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ echo "newline\nnewline" >> a
+  $ hg glog
+  o  16	: add gh - test
+  |
+  | o  15	: add gg - test
+  |/
+  @  14	: a3 - test
+  |
+  o  13	: bumped update to f37ed7a60f43: - test
+  |
+  o  11	: a2 - test
+  |
+  o  10	testbookmark: a1__ - test
+  |
+  o  0	: a0 - test
+  
+  $ hg amend
+  2 new unstable changesets
+  $ hg glog
+  @  18	: a3 - test
+  |
+  | o  16	: add gh - test
+  | |
+  | | o  15	: add gg - test
+  | |/
+  | x  14	: a3 - test
+  |/
+  o  13	: bumped update to f37ed7a60f43: - test
+  |
+  o  11	: a2 - test
+  |
+  o  10	testbookmark: a1__ - test
+  |
+  o  0	: a0 - test
+  
+  $ hg evolve --rev "14::" --hidden
+  move:[16] add gh
+  atop:[18] a3
+  move:[15] add gg
+  atop:[18] a3
+  working directory is now at 10ffdd7e3cc9
+  $ hg glog
+  @  20	: add gg - test
+  |
+  | o  19	: add gh - test
+  |/
+  o  18	: a3 - test
+  |
+  o  13	: bumped update to f37ed7a60f43: - test
+  |
+  o  11	: a2 - test
+  |
+  o  10	testbookmark: a1__ - test
+  |
+  o  0	: a0 - test
+  
+
+