Commits

Pierre-Yves David  committed 40854e9 Merge

merge

  • Participants
  • Parent commits f727ebe, e6e47c4

Comments (0)

Files changed (22)

 It also:
 
     - enables the "Changeset Obsolescence" feature of mercurial,
-    - alters core commands and extensions that rewrite history to use
-      this feature,
-    - improves some aspect of the early implementation in 2.3
+    - issues several warning messages when troubles appear in your repository.
 
 **These extensions are experimental and are not meant for production.**
 
 Changelog
 ==================
 
+3.0.0 --
+
+- compatibility with 2.5
+
 2.2.0 --
 
 - make evolve smarter at picking next troubled to solved without --any

File debian/control

  Pierre-Yves David <pierre-yves.david@logilab.fr>,
 Standards-Version: 3.9.3
 Build-Depends:
- mercurial (>=2.4~),
- mercurial (<<2.5),
- mercurial-common (>=2.4~),
- mercurial-common (<<2.5),
+ mercurial (>=2.5~),
+ mercurial-common (>=2.5~),
  python,
  debhelper (>= 8),
  python-sphinx (>= 1.0.8),
 Depends:
  ${python:Depends},
  ${misc:Depends},
- mercurial (>= 2.4),
- mercurial (<<2.5),
+ mercurial (>= 2.5),
 Description: evolve extension for Mercurial
  This package provides the experimental "evolve" extension for the Mercurial
  DVCS.

File docs/evolve-collaboration.rst

 
     $ hg ci -m '[entities] remove magic'
 
-Instant patch ! Note how the default phase of this changeset is (still)
+Instant patch! Note how the default phase of this changeset is (still)
 in "draft" state.
 
 This is easily checkable::
 "publishing" since they do not have the notion of non-public changesets
 (or mutable history).
 
-During the transition from older mercurial servers to new ones, this will
+During the transition from older Mercurial servers to new ones, this will
 happen often, so be careful.
 
 Now let's come back to our patch. Next hour sees good progress and Alice
 
     $ hg amend -m '[entities] fix frobulator (closes #42)'
 
