Previously, `hg histedit` required a revision argument specifying which
revision to use as the base for the current histedit operation. There
was an undocumented and experimental "histedit.defaultrev" option that
supported defining a single revision to be used if no argument is
passed.
Mercurial knows what changesets can be edited. And in most scenarios,
people want to edit this history of everything on the current head that
is rewritable. Making histedit do this by default and not require
an explicit argument or additional configuration is a major usability
win and will enable more people to use histedit.
This patch changes the behavior of the experimental and undocumented
"histedit.defaultrev" config option to select an appropriate base
revision by default. Comprehensive tests exercising the edge cases
in the new, somewhat complicated default revset have been added.
Surprisingly, no tests broke. I guess we were never testing the
behavior with no ANCESTOR argument (it used to fail with
"abort: histedit requires exactly one ancestor revision"). The new
behavior is much more user friendly.
The functionality for choosing the default base revision has been
moved to destutil.py, where it can easily be modified by extensions.
Because labels are applied at write() time since ce03e7329682,
colorui.popbuffer() is useless and it doesn't update _bufferapplylabels
correctly. Removing it should fix the problem.
In 6e6b18aab8b2, I made the mistake of moving the step "clearing the status
after a rebase" to inside the rebase transaction.
This was wrong, since we don't want to clear the status (and the rebase state)
if something went wrong during the transaction: if something goes wrong we
want to keep the rebase state to be able to abort.
It broke rebase with evolve + inhibit.
This change is replacing most of state.rules uses with state.actions
uses. The next change will change histeditstate class to actually
uses state actions.
the format of rules that we store in state file format is different from the rule
format that we present to users. We need a way of dumping action to state file.
To make histedit action objects responsible for understanding
the format of their action lines we are adding a torule method
which for a histedit action will return a string which can be
saved in histedit state or shown in text editor when editing the
plan.
This commits splits the parsing of the histedit rule from its semantic analysis.
It's necessary because sometimes we want to do first without doing the former (reading the
histedit state).
This decorator will is allowing us to move the registering the action
in actiontable closer to the action code. Also it is storing the
verb inside histedit action so the action is aware of the verb
needed to trigger it.
I want to refactor histedit to use action objects instead of (verb, rest)
pairs whenever possible. At the end of this series I want the rules to
be translated into action objects when reading state and translated back
when writing state. All histedit internals should use action objects instead
of state rules.
To migrate histedti internals sequentially I'm introducing the state.actions
property to translate rules on the fly so we can use both state.actions and
state.rules until refactoring is done.
Before this patch, "hg shelve" of shelve extension executes
'cmdutil.checkunfinished()' before acquisition of wlock.
It may cause unintentional result, if another command runs parallelly
(see also issue4368).
To avoid this issue, this patch executes 'cmdutil.checkunfinished()'
inside wlock scope of "hg shelve".
This also fixes issue4957, because now 'cmdutil.checkunfinished()'
isn't invoked at "hg shelve" with options below:
--cleanup
--delete
--list
--patch
--stat
Before this patch, "hg shelve" of shelve extension executes/refers
below before acquisition of wlock:
- 'repo.dirstate.parents()' via 'repo[None].parents()'
- 'repo._activebookmark'
It may cause unintentional result, if another command runs parallelly
(see also issue4368).
This patch widens wlock scope of "hg shelve" of shelve extension for
consistency while processing.
Before this patch, "hg sign" of gpg extension executes/evaluates below
without acquisition of wlock.
- repo.dirstate.parents()
- '.hgsigs' not in repo.dirstate
It may cause unintentional result, if another command runs parallelly
(see also issue4368).
To avoid this issue, this patch makes "hg sign" of gpg extension
acquire wlock before processing.
Users may spend a lot of effort writing histedit rules,
getting an abort without being told they can recover their work
is very frustrating.
Avoid that by telling them where to find their work.
localrepo.parents() has relatively few users, and most of those were
actually implicitly looking at the wctx, which is now made explicit
via repo[None].
This should have been done as part of or as an immediate follow-up to
01b01d59e33f, but presumably this feature of extensions.py was
forgotten at that time.
In many cases, we don't need to cast to a str because the object will
be cast when it is eventually written.
As part of testing this, I added some code to raise exceptions when a
non-str was passed in and wasn't able to trigger it. i.e. we're already
passing str into this function everywhere, so the casting isn't
necessary.
Previously, we stored 2-tuples of text and label in a list and then
evaluated the labels when the buffer was popped. After this patch,
we evaluate the labels at write time and do a simple join when the
buffer is popped.
This patch appears to have no impact on performance, despite creating
fewer 2-tuples and having fewer strings hanging around in memory.
If detailed conflict markers are enabled and the closing quote gets truncated,
editors will often screw syntax highlighting up from that point because they'll
see an opening quote and think it's the beginning of a string.
In tests, the hashes change because the commit messages of the shelved bundles
also change.
Used a class as a namespace, and then wired up a classmethod to return
all known constraints. I'm mostly happy with this, even though it's
kind of weird for hg.
This is a first (very simple) version of the histedit base action.
It works well in common usecases like rebasing the whole stack and
spliting the stack.
I don't see any obvious edge cases - but probably there is more than one.
That's why I want to keep it behind experimental.histeditng config knob
for now. I think on knob for all new histedit behaviors is better because
we will test all of them together and testers will need to turn it on only
once to get all new nice things.
For the future 'base' action in histedit we need a verification
constraint which will not allow using this action with changes
that are currently edited.
Before we can add a 'base' action to histedit need to change verification
so that action can specify which steps of verification should run for it.
Also it's everything we need for the exec and stop actions implementation.
I thought about baking verification into each histedit action (so each
of them is responsible for verifying its constraints) but it felt wrong
because:
- every action would need to know its context (eg. the list of all other
actions)
- a lot of duplicated work will be added - each action will iterate through
all others
- the steps of the verification would need to be extracted and named anyway
in order to be reused
The verifyrules function grows too big now. I plan to refator it in one of
the next series.
Before this patch we were using the old api bookmarks.write instead of
bookmarks.recordchange at the end of rebase operations.
We move clearstatus within the transaction to make it easier for extensions
that wrap transactions operations.
Before this patch, strip was using repo._bookmarks.write.
This patch replaces this code with the recommended way of saving bookmarks
changes: repo._bookmarks.recordchange.
Before this patch we were using the old api bookmarks.write, this patches
replaces its usage by bookmarks.recordchange, the new api to record bookmark
changes.
The largefiles merge code (currently) does not handle change/delete conflicts.
So fall back to regular filemerge in that case.
Making this code handle change/delete conflicts is left as an exercise for the
future.
Currently strip works with a single bookmark,
the changes in this patch modifies the strip module
to work with a list of bookmarks
Building on this we can take a list of bookmarks as input
and remove all of them in a single go