# HG changeset patch # User Pierre-Yves David # Date 1451832696 -3600 # Node ID ec4fae88831d857c60fc5dce40d11e4f5188d0b3 # Parent 0e9821f54ef2b274e94624e91396fb3067cfb480# Parent dcfe3afe548bca7c8195a3750440dc29e82d5ad1 merge with the rest of stable diff -r 0e9821f54ef2 -r ec4fae88831d README --- a/README Wed Dec 30 03:48:11 2015 +0530 +++ b/README Sun Jan 03 15:51:36 2016 +0100 @@ -42,10 +42,15 @@ for guidelines on the patch description. Please don't forget to update and run the tests when you fix a bug or -add a feature. To run the tests: +add a feature. To run the tests, you need a working copy of Mercurial, +say in $HGSRC: cd tests - python run-tests.py --with-hg=/path/to/hg + python $HGSRC/tests/run-tests.py --with-hg=$HGSRC/hg + +(evolve's stable and default branches correspond to Mercurial's stable +and default branches. So to test evolve from default, you need +Mercurial on default.) Changelog @@ -55,6 +60,11 @@ - split: add a new command to split changesets +5.2.2 -- + +- no longer lock the repository for `hg parents` (issue4895) +- updated help for the `evolve` command + 5.2.1 -- 2015-11-02 - add compatibility with Mercurial 3.6 diff -r 0e9821f54ef2 -r ec4fae88831d hgext/evolve.py --- a/hgext/evolve.py Wed Dec 30 03:48:11 2015 +0530 +++ b/hgext/evolve.py Sun Jan 03 15:51:36 2016 +0100 @@ -147,8 +147,8 @@ class exthelper(object): """Helper for modular extension setup - A single helper should be instanciated for each extension. Helper - methods are then used as decorator for various purpose. + A single helper should be instantiated for each extension. Helper + methods are then used as decorators for various purpose. All decorators return the original function and may be chained. """ @@ -678,16 +678,19 @@ # This section take care of issue warning to the user when troubles appear + +def _warnobsoletewc(ui, repo): + if repo['.'].obsolete(): + ui.warn(_('working directory parent is obsolete!\n')) + if (not ui.quiet) and obsolete.isenabled(repo, commandopt): + ui.warn(_('(use "hg evolve" to update to its successor)\n')) + @eh.wrapcommand("update") -@eh.wrapcommand("parents") @eh.wrapcommand("pull") def wrapmayobsoletewc(origfn, ui, repo, *args, **opts): """Warn that the working directory parent is an obsolete changeset""" def warnobsolete(): - if repo['.'].obsolete(): - ui.warn(_('working directory parent is obsolete!\n')) - if (not ui.quiet) and obsolete.isenabled(repo, commandopt): - ui.warn(_('(use "hg evolve" to update to its successor)\n')) + _warnobsoletewc(ui, repo) wlock = None try: wlock = repo.wlock() @@ -697,6 +700,12 @@ lockmod.release(wlock) return res +@eh.wrapcommand("parents") +def wrapparents(origfn, ui, repo, *args, **opts): + res = origfn(ui, repo, *args, **opts) + _warnobsoletewc(ui, repo) + return res + # XXX this could wrap transaction code # XXX (but this is a bit a layer violation) @eh.wrapcommand("commit") @@ -786,7 +795,7 @@ if histedit: extensions.wrapcommand(histedit.cmdtable, 'histedit', warnobserrors) except KeyError: - pass # rebase not found + pass # histedit not found ##################################################################### ### Old Evolve extension content ### @@ -1119,11 +1128,12 @@ @command('debugrecordpruneparents', [], '') def cmddebugrecordpruneparents(ui, repo): - """add parents data to prune markers when possible - - This commands search the repo for prune markers without parent information. - If the pruned node is locally known, a new markers with parent data is - created.""" + """add parent data to prune markers when possible + + This command searches the repo for prune markers without parent information. + If the pruned node is locally known, it creates a new marker with parent + data. + """ pgop = 'reading markers' # lock from the beginning to prevent race @@ -1155,6 +1165,7 @@ @command('debugobsstorestat', [], '') def cmddebugobsstorestat(ui, repo): + """print statistics about obsolescence markers in the repo""" def _updateclustermap(nodes, mark, clustersmap): c = (set(nodes), set([mark])) toproceed = set(nodes) @@ -1172,7 +1183,6 @@ c = other clustersmap[n] = c - """print statistic about obsolescence markers in the repo""" store = repo.obsstore unfi = repo.unfiltered() nm = unfi.changelog.nodemap @@ -1384,7 +1394,7 @@ ui.status(_('working directory is now at %s\n') % repo['.']) class MultipleSuccessorsError(RuntimeError): - """Exception raised by _singlesuccessor when multiple sucessors sets exists + """Exception raised by _singlesuccessor when multiple successor sets exists The object contains the list of successorssets in its 'successorssets' attribute to call to easily recover. @@ -1487,14 +1497,14 @@ def _orderrevs(repo, revs): """Compute an ordering to solve instability for the given revs - - Takes revs a list of instable revisions - - - Returns the same revisions ordered to solve their instability from the + revs is a list of unstable revisions. + + Returns the same revisions ordered to solve their instability from the bottom to the top of the stack that the stabilization process will produce eventually. - This ensure the minimal number of stabilization as we can stabilize each - revision on its final, stabilized, destination. + This ensures the minimal number of stabilizations, as we can stabilize each + revision on its final stabilized destination. """ # Step 1: Build the dependency graph dependencies, rdependencies = builddependencies(repo, revs) @@ -1535,38 +1545,66 @@ ] + mergetoolopts, _('[OPTIONS]...')) def evolve(ui, repo, **opts): - """solve troubles in your repository - - - rebase unstable changesets to make them stable again, - - create proper diffs from bumped changesets, - - fuse divergent changesets back together, - - update to a successor if the working directory parent is - obsolete - - If no argument are passed and the current working copy parent is obsolete, - :hg:`evolve` will update the working copy to the successors of this working - copy parent. If the working copy parent is not obsolete (and still no - argument passed) each invocation of :hg:`evolve` will evolve a single - unstable changeset, It will only select a changeset to be evolved if it - will result in a new children for the current working copy parent or its - descendants. The working copy will be updated on the result - (this last behavior will most likely to change in the future). - You can evolve all the unstable changesets that will be evolved on the - parent of the working copy and all its descendants recursively by using - :hg:`evolve` --all. - - You can decide to evolve other categories of trouble using the --divergent - and --bumped flags. If no other option are specified, this will try to - solve the specified troubles for the working copy parent. - - You can also evolve changesets affected by troubles of the selected - category using the --rev options. You can pick the next one anywhere in the - repo using --any. - - You can evolve all the changesets affected by troubles of the selected - category using --all --any. - - The working directory is updated to the newly created revision. + """solve troubled changesets in your repository + + Modifying history can lead to various types of troubled changesets: unstable, + bumped, or divergent. The evolve command resolves your troubles by executing one + of the following actions: + + - update working copy to a successor + - rebase an unstable changeset + - extract the desired changes from a bumped changeset + - fuse divergent changesets back together + + If you pass no arguments, evolve works in automatic mode: it will execute a + single action to reduce instability related to your working copy. There are two + cases for this action. First, if the parent of your working copy is obsolete, + evolve updates to the parent's successor. Second, if the working copy parent is + not obsolete but has obsolete predecessors, then evolve determines if there is an + unstable changeset that can be rebased onto the working copy parent in order to + reduce instability. If so, evolve rebases that changeset. If not, evolve refuses + to guess your intention, and gives a hint about what you might want to do next. + + Any time evolve creates a changeset, it updates the working copy to the new + changeset. (Currently, every successful evolve operation involves an update as + well; this may change in future.) + + Automatic mode only handles common use cases. For example, it avoids taking + action in the case of ambiguity, and it ignores unstable changesets that are not + related to your working copy. It also refuses to solve bumped or divergent + changesets unless you explicity request such behavior (see below). + + Eliminating all instability around your working copy may require multiple + invocations of :hg:`evolve`. Alternately, use ``--all`` to recursively select and + evolve all unstable changesets that can be rebased onto the working copy parent. + This is more powerful than successive invocations, since ``--all`` handles + ambiguous cases (e.g. unstable changesets with multiple children) by evolving all + branches. + + When your repository cannot be handled by automatic mode, you might need to use + ``--rev`` to specify a changeset to evolve. For example, if you have an unstable + changeset that is not related to the working copy parent, you could use ``--rev`` + to evolve it. Or, if some changeset has multiple unstable children, evolve in + automatic mode refuses to guess which one to evolve; you have to use ``--rev`` + in that case. + + Alternately, ``--any`` makes evolve search for the next evolvable changeset + regardless of whether it is related to the working copy parent. + + You can supply multiple revisions to evolve multiple troubled changesets in a + single invocation. In revset terms, ``--any`` is equivalent to ``--rev + first(unstable())``. ``--rev`` and ``--all`` are mutually exclusive, as are + ``--rev`` and ``--any``. + + ``hg evolve --any --all`` is useful for cleaning up instability across all + branches, letting evolve figure out the appropriate order and destination. + + When you have troubled changesets that are not unstable, :hg:`evolve` refuses to + consider them unless you specify the category of trouble you wish to resolve, + with ``--bumped`` or ``--divergent``. These options are currently mutually + exclusive with each other and with ``--unstable`` (the default). You can combine + ``--bumped`` or ``--divergent`` with ``--rev``, ``--all``, or ``--any``. + """ # Options @@ -1710,7 +1748,7 @@ def _solveunstable(ui, repo, orig, dryrun=False, confirm=False, progresscb=None): - """Stabilize a unstable changeset""" + """Stabilize an unstable changeset""" obs = orig.parents()[0] if not obs.obsolete() and len(orig.parents()) == 2: obs = orig.parents()[1] # second parent is obsolete ? @@ -2017,7 +2055,9 @@ ('n', 'dry-run', False, _('do not perform actions, just print what would be done'))], '[OPTION]...') def cmdprevious(ui, repo, **opts): - """update to parent and display summary lines""" + """update to parent revision + + Displays the summary line of the destination for clarity.""" wkctx = repo[None] wparents = wkctx.parents() dryrunopt = opts['dry_run'] @@ -2068,11 +2108,12 @@ ('n', 'dry-run', False, _('do not perform actions, just print what would be done'))], '[OPTION]...') def cmdnext(ui, repo, **opts): - """update to next child - - You can use the --evolve flag to get unstable children evolved on demand. - - The summary line of the destination is displayed for clarity""" + """update to next child revision + + Use the ``--evolve`` flag to evolve unstable children on demand. + + Displays the summary line of the destination for clarity. + """ wkctx = repo[None] wparents = wkctx.parents() dryrunopt = opts['dry_run'] @@ -2211,25 +2252,26 @@ def cmdprune(ui, repo, *revs, **opts): """hide changesets by marking them obsolete - Obsolete changesets becomes invisible to all commands. - - Unpruned descendants of pruned changesets becomes "unstable". Use the - :hg:`evolve` to handle such situation. - - When the working directory parent is pruned, the repository is updated to a - non-obsolete parent. - - You can use the ``--succ`` option to inform mercurial that a newer version - of the pruned changeset exists. - - You can use the ``--biject`` option to specify a 1-1 (bijection) between - revisions to prune and successor changesets. This option may be removed in - a future release (with the functionality absorbed automatically). - - If you specify multiple revisions in --succ, you are recording a "split" - and have to acknowledge it by usng --split. The same logic apply when you - prune multiple changesets with a single successors, this will record a - "fold" requires a --fold flag. + Pruned changesets are obsolete with no successors. If they also have no + descendants, they are hidden (invisible to all commands). + + Non-obsolete descendants of pruned changesets become "unstable". Use :hg:`evolve` + to handle this situation. + + When you prune the parent of your working copy, Mercurial updates the working + copy to a non-obsolete parent. + + You can use ``--succ`` to tell Mercurial that a newer version (successor) of the + pruned changeset exists. Mercurial records successor revisions in obsolescence + markers. + + You can use the ``--biject`` option to specify a 1-1 mapping (bijection) between + revisions to pruned (precursor) and successor changesets. This option may be + removed in a future release (with the functionality provided automatically). + + If you specify multiple revisions in ``--succ``, you are recording a "split" and + must acknowledge it by passing ``--split``. Similarly, when you prune multiple + changesets with a single successor, you must pass the ``--fold`` option. """ revs = scmutil.revrange(repo, list(revs) + opts.get('rev')) succs = opts['new'] + opts['succ'] @@ -2624,12 +2666,12 @@ ] + commitopts + commitopts2, _('hg split [OPTION]... [-r] REV')) def cmdsplit(ui, repo, *revs, **opts): - """Split the current commit using interactive selection (EXPERIMENTAL) - - By default, split the current revision by prompting for all its hunk to be + """split a changeset into smaller changesets (EXPERIMENTAL) + + By default, split the current revision by prompting for all its hunks to be redistributed into new changesets. - Use --rev for splitting a given changeset instead. + Use --rev to split a given changeset instead. """ tr = wlock = lock = None newcommits = []