-Note that we also fix the commit message. (For recovering mq users: this
+Note that we also fix the commit message. (For recovering MQ users: this
 is just like "hg qrefresh -m").
 
 Before leaving, let's push to the central shared repository. That will
 brings her to yesterday's patch. Indeed the patch serial number has
 increased (827 still exists but has been obsoleted).
 
-She understands that his original patch has been altered. But how did it
+She understands that her original patch has been altered. But how did it
 evolve?
 
 The enhanced hgview shows the two patches. By default only the most
 Amend ... Stabilize
 --------------------
 
-Almost perfect ! Alice just needs to fix a half dozen grammar oddities in
+Almost perfect! Alice just needs to fix a half dozen grammar oddities in
 the new docstrings and it will be publishable.
 
 Then, another round of:
 
 Except that rebase is a destructive (it removes information from the
 repository), unrecoverable operation, and the "evolve + obsolete"
-combo, using changeset copy and obsolescence marker, provide evolution
+combo, using changeset copy and obsolescence marker, provides evolution
 semantics by only adding new information to the repository (but more
 on that later).
 

File docs/evolve-faq.rst

 To understand what the result of amend will be I use the two following
 aliases   [#]_::
 
-    # diff what amend will look likes
+    # diff what amend will look like
     pdiff=diff --rev .^
 
-    # status what amend will look likes
+    # status what amend will look like
     pstatus=status --rev .^
 
-It takes various options to pick an author, a date and the branch of the
-result... (see ``hg help amend`` for details).
+It takes various options to pick an author, a date, and the branch of the
+result (see ``hg help amend`` for details).
 
-This command can even be invoked on changesets with children (provided
-none is public) !
+This command can even be invoked on changesets with children, provided
+none are public.
 
-.. note:: the amend command is very similar to mq's ``qrefresh``, a ``refresh``
+.. note:: As the amend command is very similar to mq's ``qrefresh``, a ``refresh``
           alias for amend is also available. But note that contrary to
           ``qrefresh``, ``amend`` does not exclude changes on file not specified
           on the command line.
 Move a changeset: ``graft``
 ------------------------------------------------------------
 
-The graft command introduced in 2.0 allows to "copy changes from other
+The graft command introduced in 2.0 allows you to "copy changes from other
 branches onto the current branch".
 
 The graft command has been altered to allow the creation of an
 ------------------------------------------------------------
 
 While working on mutable part of the history you often need to move between
-mutable commit.
+mutable commits.
 
 You just need to use standard update to work with evolve. For convenience, you
-can use ``hg gup`` to move to children commit or ``hg gdown`` to move to working
-directory parent commit.
+can use ``hg gup`` to move to the child commit or ``hg gdown`` to move to the parent commit.
 
-.. note:: those command only exist for the convenience of getting qpush and qpop
+.. note:: Those commands only exist for the convenience of getting qpush and qpop
           feeling back.
 
 Collapse changesets: ``fold``
 ------------------------------------------------------------
 
-you can use ``hg fold`` to collapse multiple changesets in a single one.
+You can use ``hg fold`` to collapse multiple changesets in a single one.
 
 Getting changes out of a commit
 ------------------------------------------------------------
 
 To split on file boundaries, just use ``uncommit`` command.
 
-If you need fine-grained split, there is no official command for that yet.
+If you need a fine-grained split, there is no official command for that yet.
 However, it is easily achieved by manual operation::
 
   ### you want to split changeset A: 42
   # current changeset (.) and previous one (.^) replace A (42)
   $ hg prune --new . --new .^ 42
 
-For more complexe scenario we recommand the use of the histedit_ extension.
+For more complexe scenario we recommend the use of the histedit_ extension.
 
 .. _histedit: http://mercurial.selenic.com/wiki/HisteditExtension
 
 Whenever you are working on some changesets, it is more likely that a pull
 will, eventually, import new changesets in your tree.
 
-And it is likely that you will want your work in progress changiesets to be
+And it is likely that you will want your work in progress changesets to be
 rebased on the top of this newly imported subtree.
 
 Doing so is only a matter of rebasing.

File docs/evolve-good-practice.rst

 ..                Logilab SA        <contact@logilab.fr>
 
 -----------------------------------------
-Good pratice for (early) user of evolve
+Good practice for (early) users of evolve
 -----------------------------------------
 
 Avoid unstability
 Branch as much as possible
 --------------------------------
 
-This is not MQ, you are not constrainted to linear history.
+This is not MQ; you are not constrained to linear history.
 
 Making a branch per independent branch will help you avoid unstability
 and conflict.
 
-Rewrite you change only
+Rewrite your changes only
 ------------------------------------------------
 
 There is no descent conflict detection and handling right now.
 conflicts. Communicate with your fellow developers before trying to
 touch other people's work (which is a good pratice in any case).
 
-Using multiple branch will help you to achieve this goal.
+Using multiple branches will help you to achieve this goal.
 
-Prefer pushing unstability than touching other people changeset
-------------------------------------------------------------------
+Prefer pushing unstability to touching other people changesets
+--------------------------------------------------------------
 
 
 If you have children changesets from other people that you don't really care

File docs/from-mq.rst

 phase revset to display unfinished work only, and use templates to have
 the same kind of compact that the output of qseries has.
 
-This will result in something like that::
+This will result in something like::
 
   [alias]
   wip = log -r 'not public()' --template='{rev}:{node|short} {desc|firstline}\n'
 
 With evolve you handle standard changesets without an additional overlay.
 
-Standard changeset are created using hg commit as usual.::
+Standard changeset are created using hg commit as usual::
 
   $ hg commit
 
 set your changeset in the secret phase using the phase command.
 
 Note that you only need it for the first commit you want to be secret. Later
-commits will inherit their parents phase.
+commits will inherit their parent's phase.
 
 If you always want your new commit to be in the secret phase, your should
 consider updating your configuration:
 hg qref --exclude
 `````````````````````
 
-To remove changes from you current commit use::
+To remove changes from your current commit use::
 
   $ hg uncommit not-ready.txt
 
 hg qpop
 `````````
 
-The following command emulate the behavior of hg qpop:
+The following command emulates the behavior of hg qpop:
 
   $ hg gdown
 
 
   $ hg update
 
-.. note:: gdown and update allow movement with working directory changes applied
-          and gracefully merge them.
+.. note:: gdown and update allow movement with working directory
+          changes applied, and gracefully merge them.
 
 hg qpush
 ````````
 hg qdiff
 `````````
 
-``pdiff`` is an alias for `hg diff -r .^` it works as qdiff, but outside mq.
+``pdiff`` is an alias for `hg diff -r .^` It works like qdiff, but outside MQ.
 
 
 
 hg qfinish and hg qimport
 ````````````````````````````
 
-These are not necessary anymore. If you want to control exchange and
-mutability of changesets, see the phase feature
+These are not necessary anymore. If you want to control the
+mutability of changesets, see the phase feature.
 
 
 

File docs/index.rst

 Here are various materials on planned improvement to Mercurial regarding
 rewriting history.
 
-First read about what challenge arise while rewriting history and how we plan to
+First, read about what challenges arise while rewriting history and how we plan to
 solve them once and for all.
 
 .. toctree::
 The effort is split in two parts:
 
  * The **obsolescence marker** concept aims to provide an alternative to ``strip``
-   to get rid of changesets. This concept have been partially implemented since
+   to get rid of changesets. This concept has been partially implemented since
    Mercurial 2.3.
 
- * The **evolve** mercurial extension rewrites history using obsolete
+ * The **evolve** Mercurial extension rewrites history using obsolete
    *marker* under the hood.
 
 The first and most important step is by far the **obsolescence marker**. However
 ====================================
 
 Evolve is an experimental history rewriting extension that uses obsolete
-markers. It is inspired from MQ and pbranch but have multiple advantages over
+markers. It is inspired by MQ and pbranch but has multiple advantages over
 them:
 
 * Focus on your current work.
 
     You can focus your work on a single changeset and take care of adapting
-    descendent changeset later.
+    descendent changesets later.
 
 * Handle **non-linear history with branches and merges**
 
-* Rely internally on **robust merge** mechanism of mercurial.
+* Rely internally on Mercurial's **robust merge** mechanism.
 
-  Simple conflict are handled by real merge tools using appropriate ancestor.
-  Conflict are much rarer and much more user friendly.
+  Simple conflicts are handled by real merge tools using the appropriate ancestor.
+  Conflicts are much rarer and much more user friendly.
 
 *  Mutable history **fully available all the time**.
 
-  always use 'hg update' and forget about (un)applying patches to access the
+  Always use 'hg update' and forget about (un)applying patches to access the
   mutable part of your history.
 
 
-* Use only **plain changeset** and forget about patches. Evole will create and
+* Use only **plain changesets** and forget about patches. Evolve will create and
   exchange real changesets. Mutable history can be used in all usual operations:
   pull, push, log, diff, etc.
 
-* Allow **sharing and collaboration** mutable history without fear of duplicate
+* Allow **sharing and collaboration** mutable history without fear of duplicates
   (thanks to obsolete marker).
 
-* Cover all mq usage but guard.
+* Cover all MQ usage but guard.
 
 .. warning:: The evolve extension and obsolete markers are at an experimental
              stage. While using obsolete you willl likely be exposed to complex
              non-power users to test this at this stage.
 
              While numbered 1.0.0, the command line API of this version should
-             **not** be regarded as *stable*, command behavior, name and
-             options may change in future release or once integrated in
-             mercurial. It is still an immature extension, a lot of
-             features are still missing but there is no high risk of
+             **not** be regarded as *stable*: command behavior, name and
+             options may change in future releases or once integrated into
+             Mercurial. It is still an immature extension; a lot of
+             features are still missing but there is low risk of
              repository corruption.
 
-             Production ready version should hide such details to normal user.
+             Production-ready version should hide such details from normal users.
 
-The evolve extension requires mercurial 2.4 (older version supports 2.3 and 2.2)
+The evolve extension requires Mercurial 2.4 (older versions support 2.3 and 2.2)
 
 To enable the evolve extension use::
 
 
  ---
 
-For more information see documents below:
+For more information see the documents below:
 
 .. toctree::
    :maxdepth: 1
 Smart changeset deletion: Obsolete Marker
 ==========================================
 
-Obsolete marker is a powerful concept that allow mercurial to safely handle
+The obsolete marker is a powerful concept that allows Mercurial to safely handle
 history rewriting operations. It is a new type of relation between Mercurial
-changesets that track the result of history rewriting operations.
+changesets that tracks the result of history rewriting operations.
 
-This concept is simple to define and provides a very solid base to:
+This concept is simple to define and provides a very solid base for:
 
-- Very fast history rewriting operations,
+- very fast history rewriting operations
 
-- auditable and reversible history rewriting process,
+- auditable and reversible history rewriting process
 
-- clean final history,
+- clean final history
 
-- share and collaborate on mutable parts of the history,
+- share and collaborate on mutable parts of the history
 
-- gracefully handle history rewriting conflicts,
+- gracefully handle history rewriting conflicts
 
-- allow various history rewriting UI to collaborate with a underlying common API.
+- allow various history rewriting UI to collaborate with a underlying common API
 
  ---
 
-For more information see documents below
+For more information, see the documents below
 
 .. toctree::
    :maxdepth: 1
    obs-implementation
 
 
-Known limitation and bug
+Known limitations and bugs
 =================================
 
-Here is a list of know issue that will be fixed later:
+Here is a list of known issues that will be fixed later:
 
 
-* you need to provide to `graft --continue -O` if you started you
+* You need to provide to `graft --continue -O` if you started you
   graft using `-O`.
 
   you to manually specify target all the time.
 
-* trying to exchange obsolete marker with a static http repo will crash.
+* Trying to exchange obsolete marker with a static http repo will crash.
 
 * Extinct changesets are hidden using the *hidden* feature of mercurial only
   supported by a few commands.
 
-  Only ``hg log``, ``hgview`` and `hg glog` support it. ``hg head`` or other visual viewer don't.
+  Only ``hg log``, ``hgview`` and `hg glog` support it. Neither ``hg heads`` nor other visual viewers do.
 
-* hg heads show extinct changeset
+* hg heads shows extinct changesets.

File docs/instability.rst

 
 XXX starts by talking about getting ride of changeset.
 
-DVCSes bring two new major concepts to the Version Control Scene:
+DVCSes bring two new major concepts to the version control scene:
 
     * History is organized as a robust DAG,
     * History can be rewritten.
 
     * Full snapshot of the versioned content,
     * Reference to the previous full snapshot used to build the new one,
-    * A description of the change who lead from the old content to the new old.
+    * A description of the change which leads from the old content to the new content.
 
-All three elements are to compute a *unique* hash that identify the changeset
+All three elements are used to compute a *unique* hash that identifies the changeset
 (with various other metadata). This identification is a key part of DVCS design.
 
-This is a very useful property because Changing B parent means
-changing B content too. This requires the creation of **another**
+This is a very useful property because changing B's parent means
+changing B's content too. This requires the creation of **another**
 changeset, which is semantically good.
 
 .. figure:: ./figures/edit-is-rewrite-step2.svg
 history. I'm calling them *obsolete* changesets.
 
 
-But rewriting a changeset with children does not change these
-children's parent! And because children of the rewritten changeset
-still **depend** on the older "dead" version of the changeset with
-can not get rid of this dead version.
+But rewriting a changeset with children does not change the
+children's parents! And because children of the rewritten changeset
+still **depend** on the older "dead" version of the changeset, we
+cannot get rid of this dead version.
 
 ::
 
   Schema base,  A and A' and B.
 
 I'm calling these children **unstable** because they are based on a
-dead changeset and prevent people to get rid of it.
+dead changeset and prevent people from getting rid of it.
 
 This instability is an **unavoidable consequence** of the strict dependency of
-changeset.  History Rewriting history alway  need to take it in account and
-provide a way to rewrite the descendant on the new changeset to avoid
-coexistence of the old and new version of a rewritten changeset.
+changesets.  Rewriting history always needs to take it into account and
+provide a way to rewrite the descendants of the new changeset to avoid
+coexistence of the old and new versions of a rewritten changeset.
 
 
 Everybody is working around the issue
 ------------------------------------------------
 
-I'm not claiming that rewriting history is impossible. People are successfully
-doing for years. However they all need to work around *instability*. Several
-work around strategy exists.
+I'm not claiming that rewriting history is impossible. People have been successfully
+doing it for years. However they all need to work around *instability*. Several
+workaround strategies exist.
 
 
 Rewriting all at once
   Schema!
 
 Several Mercurial commands apply it: rebase, collapse, histedit.
-Mercurial also refuses to amend changeset with descendant. The git
-branch design enforces such approach in git too.
+Mercurial also refuses to amend changesets with descendants. The git
+branch design enforces this approach in git too.
 
 
-However, DVCS are **Distributed**. This means that you do not control what
-happen outside your repository. Once a changeset have been exchanged *outside*,
+However, DVCS are **distributed**. This means that you do not control what
+happens outside your repository. Once a changeset has been exchanged *outside*,
 there is no way to be sure it does not have descendants somewhere else.
 Therefore **if you rewrite changeset that exists elsewhere, you can't eradicate
 the risk of instability.**
 
-Do not rewrite exchanged changeset
+Do not rewrite exchanged changesets
 ```````````````````````````````````
 
 To work around the issue above, Mercurial introduced phases, which
 collaborating on mutable changesets.
 
 In the Git world, they use another approach to prevent instability. By
-convention only a single developper works on a changeset contained in
+convention only a single developer works on a changeset contained in
 a named branch. But once again this is a huge blocker for
 collaborating. Moreover clueless people **will** mess up social
 convention soon or later.
 
 
-Loose the DAG robustness
+Lose the DAG robustness
 ````````````````````````````
 
 The other approach in Mercurial is to keep the mutable part of the
 This allow much more flexible workflow but two major feature are lost in the
 process:
 
-:graceful merge: MQ use plain-patch to store changeset content and patch have
-                 trouble to apply in changing context. Applying your queue
+:graceful merge: MQ uses plain patch to store changeset contents, which has
+                 problems in changing context. Applying your queue
                  becomes very painful when context changes.
 
-:easy branching: A quilt queue is by definition a linear queue. Increasing risk
-                 of conflict
+:easy branching: A quilt queue is by definition a linear queue, increasing risk
+                 of conflict.
 
-It is possible to collaborate over versioned mq! But you are going to
-have a lot of troubles.
+It is possible to collaborate over versioned MQ! But you are going to
+have a lot of trouble.
 
 Ignore conflicts
 ```````````````````````````````````
 The "One set of mutable changset == One developer" mantra is also a way to work
 around conflicting rewriting of changeset. If two different people are able to
 
-The git branch model allow to overwrite changeset version by another
+The git branch model allows overwriting changeset version by another
 one, but it does not care about divergent version. It is the equivalent
 of "common ftp" source management for changesets.
 
 Facing The Danger Once And For All
 ------------------------------------------------
 
-Above we saw that, the more effort you put to avoid instability, the more option
-you deny. And even most restrictive work flow can't guarantee that instability
+Above we saw that the more effort you put to avoid instability, the more options
+you deny. And even the most restrictive workflow can't guarantee that instability
 will never show up!
 
 Obsolete marker can handle the job
 ```````````````````````````````````
 
-It is time to provide a full featured solution to deal with
+It is time to provide a full-featured solution to deal with
 instability and to stop working around the issue! This is why I
-developing a new feature for mercurial called "Obsolete markers".
+am developing a new feature for Mercurial called "Obsolete markers".
 Obsolete markers have two key properties:
 
 
-* Any "old" changeset we want to get ride of is **explicitly** marked
-  as "obsolete" by history rewriting operation.
+* Any "old" changeset we want to get rid of is **explicitly** marked
+  as "obsolete" by history rewriting operations.
 
   By explicitly marking the obsolete part of the history, we will be able to
   easily detect instability situation.
 * Relations between old and new version of changesets are tracked by obsolete
   markers.
 
-  By Storing a meta-history of changeset evolution we are able to easily resolve
-  instability and edition conflict [#]_ .
+  By storing a meta-history of changeset evolution we are able to easily resolve
+  instability and edit conflicts [#]_ .
 
-.. [#] edition conflict is another major obstable to collaboration. See the
+.. [#] Edit conflicts is another major obstable to collaboration. See the
        section dedicated to obsolete marker for details.
 
-Improves robustness == improves simplicity
+Improved robustness == improved simplicity
 ````````````````````````````````````````````````
 
 This proposal should **first** be seen as a safety measure.
 
-It allow to detect instability as soon as possible
+It allows detecting instability as soon as possible.
 
 ::
 
     outgoing unstable changesets
     (use "hg evolve" or force the push)
 
-And should not not encourage people to create instability
+And it should not not encourage people to create instability.
 
 ::
 

File docs/qsync.rst

 ---------------------------------------------------------------------
 
 
-People may have tools or co-workers that export to receive mutable history using
-a versioned mq repository.
+People may have tools or co-workers that expect to receive mutable history using
+a versioned MQ repository.
 
-For this purpose you can use the ``qsync`` extension:
+For this purpose you can use the ``qsync`` extension.
 
 
 To enable the evolve extension use::

File docs/tutorials/tutorial.t

   > EOF
 
 
-This tutorial use the following configuration for Mercurial:
+This tutorial uses the following configuration for Mercurial:
 
 A compact log template with phase data:
 
   +Pear
   +Apple
 
-The faulty changeset is in the "draft" phase because he was not exchanged with
-the outside. The first one have been exchanged and is an immutable public
-changeset.
+The faulty changeset is in the "draft" phase because it has not been exchanged with
+the outside. The first one has been exchanged and is "public" (immutable).
 
   $ hg glog
   @  d85de4546133 (draft): adding fruit
   +Pear
   +Apple
 
-Getting Ride of branchy history
+Getting rid of branchy history
 ----------------------------------
 
 While I was working on my list. someone help made a change remotly.
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
-Removing changeset
+Removing changesets
 ------------------------
 
 I add new item to my list
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
-Reordering changeset
+Reordering changesets
 ------------------------
 
 
 
 .. note: don't amend changeset 7e82d3f3c2cb or 9ca060c80d74 as they are immutable.
 
-I now want to push to remote all my change but the bathroom one that i'm not
-totally happy with yet. To be able to push "SPAM SPAM" I need a version of "SPAM SPAM" not children of
+I now want to push to remote all my changes except the bathroom one, which I'm not
+totally happy with yet. To be able to push "SPAM SPAM" I need a version of "SPAM SPAM" which is not a child of
 "bathroom stuff"
 
 You can use 'rebase -r' or 'graft -O' for that:
 
 We have a new SPAM SPAM version without the bathroom stuff
 
-  $ grep Spam shopping  # enouth spam
+  $ grep Spam shopping  # enough spam
   Spam Spam Spam Spam Spam Spam Spam Spam Spam
   $ grep Toothbrush shopping # no Toothbrush
   [1]
 sharing mutable changeset
 ----------------------------
 
-To share mutable changeset with other just check that the repo you interact
+To share mutable changeset with others, just check that the repo you interact
 with is "not publishing". Otherwise you will get the previously observe
 behavior where exchanged changeset are automatically published.
 
   1 new unstables changesets
 
 
-The new changeset "animal" is based one an old changeset of "bathroom". You can
+The new changeset "animal" is based on an old changeset of "bathroom". You can
 see both version showing up in the log.
 
   $ hg log -G
   
 
 The older version 8a79ae8b029e never ceased to exist in the local repo. It was
-jsut hidden and excluded from pull and push.
+just hidden and excluded from pull and push.
 
-.. note:: In hgview there is a nice doted relation highlighting ffa278c50818 as a new version of 8a79ae8b029e. this is not yet ported to graphlog.
+.. note:: In hgview there is a nice dotted relation highlighting ffa278c50818 as a new version of 8a79ae8b029e. This is not yet ported to ``hg log -G``.
 
-Their is **unstable** changeset in this history now. Mercurial will refuse to
+There is now an **unstable** changeset in this history. Mercurial will refuse to
 share it with the outside:
 
   $ hg push other
 
 
 To resolve this unstable state, you need to rebase 9ac5d0e790a2 onto
-ffa278c50818 the "hg stabilize" command will make this for you.
+ffa278c50818. The "hg stabilize" command will do this for you.
 
 It has a --dry-run option to only suggest the next move.
 
 Handling Conflicting amend
 ----------------------------------------------
 
-We can detect that multiple diverging//conflicting amend have been made. There
-will be a "evol-merge" command to merge conflicting amend
+We can detect that multiple diverging/conflicting amendments have been made. There
+will be a "evol-merge" command to merge conflicting amendments.
 
 This command is not ready yet.

File hgext/evolve.py

     - improves some aspect of the early implementation in 2.3
 '''
 
-testedwith = '2.4'
+testedwith = ''
 buglink = 'https://bitbucket.org/marmoute/mutable-history/issues'
 
 
 
 try:
     from mercurial import obsolete
-    getattr(obsolete, 'getrevs') # 2.4 specific
     if not obsolete._enabled:
         obsolete._enabled = True
-except (ImportError, AttributeError):
-    raise util.Abort('Evolve extension requires Mercurial 2.4.x')
-try:
     from mercurial import bookmarks
     bookmarks.bmstore
-    raise util.Abort('This version of Evolve is too old for you mercurial version')
-except AttributeError:
-    pass
+except (ImportError, AttributeError):
+    raise util.Abort('Your Mercurial is too old for this version of Evolve',
+                     hint='requires version >> 2.4.x')
 
 
 
 latediff = 1  # flag to prevent taking late comer fix into account
 
 
-@cachefor('divergent')
-def _computedivergentset(repo):
-    """the set of rev trying to obsolete public revision"""
-    divergent = set()
-    obsstore = repo.obsstore
-    newermap = {}
-    for ctx in repo.set('(not public()) - obsolete()'):
-        mark = obsstore.precursors.get(ctx.node(), ())
-        toprocess = set(mark)
-        while toprocess:
-            prec = toprocess.pop()[0]
-            if prec not in newermap:
-                successorssets(repo, prec, newermap)
-            newer = [n for n in newermap[prec] if n]
-            if len(newer) > 1:
-                divergent.add(ctx.rev())
-                break
-            toprocess.update(obsstore.precursors.get(prec, ()))
-    return divergent
 
 ### changectx method
 
     return ctx.bumped()
 
 @eh.addattr(context.changectx, 'conflicting')
-@eh.addattr(context.changectx, 'divergent')
-def divergent(ctx):
+def conflicting(ctx):
     """is the changeset divergent (Try to succeed to public change)"""
-    if ctx.node() is None:
-        return False
-    return ctx.rev() in getrevs(ctx._repo, 'divergent')
+    return ctx.divergent()
 
 ### revset symbol
 
 eh.revset('latecomer')(revset.symbols['bumped'])
 
-@eh.revset('conflicting')
-@eh.revset('divergent')
-def revsetdivergent(repo, subset, x):
-    """``divergent()``
-    Changesets marked as successors of a same changeset.
-    """
-    args = revset.getargs(x, 0, 0, 'divergent takes no arguments')
-    conf = getrevs(repo, 'divergent')
-    return [r for r in subset if r in conf]
+eh.revset('conflicting')(revset.symbols['divergent'])
 
 
 
-### Discovery wrapping
-
-@eh.wrapfunction(discovery, 'checkheads')
-def wrapcheckheads(orig, repo, remote, outgoing, *args, **kwargs):
-    """wrap mercurial.discovery.checkheads
-
-    * prevent divergent to be pushed
-    """
-    # do not push instability
-    for h in outgoing.missingheads:
-        # Checking heads is enough, obsolete descendants are either
-        # obsolete or unstable.
-        ctx = repo[h]
-        if ctx.divergent():
-            raise util.Abort(_("push includes a divergent changeset: %s!")
-                             % ctx)
-    return orig(repo, remote, outgoing, *args, **kwargs)
-
-#####################################################################
-### Filter extinct changesets from common operations              ###
-#####################################################################
-
-@eh.wrapfunction(merge, 'update')
-def wrapmergeupdate(orig, repo, node, *args, **kwargs):
-    """ensure we don't automatically update on hidden changeset"""
-    if node is None:
-        # tip of current branch
-        branch = repo[None].branch()
-        node = repo.revs('last((.:: and branch(%s)) - hidden())', branch)[0]
-    return orig(repo, node, *args, **kwargs)
-
-@eh.wrapfunction(localrepo.localrepository, 'branchtip')
-def obsbranchtip(orig, repo, branch):
-    """ensure "stable" reference does not end on a hidden changeset"""
-    if not getattr(repo, '_dofilterbranchtip', True):
-        return orig(repo, branch)
-    result = ()
-    heads = repo.branchmap().get(branch, ())
-    if heads:
-        result = list(repo.set('last(heads(branch(%n) - hidden()))', heads[0]))
-    if not result:
-        raise error.RepoLookupError(_("unknown branch '%s'") % branch)
-    return result[0].node()
-
-
-@eh.wrapfunction(mercurial.hgweb.hgweb_mod.hgweb, '__init__')
-@eh.wrapfunction(mercurial.hgweb.hgweb_mod.hgweb, 'refresh')
-def nofilter(orig, hgweb, *args, **kwargs):
-    orig(hgweb, *args, **kwargs)
-    hgweb.repo._dofilterbranchtip = False
-
 
 #####################################################################
 ### Additional Utilities                                          ###
     if ui.config('alias', 'olog', None) is None:
         ui.setconfig('alias', 'olog', "log -r 'precursors(.)' --hidden")
     if ui.config('alias', 'odiff', None) is None:
-        ui.setconfig('alias', 'odiff', "diff --rev 'limit(precursors(.),1)' --rev .")
-
-# - "troubles" method on changectx
-
-@eh.addattr(context.changectx, 'troubles')
-def troubles(ctx):
-    """Return a tuple listing all the troubles that affect a changeset
-
-    Troubles may be "unstable", "bumped" or "divergent".
-    """
-    troubles = []
-    if ctx.unstable():
-        troubles.append('unstable')
-    if ctx.bumped():
-        troubles.append('bumped')
-    if ctx.divergent():
-        troubles.append('divergent')
-    return tuple(troubles)
+        ui.setconfig('alias', 'odiff', "diff --hidden --rev 'limit(precursors(.),1)' --rev .")
 
 ### Troubled revset symbol
 
             cs.add(sr)
     return cs
 
-nodemod = node
-def successorssets(repo, initialnode, cache=None):
-    """Return the newer version of an obsolete changeset"""
-
-    # prec -> markers mapping
-    markersfor = repo.obsstore.successors
-
-    # Stack of node need to know the last successors set
-    toproceed = [initialnode]
-    # set version of toproceed for fast loop detection
-    stackedset = set(toproceed)
-    if cache is None:
-        cache = {}
-    while toproceed:
-        # work on the last node of the stack
-        node = toproceed[-1]
-        if node in cache:
-            # We already have a value for it.
-            # Keep working on something else.
-            stackedset.remove(toproceed.pop())
-        elif node not in markersfor:
-            # The node is not obsolete.
-            # This mean it is its own last successors.
-            if node in repo:
-                # We have a valid last successors.
-                cache[node] = [(node,)]
-            else:
-                # final obsolete version is unknown locally.
-                # Do not count that as a valid successors
-                cache[node] = []
-        else:
-            # <lss> stand for Last Successors Sets
-            # it contains the list of all last successors for the current node.
-            lss = []
-            for mark in markersfor[node]:
-                # <mlss> stand for Marker Last Successors Sets
-                # it contains the list of last successors set introduced by
-                # this marker.
-                mlss = [[]]
-                # iterate over possible multiple successors
-                for suc in mark[1]:
-                    if suc not in cache:
-                        # We do not know the last successors of that yet.
-                        if suc in stackedset:
-                            # Loop detected!
-                            #
-                            # we won't be able to ever compute a proper last
-                            # successors the naive and simple approve is to
-                            # consider it killed
-                            cache[suc] = []
-                        else:
-                            # Add the successor to the stack and break the next
-                            # iteration will work on this successors and the
-                            # algorithm will eventually process the current
-                            # node again.
-                            toproceed.append(suc)
-                            stackedset.add(suc)
-                            break
-                    # if we did not break, we can extend the possible set of
-                    # last successors.
-                    #
-                    # I say "extends" because if the marker have multiple
-                    # successors we have to generate
-                    #
-                    # if successors have multiple successors set (when ther are
-                    # divergent themself), we do a cartesian product of
-                    # possible successors set of already processed successors
-                    # and newly obtains successors set.
-                    newmlss = []
-                    for prefix in mlss:
-                        for suffix in cache[suc]:
-                            newss = list(prefix)
-                            for part in suffix:
-                                # do not duplicated entry in successors set.
-                                # first entry win.
-                                if part not in newss:
-                                    newss.append(part)
-                            newmlss.append(newss)
-                    mlss = newmlss
-                else:
-                    # note: mlss is still empty if the marker was a bare killing
-                    # of this changeset
-                    #
-                    # We extends the list of all possible successors sets with
-                    # successors set continuted by this marker
-                    lss.extend(mlss)
-                    # we use continue here to skip the break right bellow
-                    continue
-                # propagate "nested for" break.
-                # if the nested for exited on break, it did not ran the else
-                # clause and didn't "continue
-                break
-            else:
-                # computation was succesful for *all* marker.
-                # Add computed successors set to the cache
-                # (will be poped from to proceeed) on the new iteration
-                #
-                # We remove successors set that are subset of another one
-                # this fil
-                candsucset = sorted(((len(ss), set(ss), ss) for ss in lss),
-                                    reverse=True)
-                finalsucset = []
-                for cl, cs, css in candsucset:
-                    if not css:
-                        # remove empty successors set
-                        continue
-                    for fs, fss in finalsucset:
-                        if cs.issubset(fs):
-                            break
-                    else:
-                        finalsucset.append((cs, css))
-                finalsucset = [s[1] for s in finalsucset]
-                finalsucset.reverse()
-                cache[node] = finalsucset
-    return cache[initialnode]
-
 
 
 
 @eh.wrapcommand("unbundle")
 def warnobserrors(orig, ui, repo, *args, **kwargs):
     """display warning is the command resulted in more instable changeset"""
-    priorunstables = len(repo.revs('unstable()'))
-    priorbumpeds = len(repo.revs('bumped()'))
-    priordivergents = len(repo.revs('divergent()'))
+    # part of the troubled stuff may be filtered (stash ?)
+    # This needs a better implementation but will probably wait for core.
+    filtered = repo.changelog.filteredrevs
+    priorunstables = len(set(getrevs(repo, 'unstable')) - filtered)
+    priorbumpeds = len(set(getrevs(repo, 'bumped')) - filtered)
+    priordivergents = len(set(getrevs(repo, 'divergent')) - filtered)
     ret = orig(ui, repo, *args, **kwargs)
     # workaround phase stupidity
-    phases._filterunknown(ui, repo.changelog, repo._phasecache.phaseroots)
-    newunstables = len(repo.revs('unstable()')) - priorunstables
-    newbumpeds = len(repo.revs('bumped()')) - priorbumpeds
-    newdivergents = len(repo.revs('divergent()')) - priordivergents
+    #phases._filterunknown(ui, repo.changelog, repo._phasecache.phaseroots)
+    filtered = repo.changelog.filteredrevs
+    newunstables = len(set(getrevs(repo, 'unstable')) - filtered) - priorunstables
+    newbumpeds = len(set(getrevs(repo, 'bumped')) - filtered) - priorbumpeds
+    newdivergents = len(set(getrevs(repo, 'divergent')) - filtered) - priordivergents
     if newunstables > 0:
         ui.warn(_('%i new unstable changesets\n') % newunstables)
     if newbumpeds > 0:
         for book in destbookmarks: # restore bookmark that rebase move
             repo._bookmarks[book] = dest.node()
         if oldbookmarks or destbookmarks:
-            bookmarks.write(repo)
+            repo._bookmarks.write()
         return nodenew
     except util.Abort:
         # Invalidate the previous setparents
                 repo._bookmarks[b] = newid
             dirty = True
         if dirty:
-            bookmarks.write(repo)
+            repo._bookmarks.write()
     return updatebookmarks
 
 ### new command
         else:
             ui.write_err(_('no troubled changeset\n'))
             return 1
+    repo = repo.unfiltered()
+    tr = repo[tr.rev()]
     cmdutil.bailifchanged(repo)
     troubles = tr.troubles()
     if 'unstable' in troubles:
     elif 'bumped' in troubles:
         return _solvebumped(ui, repo, tr, opts['dry_run'])
     elif 'divergent' in troubles:
+        repo = repo.unfiltered()
+        tr = repo[tr.rev()]
         return _solvedivergent(ui, repo, tr, opts['dry_run'])
     else:
         assert False  # WHAT? unknown troubles
         print orig.rev()
         obs = orig.parents()[1]
     assert obs.obsolete()
-    newer = successorssets(repo, obs.node())
+    newer = obsolete.successorssets(repo, obs.node())
     # search of a parent which is not killed
     while not newer or newer == [()]:
         ui.debug("stabilize target %s is plain dead,"
                  " trying to stabilize on its parent")
         obs = obs.parents()[0]
-        newer = successorssets(repo, obs.node())
+        newer = obsolete.successorssets(repo, obs.node())
     if len(newer) > 1:
         ui.write_err(_("conflict rewriting. can't choose destination\n"))
         return 2
     XXX this woobly function won't survive XXX
     """
     for base in ctx._repo.set('reverse(precursors(%d))', ctx):
-        newer = successorssets(ctx._repo, base.node())
+        newer = obsolete.successorssets(ctx._repo, base.node())
         # drop filter and solution including the original ctx
         newer = [n for n in newer if n and ctx.node() not in n]
         if newer:
             for book in oldbookmarks:
                 repo._bookmarks[book] = new.node()
             if oldbookmarks:
-                bookmarks.write(repo)
+                repo._bookmarks.write()
         return result
     finally:
         if lock is not None:
         finally:
             tr.release()
         ui.status('%i changesets folded\n' % len(revs))
-        if repo.revs('. and %ld', revs):
+        if repo['.'].rev() in revs:
             hg.update(repo, newid)
     finally:
         lockmod.release(lock, wlock)
 
-if 'debugsuccessorssets' not in commands.table:
-
-    @command('debugsuccessorssets',
-        [],
-        _('[REV]'))
-    def debugsuccessorssets(ui, repo, *revs):
-        """show set of successors for revision
-
-        Successors set of changeset A are a consistent group of revision that
-        succeed to A. Successors set contains non-obsolete changeset only.
-
-        In most case a changeset A have zero (changeset pruned) or a single
-        successors set that contains a single successors (changeset A replacement
-        by A')
-
-        But splitted changeset will result with successors set containing more than
-        a single element. Divergent rewritting will result in multiple successor
-        set.
-
-        result is displayed as follows::
-
-            <rev1>
-                <successors-1A>
-            <rev2>
-                <successors-2A>
-                <successors-2B1> <successors-2B1> <successors-2B1>
-
-        here rev2 have two possible successors sets. One hold three elements.
-
-        add --debug if you want full size node id.
-        """
-        cache = {}
-        s = str
-        if ui.debug:
-            def s(ctx):
-                return ctx.hex()
-        for rev in scmutil.revrange(repo, revs):
-            ctx = repo[rev]
-            if ui.debug():
-                ui.write('%s\n'% ctx.hex())
-                s = node.hex
-            else:
-                ui.write('%s\n'% ctx)
-                s = node.short
-            for ss in successorssets(repo, ctx.node(), cache):
-                if ss:
-                    ui.write('    ')
-                    ui.write(s(ss[0]))
-                    for n in ss[1:]:
-                        ui.write(' ')
-                        ui.write(s(n))
-                ui.write('\n')
-        pass
 
 
 @eh.wrapcommand('graft')

File hgext/qsync.py

 from mercurial import error
 from mercurial import extensions
 from mercurial import phases
+from mercurial import obsolete
 
 ### old compat code
 #############################
                     review_list.append(patch_name)
                 except IOError:
                     oldnode = oldfiles[patch_name]
-                    evolve = extensions.find('evolve')
-                    newnodes = evolve.successorssets(repo, oldnode)
+                    newnodes = obsolete.successorssets(repo, oldnode)
                     if newnodes:
                         newnodes = [n for n in newnodes if n and n[0] in repo] # remove killing
                     if not newnodes:
         usedold.add(oldhex)
         oldname = str(oldname)
         oldnode = bin(oldhex)
-        newnodes = evolve.successorssets(repo, oldnode)
+        newnodes = obsolete.successorssets(repo, oldnode)
         if newnodes:
             newnodes = [n for n in newnodes if n and n[0] in repo] # remove killing
             if len(newnodes) > 1:

File hgext/simple4server.py

+'''enable experimental obsolescence feature of Mercurial
+
+OBSOLESCENCE IS AN EXPERIMENTAL FEATURE MAKE SURE YOU UNDERSTOOD THE INVOLVED
+CONCEPT BEFORE USING IT.
+
+/!\ THIS EXTENSION IS INTENDED FOR SERVER SIDE ONLY USAGE /!\
+
+For client side usages it is recommended to use the evolve extension for
+improved user interface.'''
+
+import mercurial.obsolete
+mercurial.obsolete._enabled = True
 
 setup(
     name='hg-evolve',
-    version='2.1.0',
+    version='2.99.0',
     author='Pierre-Yves David',
     maintainer='Pierre-Yves David',
     maintainer_email='pierre-yves.david@logilab.fr',

File tests/test-amend.t

   >   hg glog --template '{rev}@{branch}({phase}) {desc|firstline}\n' "$@"
   > }
 
-  $ hg init repo
+  $ hg init repo --traceback
   $ cd repo
   $ echo a > a
   $ hg ci -Am adda
   foo
   $ hg branches
   foo                            2:a34b93d251e4
-  default                        0:07f494440405 (inactive)
   $ glog
   @  2@foo(draft) adda
   
   marked working directory as branch default
   (branches are permanent and global, did you want a bookmark?)
   $ hg ci -m resetbranch
-  created new head
   $ hg branch --force foo
   marked working directory as branch foo
   (branches are permanent and global, did you want a bookmark?)

File tests/test-evolve.t

 
   $ hg phase --public 0 -v
   phase changed for 1 changesets
-  $ hg amend -c 2
+  $ hg amend -c 4
   abort: cannot amend non ancestor changeset
   [255]
 
 
 (amend of on ancestors)
 
-  $ hg amend -c 2
-  abort: cannot amend non ancestor changeset
-  [255]
-
   $ hg amend --note 'french looks better'
   1 new unstable changesets
   $ hg log
 
 phase change turning obsolete changeset public issue a bumped warning
 
-  $ hg phase --public 7
+  $ hg phase --hidden --public 7
   1 new bumped changesets
 
 all solving bumped troubled
   |
   o  0	: base - test
   
-  $ hg diff -r 9 -r 8
+  $ hg diff --hidden -r 9 -r 8
   $ hg diff -r 9^ -r 9
   diff --git a/main-file-1 b/main-file-1
   --- a/main-file-1
   checking files
   3 files, 4 changesets, 4 total revisions
   $ hg --config extensions.hgext.mq= strip 'extinct()'
+  abort: empty revision set
+  [255]
+  $ hg --config extensions.hgext.mq= strip --hidden 'extinct()'
   saved backup bundle to $TESTTMP/alpha/.hg/strip-backup/e87767087a57-backup.hg
   $ hg verify
   checking changesets

File tests/test-obsolete-divergent.t

-Test file decicated to testing the divergent troubles from obsolete changeset.
-
-This is the most complexe troubles from far so we isolate it in a dedicated
-file.
-
-Enable obsolete
-
-  $ cat >> $HGRCPATH << EOF
-  > [ui]
-  > logtemplate = {rev}:{node|short} {desc}\n
-  > [alias]
-  > debugobsolete = debugobsolete -d '0 0'
-  > [phases]
-  > publish=False
-  > [extensions]
-  > rebase=
-  > EOF
-  $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext/evolve.py" >> $HGRCPATH
-
-
-  $ mkcommit() {
-  >    echo "$1" > "$1"
-  >    hg add "$1"
-  >    hg ci -m "$1"
-  > }
-  $ getid() {
-  >    hg id --debug -ir "desc('$1')"
-  > }
-
-setup repo
-
-  $ hg init reference
-  $ cd reference
-  $ mkcommit base
-  $ mkcommit A_0
-  $ hg up 0
-  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  $ mkcommit A_1
-  created new head
-  $ hg up 0
-  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  $ mkcommit A_2
-  created new head
-  $ hg up 0
-  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  $ cd ..
-
-
-  $ newcase() {
-  >    hg clone -u 0 -q reference $1
-  >    cd $1
-  > }
-
-direct divergence
------------------
-
-A_1 have two direct and divergent successors A_1 and A_1
-
-  $ newcase direct
-  $ hg debugobsolete `getid A_0` `getid A_1`
-  $ hg debugobsolete `getid A_0` `getid A_2`
-  $ hg log -G --hidden
-  o  3:392fd25390da A_2
-  |
-  | o  2:82623d38b9ba A_1
-  |/
-  | x  1:007dc284c1f8 A_0
-  |/
-  @  0:d20a80d4def3 base
-  
-  $ hg debugsuccessorssets 'all()'
-  d20a80d4def3
-      d20a80d4def3
-  007dc284c1f8
-      392fd25390da
-      82623d38b9ba
-  82623d38b9ba
-      82623d38b9ba
-  392fd25390da
-      392fd25390da
-  $ hg log -r 'divergent()'
-  2:82623d38b9ba A_1
-  3:392fd25390da A_2
-  $ hg summary -v
-  parent: 0:d20a80d4def3 
-   base
-  branch: default
-  commit: (clean)
-  update: 3 new changesets (update)
-  unstable: 0 changesets
-  bumped: 0 changesets
-  divergent: 2 changesets
-
-
-check that mercurial refuse to push
-
-  $ hg init ../other
-  $ hg push ../other
-  pushing to ../other
-  searching for changes
-  abort: push includes a divergent changeset: 82623d38b9ba!
-  (use 'hg evolve' to get a stable history or --force to ignore warnings)
-  [255]
-
-  $ cd ..
-
-
-indirect divergence with known changeset
--------------------------------------------
-
-  $ newcase indirect_known
-  $ hg debugobsolete `getid A_0` `getid A_1`
-  $ hg debugobsolete `getid A_0` `getid A_2`
-  $ mkcommit A_3
-  created new head
-  $ hg debugobsolete `getid A_2` `getid A_3`
-  $ hg log -G --hidden
-  @  4:01f36c5a8fda A_3
-  |
-  | x  3:392fd25390da A_2
-  |/
-  | o  2:82623d38b9ba A_1
-  |/
-  | x  1:007dc284c1f8 A_0
-  |/
-  o  0:d20a80d4def3 base
-  
-  $ hg debugsuccessorssets 'all()'
-  d20a80d4def3
-      d20a80d4def3
-  007dc284c1f8
-      01f36c5a8fda
-      82623d38b9ba
-  82623d38b9ba
-      82623d38b9ba
-  392fd25390da
-      01f36c5a8fda
-  01f36c5a8fda
-      01f36c5a8fda
-  $ hg log -r 'divergent()'
-  2:82623d38b9ba A_1
-  4:01f36c5a8fda A_3
-  $ cd ..
-
-
-indirect divergence with known changeset
--------------------------------------------
-
-  $ newcase indirect_unknown
-  $ hg debugobsolete `getid A_0` aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-  $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa `getid A_1`
-  $ hg debugobsolete `getid A_0` `getid A_2`
-  $ hg log -G --hidden
-  o  3:392fd25390da A_2
-  |
-  | o  2:82623d38b9ba A_1
-  |/
-  | x  1:007dc284c1f8 A_0
-  |/
-  @  0:d20a80d4def3 base
-  
-  $ hg debugsuccessorssets 'all()'
-  d20a80d4def3
-      d20a80d4def3
-  007dc284c1f8
-      392fd25390da
-      82623d38b9ba
-  82623d38b9ba
-      82623d38b9ba
-  392fd25390da
-      392fd25390da
-  $ hg log -r 'divergent()'
-  2:82623d38b9ba A_1
-  3:392fd25390da A_2
-  $ cd ..
-
-do not take unknown node in account if they are final
------------------------------------------------------
-
-  $ newcase final-unknown
-  $ hg debugobsolete `getid A_0` `getid A_1`
-  $ hg debugobsolete `getid A_1` `getid A_2`
-  $ hg debugobsolete `getid A_0` bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-  $ hg debugobsolete bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccccccccccccccccccccc
-  $ hg debugobsolete `getid A_1` dddddddddddddddddddddddddddddddddddddddd
-
-  $ hg debugsuccessorssets 'desc('A_0')'
-  007dc284c1f8
-      392fd25390da
-
-  $ cd ..
-
-divergence that converge again is not divergence anymore
------------------------------------------------------
-
-  $ newcase converged_divergence
-  $ hg debugobsolete `getid A_0` `getid A_1`
-  $ hg debugobsolete `getid A_0` `getid A_2`
-  $ mkcommit A_3
-  created new head
-  $ hg debugobsolete `getid A_1` `getid A_3`
-  $ hg debugobsolete `getid A_2` `getid A_3`
-  $ hg log -G --hidden
-  @  4:01f36c5a8fda A_3
-  |
-  | x  3:392fd25390da A_2
-  |/
-  | x  2:82623d38b9ba A_1
-  |/
-  | x  1:007dc284c1f8 A_0
-  |/
-  o  0:d20a80d4def3 base
-  
-  $ hg debugsuccessorssets 'all()'
-  d20a80d4def3
-      d20a80d4def3
-  007dc284c1f8
-      01f36c5a8fda
-  82623d38b9ba
-      01f36c5a8fda
-  392fd25390da
-      01f36c5a8fda
-  01f36c5a8fda
-      01f36c5a8fda
-  $ hg log -r 'divergent()'
-  $ cd ..
-
-split is not divergences
------------------------------
-
-  $ newcase split
-  $ hg debugobsolete `getid A_0` `getid A_1` `getid A_2`
-  $ hg log -G --hidden
-  o  3:392fd25390da A_2
-  |
-  | o  2:82623d38b9ba A_1
-  |/
-  | x  1:007dc284c1f8 A_0
-  |/
-  @  0:d20a80d4def3 base
-  
-  $ hg debugsuccessorssets 'all()'
-  d20a80d4def3
-      d20a80d4def3
-  007dc284c1f8
-      82623d38b9ba 392fd25390da
-  82623d38b9ba
-      82623d38b9ba
-  392fd25390da
-      392fd25390da
-  $ hg log -r 'divergent()'
-
-Even when subsequente rewriting happen
-
-  $ mkcommit A_3
-  created new head
-  $ hg debugobsolete `getid A_1` `getid A_3`
-  $ hg up 0
-  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  $ mkcommit A_4
-  created new head
-  $ hg debugobsolete `getid A_2` `getid A_4`
-  $ hg up 0
-  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  $ mkcommit A_5
-  created new head
-  $ hg debugobsolete `getid A_4` `getid A_5`
-  $ hg log -G --hidden
-  @  6:e442cfc57690 A_5
-  |
-  | x  5:6a411f0d7a0a A_4
-  |/
-  | o  4:01f36c5a8fda A_3
-  |/
-  | x  3:392fd25390da A_2
-  |/
-  | x  2:82623d38b9ba A_1
-  |/
-  | x  1:007dc284c1f8 A_0
-  |/
-  o  0:d20a80d4def3 base
-  
-  $ hg debugsuccessorssets 'all()'
-  d20a80d4def3
-      d20a80d4def3
-  007dc284c1f8
-      01f36c5a8fda e442cfc57690
-  82623d38b9ba
-      01f36c5a8fda
-  392fd25390da
-      e442cfc57690
-  01f36c5a8fda
-      01f36c5a8fda
-  6a411f0d7a0a
-      e442cfc57690
-  e442cfc57690
-      e442cfc57690
-  $ hg log -r 'divergent()'
-
-Check more complexe obsolescence graft (with divergence)
-
-  $ mkcommit B_0; hg up 0
-  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
-  $ hg debugobsolete `getid B_0` `getid A_2`
-  $ mkcommit A_7; hg up 0
-  created new head
-  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  $ mkcommit A_8; hg up 0
-  created new head
-  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  $ hg debugobsolete `getid A_5` `getid A_7` `getid A_8`
-  $ mkcommit A_9; hg up 0
-  created new head
-  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  $ hg debugobsolete `getid A_5` `getid A_9`
-  $ hg log -G --hidden
-  o  10:bed64f5d2f5a A_9
-  |
-  | o  9:14608b260df8 A_8
-  |/
-  | o  8:7ae126973a96 A_7
-  |/
-  | x  7:3750ebee865d B_0
-  | |
-  | x  6:e442cfc57690 A_5
-  |/
-  | x  5:6a411f0d7a0a A_4
-  |/
-  | o  4:01f36c5a8fda A_3
-  |/
-  | x  3:392fd25390da A_2
-  |/
-  | x  2:82623d38b9ba A_1
-  |/
-  | x  1:007dc284c1f8 A_0
-  |/
-  @  0:d20a80d4def3 base
-  
-  $ hg debugsuccessorssets 'all()'
-  d20a80d4def3
-      d20a80d4def3
-  007dc284c1f8
-      01f36c5a8fda bed64f5d2f5a
-      01f36c5a8fda 7ae126973a96 14608b260df8
-  82623d38b9ba
-      01f36c5a8fda
-  392fd25390da
-      bed64f5d2f5a
-      7ae126973a96 14608b260df8
-  01f36c5a8fda
-      01f36c5a8fda
-  6a411f0d7a0a
-      bed64f5d2f5a
-      7ae126973a96 14608b260df8
-  e442cfc57690
-      bed64f5d2f5a
-      7ae126973a96 14608b260df8
-  3750ebee865d
-      bed64f5d2f5a
-      7ae126973a96 14608b260df8
-  7ae126973a96
-      7ae126973a96
-  14608b260df8
-      14608b260df8
-  bed64f5d2f5a
-      bed64f5d2f5a
-  $ hg log -r 'divergent()'
-  4:01f36c5a8fda A_3
-  8:7ae126973a96 A_7
-  9:14608b260df8 A_8
-  10:bed64f5d2f5a A_9
-
-fix the divergence
-
-  $ mkcommit A_A; hg up 0
-  created new head
-  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  $ hg debugobsolete `getid A_9` `getid A_A`
-  $ hg debugobsolete `getid A_7` `getid A_A`
-  $ hg debugobsolete `getid A_8` `getid A_A`
-  $ hg log -G --hidden
-  o  11:a139f71be9da A_A
-  |
-  | x  10:bed64f5d2f5a A_9
-  |/
-  | x  9:14608b260df8 A_8
-  |/
-  | x  8:7ae126973a96 A_7
-  |/
-  | x  7:3750ebee865d B_0
-  | |
-  | x  6:e442cfc57690 A_5
-  |/
-  | x  5:6a411f0d7a0a A_4
-  |/
-  | o  4:01f36c5a8fda A_3
-  |/
-  | x  3:392fd25390da A_2
-  |/
-  | x  2:82623d38b9ba A_1
-  |/
-  | x  1:007dc284c1f8 A_0
-  |/
-  @  0:d20a80d4def3 base
-  
-  $ hg debugsuccessorssets 'all()'
-  d20a80d4def3
-      d20a80d4def3
-  007dc284c1f8
-      01f36c5a8fda a139f71be9da
-  82623d38b9ba
-      01f36c5a8fda
-  392fd25390da
-      a139f71be9da
-  01f36c5a8fda
-      01f36c5a8fda
-  6a411f0d7a0a
-      a139f71be9da
-  e442cfc57690
-      a139f71be9da
-  3750ebee865d
-      a139f71be9da
-  7ae126973a96
-      a139f71be9da
-  14608b260df8
-      a139f71be9da
-  bed64f5d2f5a
-      a139f71be9da
-  a139f71be9da
-      a139f71be9da
-  $ hg log -r 'divergent()'
-
-  $ cd ..
-
-
-Subset does not diverge
-------------------------------
-
-Do not report divergent successors-set if it is a subset of another
-successors-set. (report [A,B] not [A] + [A,B])
-
-  $ newcase subset
-  $ hg debugobsolete `getid A_0` `getid A_2`
-  $ hg debugobsolete `getid A_0` `getid A_1` `getid A_2`
-  $ hg debugsuccessorssets 'desc('A_0')'
-  007dc284c1f8
-      82623d38b9ba 392fd25390da
-
-  $ cd ..

File tests/test-obsolete-rebase.t

-  $ cat >> $HGRCPATH <<EOF
-  > [defaults]
-  > amend=-d "0 0"
-  > [extensions]
-  > hgext.rebase=
-  > hgext.graphlog=
-  > EOF
-  $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext/evolve.py" >> $HGRCPATH
-
-  $ glog() {
-  >   hg glog --template '{rev}:{node|short}@{branch}({phase}) {desc|firstline}\n'\
-  >     "$@"
-  > }
-
-  $ hg init repo
-  $ cd repo
-  $ echo a > a
-  $ hg ci -Am adda
-  adding a
-  $ echo a >> a
-  $ hg ci -m changea
-
-Test regular rebase
-
-  $ hg up 0
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ echo b > b
-  $ hg ci -Am addb
-  adding b
-  created new head
-  $ echo e > e
-  $ hg ci -Am adde e
-
-(phase compliance)
-
-  $ hg phase --public 3
-  $ hg rebase -d 1 -r 3
-  abort: can't rebase immutable changeset 98e4a024635e
-  (see hg help phases for details)
-  [255]
-  $ hg phase --draft --force 0
-  $ hg rebase -d 1 -r 3 --keep  
-  $ glog
-  @  4:9c5494949763@default(draft) adde
-  |
-  | o  3:98e4a024635e@default(draft) adde
-  | |
-  | o  2:102a90ea7b4a@default(draft) addb
-  | |
-  o |  1:540395c44225@default(draft) changea
-  |/
-  o  0:07f494440405@default(draft) adda
-  
-  $ glog --hidden
-  @  4:9c5494949763@default(draft) adde
-  |
-  | o  3:98e4a024635e@default(draft) adde
-  | |
-  | o  2:102a90ea7b4a@default(draft) addb
-  | |
-  o |  1:540395c44225@default(draft) changea
-  |/
-  o  0:07f494440405@default(draft) adda
-  
-  $ hg debugobsolete
-  $ hg --config extensions.hgext.mq= strip tip
-  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  saved backup bundle to $TESTTMP/repo/.hg/strip-backup/9c5494949763-backup.hg
-  $ hg rebase -d 1 -r 3
-  $ glog
-  @  4:9c5494949763@default(draft) adde
-  |
-  | o  2:102a90ea7b4a@default(draft) addb
-  | |
-  o |  1:540395c44225@default(draft) changea
-  |/
-  o  0:07f494440405@default(draft) adda
-  
-  $ glog --hidden
-  @  4:9c5494949763@default(draft) adde
-  |
-  | x  3:98e4a024635e@default(draft) adde
-  | |
-  | o  2:102a90ea7b4a@default(draft) addb
-  | |
-  o |  1:540395c44225@default(draft) changea
-  |/
-  o  0:07f494440405@default(draft) adda
-  
-  $ hg debugobsolete
-  98e4a024635e8c50928144c9277a4388d26bd786 9c54949497631abfb5a255d96746bbd3a42ed2ba 0 {'date': '* *', 'user': 'test'} (glob)
-
-Test rebase with deleted empty revision
-
-  $ hg up 0
-  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  $ hg branch foo
-  marked working directory as branch foo
-  (branches are permanent and global, did you want a bookmark?)
-  $ echo a >> a
-  $ hg ci -m changea
-  $ hg rebase -d 1
-  $ glog --hidden
-  x  5:4e322f7ce8e3@foo(draft) changea
-  |
-  | o  4:9c5494949763@default(draft) adde
-  | |
-  | | x  3:98e4a024635e@default(draft) adde
-  | | |
-  +---o  2:102a90ea7b4a@default(draft) addb
-  | |
-  | @  1:540395c44225@default(draft) changea
-  |/
-  o  0:07f494440405@default(draft) adda
-  
-  $ hg debugobsolete
-  98e4a024635e8c50928144c9277a4388d26bd786 9c54949497631abfb5a255d96746bbd3a42ed2ba 0 {'date': '* *', 'user': 'test'} (glob)
-  4e322f7ce8e3e4203950eac9ece27bf7e45ffa6c 540395c442253af3b991be882b539e7e198b5808 0 {'date': '* *', 'user': 'test'} (glob)
-
-Test rebase --collapse
-
-  $ hg up 0
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ echo c > c
-  $ hg ci -Am addc
-  adding c
-  created new head
-  $ echo c >> c
-  $ hg ci -m changec
-  $ hg rebase --collapse -d 1
-  merging c
-  $ glog --hidden
-  @  8:a7773ffa7edc@default(draft) Collapsed revision
-  |
-  | x  7:03f31481307a@default(draft) changec
-  | |
-  | x  6:076e9b2ffbe1@default(draft) addc
-  | |
-  | | x  5:4e322f7ce8e3@foo(draft) changea
-  | |/
-  +---o  4:9c5494949763@default(draft) adde
-  | |
-  | | x  3:98e4a024635e@default(draft) adde
-  | | |
-  | | o  2:102a90ea7b4a@default(draft) addb
-  | |/
-  o |  1:540395c44225@default(draft) changea
-  |/
-  o  0:07f494440405@default(draft) adda
-  
-  $ hg debugobsolete
-  98e4a024635e8c50928144c9277a4388d26bd786 9c54949497631abfb5a255d96746bbd3a42ed2ba 0 {'date': '* *', 'user': 'test'} (glob)
-  4e322f7ce8e3e4203950eac9ece27bf7e45ffa6c 540395c442253af3b991be882b539e7e198b5808 0 {'date': '* *', 'user': 'test'} (glob)
-  076e9b2ffbe11c7bcb9ee97f5c0c8b88a1a10b93 a7773ffa7edcfac27b5dcdb2d5c1036e15a49861 0 {'date': '* *', 'user': 'test'} (glob)
-  03f31481307aaf5275d07ec28c1c59931759ccd2 a7773ffa7edcfac27b5dcdb2d5c1036e15a49861 0 {'date': '* *', 'user': 'test'} (glob)
-
-Test rebase --abort
-
-  $ hg debugobsolete > ../successors.old
-  $ hg up 0
-  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  $ echo d > d
-  $ hg ci -Am addd d
-  created new head
-  $ echo b >> a
-  $ hg ci -m appendab
-  $ hg rebase -d 1
-  merging a
-  warning: conflicts during merge.
-  merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
-  abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
-  [255]
-  $ hg rebase --abort
-  saved backup bundle to $TESTTMP/repo/.hg/strip-backup/03f165c84ea8-backup.hg
-  rebase aborted
-  $ hg debugobsolete > ../successors.new
-  $ diff -u ../successors.old ../successors.new
-
-Test rebase --continue
-
-  $ hg rebase -d 1
-  merging a
-  warning: conflicts during merge.
-  merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
-  abort: unresolved conflicts (see hg resolve, then hg rebase --continue)
-  [255]
-  $ hg resolve --tool internal:other a
-  $ hg rebase --continue
-  $ glog --hidden
-  @  12:1951ead97108@default(draft) appendab
-  |
-  o  11:03f165c84ea8@default(draft) addd
-  |
-  | x  10:4b9d80f48523@default(draft) appendab
-  | |
-  | x  9:a31943eabc43@default(draft) addd
-  | |
-  +---o  8:a7773ffa7edc@default(draft) Collapsed revision
-  | |
-  | | x  7:03f31481307a@default(draft) changec
-  | | |
-  | | x  6:076e9b2ffbe1@default(draft) addc
-  | |/
-  | | x  5:4e322f7ce8e3@foo(draft) changea
-  | |/
-  +---o  4:9c5494949763@default(draft) adde
-  | |
-  | | x  3:98e4a024635e@default(draft) adde
-  | | |
-  | | o  2:102a90ea7b4a@default(draft) addb
-  | |/
-  o |  1:540395c44225@default(draft) changea
-  |/
-  o  0:07f494440405@default(draft) adda
-  
-  $ hg debugobsolete > ../successors.new
-  $ diff -u ../successors.old ../successors.new
-  --- ../successors.old* (glob)
-  +++ ../successors.new* (glob)
-  @@ -2,3 +2,5 @@
-   4e322f7ce8e3e4203950eac9ece27bf7e45ffa6c 540395c442253af3b991be882b539e7e198b5808 0 {'date': '* *', 'user': 'test'} (glob)
-   076e9b2ffbe11c7bcb9ee97f5c0c8b88a1a10b93 a7773ffa7edcfac27b5dcdb2d5c1036e15a49861 0 {'date': '* *', 'user': 'test'} (glob)
-   03f31481307aaf5275d07ec28c1c59931759ccd2 a7773ffa7edcfac27b5dcdb2d5c1036e15a49861 0 {'date': '* *', 'user': 'test'} (glob)
-  +a31943eabc4327df16f9eca71bf7779c32f815f7 03f165c84ea8889fc35a64a392caa7a0084dd212 0 {'date': '* *', 'user': 'test'} (glob)
-  +4b9d80f48523e296f4402cc8e37236b768dfb981 1951ead9710803dbf117e95901954d5ed717f80b 0 {'date': '* *', 'user': 'test'} (glob)
-  [1]
-
-Test hg pull --rebase
-
-  $ hg glog
-  @  changeset:   12:1951ead97108
-  |  tag:         tip
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     appendab
-  |
-  o  changeset:   11:03f165c84ea8
</