histedit: replace various nodes lists with replacement graph (and issue3582)

This changeset rewrites the change tracking logic of histedit to record every
operation it does. Tracked operations record the full list of "old" node that
will eventually be removed to the list of new nodes that replace it. Operations
on temporary nodes are tracked too. Dropped changesets are also recorded as an
"old" node replacement by nothing. This logic is similar to the obsolescence
marker one and will be used for this purpose in later commit.

This new logic implies a big amount of change in the histedit code base.

histedit action functions now always return a tuple of

    (new-ctx, [list of rewriting operations])

The old `created`, `replaced` and `tmpnodes` are no longer returned and stored
during histedit operation. When such information is necessary it is computed
from the replacement graph. This computation is done in the `processreplacement`
function.

The `replacemap` is also dropped. It is computed at the end of the command from the
graph.  The `bootstrapcontinue` methods are altered to compute this different kind of
information.

This new mechanism requires much less information to be written on disk.

Note:

    This changes allows a more accurate bookmark movement. bookmark on dropped
    changeset are now move of their parent (or replacement of their parent)
    instead of their children.

    This fix issue3582
histedit: add obsolete support

When the obsolete feature is enabled, histedit creates obsolescence marker
instead of stripping replaced changesets.

For now, we keep stripping temporary nodes created along the way.
histedit: simplify computation of edited set (issue3620)

This complex code can be replaced by two simple revset calls.
histedit: ignores hidden revision when checking for orphaned nodes

We do not want hidden revision to block histedit. They are already "dead"
and we do not care about dead orphans. see similar changeset 9e2dc0d292cd for
rebase.
histedit: refuse to edit public changeset

Public changeset are immutable. This changeset enforce that in histedit.
vfs: backout fchmod change from 76b73ce0ffac

Only works on Unix with Python >= 2.6, need a different fix.

--HG--
extra : rebase_source : 0223305b312c6f65c95e1b9904374559b794a6e1
test: fix invalid redirection for histedit text

Appending to the file is wrong, we want new content.

--HG--
extra : rebase_source : 23b0bb576798cc070048a8491466435af4fdb286
histedit: rename `revs` in `ctxs` inside the `between` function

The variable content is actually contexts, not revision numbers.

--HG--
extra : rebase_source : f03de323cf6fa4ac0eb3a5b1e83af2f68167c52b
histedit: clean abort when there is nothing to edit

--HG--
extra : rebase_source : d24d85c57744dc4f2e33f1da6897117721a05728
histedit: do not use "min" on ctx

It does not crash but does not compare revision number at all. We actually
remove any call to min because the list is already topologically sorted.

--HG--
extra : rebase_source : a04887aaaf1558f7b1cf8a49045cdc038d1726a8
vfs: use self.write to write symlink placeholders

The existing write() path is much more robust than the hand-rolled
version that was inlined here.