Commit Graph

446 Commits

Author SHA1 Message Date
Jun Wu
a3005e76f2 rebase: move bookmark to destination for commits becoming empty (issue5627)
When rebasing a changeset X and that changeset becomes empty, we should move
the bookmark on X to rebase destination.

This is a regression caused by the scmutil.cleanupnodes refactoring for
rebase.

The `adjustdest` function calculates the destination of bookmark movement.
It was back-ported from https://phab.mercurial-scm.org/D21. It might be
slightly more powerful than the minimal requirement to solve this issue.
For example, it's impossible for a merge changeset to become empty while any
of its ancestors does not become empty, but the code could handle that case.
Since the code is reasonably short and clean, and helps the upcoming D21
series, I'd like to check-in `adjustdest` now.

Thanks Martin von Zweigbergk for spotting corner cases (-k and descendant
with bookmarks) in this area!
2017-07-24 23:52:56 -07:00
Durham Goode
7ab951502c rebase: add config to move rebase into a single transaction
This was previously landed as 507f16f4aa51 but backed out in a5abaa81fa because
it broke hook mid rebase and caused conflict resolution data loss in the event
of unexpected exceptions. This new version adds the behavior back but behind a
config flag, since the performance improvement is notable in large repositories.

The next patch adds a test covering this config.

The old commit message was:

Previously, rebasing would open several transaction over the course of rebasing
several commits. Opening a transaction can have notable overhead (like copying
the dirstate) which can add up when rebasing many commits.

This patch adds a single large transaction around the actual commit rebase
operation, with a catch for intervention which serializes the current state if
we need to drop back to the terminal for user intervention. Amazingly, almost
all the tests seem to pass.

On large repos with large working copies, this can speed up rebasing 7 commits
by 25%. I'd expect the percentage to be a bit larger for rebasing even more
commits.

There are minor test changes because we're rolling back the entire transaction
during unexpected exceptions instead of just stopping mid-rebase, so there's no
more backup bundle. It also leave an unknown file in the working copy, since our
clean up 'hg update' doesn't delete unknown files.
(grafted from cca36c7f35261b0e31beb226bf361067ef0e06ab)
(grafted from dc497d8705b71503e32e07bd33925c1e42cf9c9a)

Differential Revision: https://phab.mercurial-scm.org/D134
2017-07-18 07:47:28 -07:00
Jun Wu
8046e7f0bb rebase: remove "if True"
The "if True" block was to make the last patch easier to review. This patch
removes "if True" and unindents the block.
2017-07-07 19:03:03 -07:00
Jun Wu
936199e02d rebase: use scmutil.cleanupnodes (issue5606) (BC)
This patch migrates rebase to use scmutil.cleanupnodes API. It simplifies
the code and makes rebase code reusable inside a transaction.

This is a BC because the backup file is no longer strip-backup/*-backup.hg,
but strip-backup/*-rebase.hg. The latter looks more reasonable since the
directory name is "strip-backup" so there is no need to repeat "backup".

I think the backup file name change is probably fine as a BC, since we have
changed it before (2e51c9a7a08f) and didn't get complains. The end result
of this series will be a much more consistent and unified backup names:

  command  | old backup file suffix       | new backup file suffix
  -------------------------------------------------------------------
  amend    | amend-backup.hg              | amend.hg
  histedit | backup.hg (could be 2 files) | histedit.hg (single file)
  rebase   | backup.hg                    | rebase.hg
  strip    | backup.hg                    | backup.hg

(note: backup files are under .hg/strip-backup)

It also fixes issue5606 as a side effect because the new "delayedstrip" code
path will carefully examine nodes (safestriproots) to make sure orphaned
changesets won't get stripped by accident.

Some warning messages are changed to the new "warning: orphaned descendants
detected, not stripping HASHES", which provides more information about
exactly what changesets are left behind.

Another minor behavior change is when there is an obsoleted changeset with a
successor in the destination branch, bookmarks pointing to that obsoleted
changeset will not be moved. I have commented in test-rebase-obsolete.t
explaining why that is more desirable.
2017-07-07 18:51:46 -07:00
Martin von Zweigbergk
6ec81d71ce rebase: always pass destination as revnum to _handleskippingobsolete()
We were passing it as a revision number in one place and as a context
in another. It worked because the only use was in "repo[dest].rev()",
but it was confusing. By always passing a revision number, we can also
remove that unnecessary lookup.
2017-06-28 14:53:54 -07:00
Pierre-Yves David
719387c7c7 obsutil: move 'allsuccessors' to the new modules
We have a new 'obsutil' module now. We move the high level utility there to bring
'obsolete.py' back to a more reasonable size.
2017-06-27 01:36:20 +02:00
Martin von Zweigbergk
3ce6c1796d merge with stable 2017-06-29 15:21:52 -07:00
Pierre-Yves David
17353b92ba rebase: backed out changeset 507f16f4aa51 (issue5610)
Having a single transaction for rebase means the whole transaction gets rolled back
on error. To work around this a small hack has been added to detect merge
conflict and commit the work done so far before exiting. This hack works because
there is nothing transaction related going on during the merge phase.

However, if a hook blocks the rebase to create a changeset, it is too late to commit the
work done in the transaction before the problematic changeset was created. This
leads to the whole rebase so far being rolled back. Losing merge resolution and
other work in the process. (note: rebase state will be fully lost too).

Since issue5610 is a pretty serious regression and the next stable release is a
couple day away, we are taking the backout route until we can figure out
something better to do.
2017-06-27 17:40:24 +02:00
Pierre-Yves David
70672e4541 rebase: backed out changeset 4bc0c14fb501
In the process of fixing issue5610 in 4.2.2, we are trying to backout
507f16f4aa51. This changeset is making changes that depend on 507f16f4aa51,
so we need to back it out first.

Since issue5610 is pretty serious regression and the next stable release is a
couple of days away, we are taking the backout route until we can figure out
something better to do.
2017-06-27 17:39:55 +02:00
Jun Wu
e906874924 rebase: clean up rebasestate from active transaction
Previously, rebase assumes the following pattern:

    rebase:
        with transaction as tr: # top-level
            ...
        tr.__close__ writes rebasestate
        unlink('rebasestate')

However it's possible that "rebase" was called inside a transaction:

    with transaction as tr1:
        rebase:
            with transaction as tr2: # not top-level
                ...
            tr2.__close__ does not write rebasestate
            unlink('rebasestate')
    tr1.__close__ writes rebasestate

That leaves a rebasestate on disk incorrectly.

This patch adds "removefilegenerator" to notify transaction code that the
state file is no longer needed therefore fixes the issue.
2017-06-24 21:13:48 -07:00
Martin von Zweigbergk
aac8f4879e rebase: use context manager for locking in pullrebase() 2017-06-19 11:18:12 -07:00
Martin von Zweigbergk
042e7bf238 rebase: use context manager for locking in rebase() 2017-06-19 11:18:05 -07:00
FUJIWARA Katsunori
6eec3cc46a help: apply bulk fixes for indentation and literal blocking issues
There are some paragraphs, which aren't rendered in online help as
expected because of indentation and literal blocking issues.

- hgext/rebase.py

  - paragraph before example code ends with ":", which treats
    subsequent indented paragraphs as normal block

    => replace ":" with "::" to treat subsequent paragraphs as literal block

- help/pager.txt

  - paragraph before a list of --pager option values ends with "::",
    which treats subsequent indented paragraphs as literal block

    => replace "::" with ":" to treat subsequent paragraphs as normal block

  - the second line of explanation for no/off --pager option value is
    indented incorrectly (this also causes failure of "make" in doc)

    => indent correctly

- help/revisions.txt

  - explanation following example code of "[revsetalias]" section
    isn't suitable for literal block

    => un-indent explanation paragraph to treat it as normal block

  - indentation of "For example" before example of tag() revset
    predicate matching is meaningless

  - descriptive text for tag() revset predicate matching isn't
    suitable for literal block

    => un-indent concatenated two paragraphs to treat them as normal block
2017-05-01 05:52:32 +09:00
FUJIWARA Katsunori
262750cefb rebase: fix incorrect configuration example
This configuration example doesn't make rebase require a destination,
even though help document wants to show such example.
2017-05-01 05:38:52 +09:00
Martin von Zweigbergk
f173705214 rebase: rewrite "x in y.children()" as "y in x.parents()"
children() is slow
2017-06-17 23:09:47 -07:00
Ryan McElroy
a42e2a36a6 rebase: abort hg pull --rebase if rebase.requiredest is set (issue5514)
Previously, the pull would succeed, but the subsequent rebase would fail due
to the rebase.requiredest flag. Now abort earlier with a more useful error
message.
2017-03-30 03:50:10 -07:00
Ryan McElroy
892a9acab3 rebase: allow destination-free continue and abort (issue5513) 2017-03-30 03:50:10 -07:00
Martin von Zweigbergk
6a886bd950 rebase: don't require destination if commands.rebase.requiredest=False 2017-03-24 16:20:10 -07:00
Durham Goode
de02ce8716 rebase: move state serialization to use unfiltered repo
Now that rebasestate is serialized as part of the transaction, the repo state it
sees is the version at the end of the transaction, which may have hidden nodes.
Therefore, it's possible parts of the rebase commit set are no longer visible by
the time the transaction is closing, which causes a filtered revision error in
this code. I don't think state serialization should be blocked from accessing
commits it knows exist, especially if all it's trying to do is get the hex of
them, so let's use an unfiltered repo here.

Unfortunately, the only known repro is with the fbamend Facebook extension, so
I'm not sure how to repro it in core Mercurial for a test.
2017-03-12 12:33:35 -07:00
Martin von Zweigbergk
dc4c37c445 plain: ignore [commands] config
We only have commands.{update,rebase}.requiredest so far. We should
clearly ignore those two if HGPLAIN is in effect, and it seems like we
should ignore any future config that will be added in [commands] since
that is about changing the behavior of commands.

Thanks to Yuya for suggesting to centralize the code in ui.py.

While at it, remove the unnecessary False values passed to
ui.configbool() for the aforementioned config options.
2017-03-21 21:26:52 -07:00
Siddharth Agarwal
320ab6e3cf rebase: drop unnecessary parentchange call
We're calling localrepo.setparents here, not dirstate.setparents.
localrepo.setparents calls dirstate.parentchange already.
2017-05-31 19:46:04 -07:00
Martin von Zweigbergk
782a1185dc hidden: rename "revealedrevs" to "pinnedrevs" (API)
E.g. tags and bookmarks can reveal revisions that would otherwise be
hidden. A revision can also be revealed because one if its descendants
is visible. Let's use the term "pinned" for the former case
(bookmarks etc.).
2017-05-27 21:08:51 -07:00
Ryan McElroy
8198e58557 rebase: add flag to require destination
In some mercurial workflows, the default destination for rebase does not
always work well and can lead to confusing behavior. With this flag enabled,
every rebase command will require passing an explicit destination, eliminating
this confusion.
2017-03-14 17:43:44 -07:00
Durham Goode
c54132949d rebase: use one dirstateguard for entire rebase
Recently we switched rebases to run the entire rebase inside a single
transaction, which dramatically improved the speed of rebases in repos with
large working copies. Let's also move the dirstate into a single dirstateguard
to get the same benefits. This let's us avoid serializing the dirstate after
each commit.

In a large repo, rebasing 27 commits is sped up by about 20%.

I believe the test changes are because us touching the dirstate gave the
transaction something to actually rollback.
2017-03-19 11:54:15 -07:00
Jun Wu
bef3efe46f rebase: get rid of ui.backupconfig 2017-03-16 14:40:34 -07:00
Pierre-Yves David
9f5b98723a rebase: explicitly tests for None
Changeset 33b71926122d removed the mutable default value, but did not explicitly
tested for None. Such implicit checking can introduce semantic and performance
issue. We move to an explicit check for None as recommended by PEP8:

https://www.python.org/dev/peps/pep-0008/#programming-recommendations
2017-03-15 15:03:43 -07:00
Gregory Szorc
547d4e1ec5 rebase: don't use mutable default argument value 2017-03-12 21:56:39 -07:00
Mads Kiilerich
b41f3f4681 rebase: allow rebasing children of wd to wd if a new branch has been set (BC)
The named branch of the leaf changeset can be changed by updating to it,
setting the branch, and amending.

But previously, there was no good way to *just* change the branch of several
linear changes. If rebasing changes with another parent to '.', it would pick
up a pending branch change up. But when rebasing changes that have the same
parent, it would fail with 'nothing to rebase', even when the branch name was
set differently.

To fix this, allow rebasing to same parent when a branch has been set.
2017-03-12 16:44:01 -07:00
Pierre-Yves David
b02205e9d6 repoview: rename '_getdynamicblockers' to 'revealedrevs' (API)
Recent mailing list discussion made me realised we could clarify these. We make
the function "public" to encourage extensions to wrap it and we use a more
explicit name that mirror "hideablerevs".
2017-05-20 19:43:58 +02:00
Yuya Nishihara
6c2103bc71 commands: move templates of common command options to cmdutil (API)
The goal is to get rid of the debugcommands -> commands dependency.

Since globalopts is the property of the commands, it's kept in the commands
module.
2017-05-14 16:19:47 +09:00
Augie Fackler
dd53cf64c4 rebase: migrate to context manager for changing dirstate parents 2017-05-18 17:11:01 -04:00
Yuya Nishihara
3e663dde68 registrar: move cmdutil.command to registrar module (API)
cmdutil.command wasn't a member of the registrar framework only for a
historical reason. Let's make that happen. This patch keeps cmdutil.command
as an alias for extension compatibility.
2016-01-09 23:07:20 +09:00
Durham Goode
77dcefda06 obsolete: add operation metadata to rebase/amend/histedit obsmarkers
By recording what operation created the obsmarker, we can show very intuitive
messages to the user in various UIs. For instance, log output could have
messages like "Amended as XXX" to show why a commit is old and has an 'x' on it.

     @  ac28e3  durham
    /   First commit
   |
   | o  d4afe7 durham
   | |  Second commit
   | |
   | x  8e9a5d (Amended as ac28e3)  durham
   |/   First commit
   |
2017-05-09 16:29:31 -07:00
Jeremy Fitzhardinge
429da32f1a rebase: make sure merge state is cleaned up for no-op rebases (issue5494)
If a rebase ends up doing a no-op commit, make sure the merge state is still cleaned up.
2017-05-18 13:18:05 -07:00
Martin von Zweigbergk
c3406ac3db cleanup: use set literals
We no longer support Python 2.6, so we can now use set literals.
2017-02-10 16:56:29 -08:00
Martin von Zweigbergk
ecac8d45a0 rebase: allow rebase even if some revisions need no rebase (BC) (issue5422)
This allows you to do e.g. "hg rebase -d @ -r 'draft()'" even if some
drafts are already based off of @. You'd still need to exclude
obsolete and troubled revisions, though. We will deal with those cases
later.

Implemented by treating state[rev]==rev as "no need to rebase". I
considered adding another fake revision number like revdone=-6. That
would make the code clearer in a few places, but would add extra code
in other places.

I moved the existing test out of test-rebase-base.t and into a new
file and added more tests there, since not all are using --base.
2017-05-11 11:37:18 -07:00
Martin von Zweigbergk
2f96143f27 rebase: rename "target" to "destination" in messages
The help text for rebase calls it "the destination" (never "target"),
so let's use that in messages as well.
2017-05-11 22:38:15 -07:00
Martin von Zweigbergk
82f161dd68 rebase: rename "target" to "dest" in variable names
It took me a while to figure out that "target" was actually what's
passed to --dest.
2017-05-11 22:38:03 -07:00
Martin von Zweigbergk
a49529bbbf rebase: don't update state dict same way for each root
The update statement does not depend on anything in the loop, so just
move it before the loop and do it once. There are no cases where
update would happen 0 times before (and 1 now); the function returns
early in all such cases.
2017-03-11 12:25:56 -08:00
Mads Kiilerich
975c19c195 vfs: use repo.vfs.unlinkpath 2017-03-11 11:02:25 -08:00
Martin von Zweigbergk
ef133769b3 rebase: abort if *any* commit in rebase set is public 2017-03-11 10:35:44 -08:00
Martin von Zweigbergk
df689070f8 rebase: unhide original working directory node as well (issue5219)
By including the working directory revision at the start of rebase in
the repo._rebaseset, we make sure it's not hidden when we update back
to it at the end of the rebase.

This feels like abusing the set a bit given its name (_rebaseset), but
I couldn't think of another name that's clearly better.
2017-03-10 23:07:20 -08:00
Martin von Zweigbergk
44ffe12623 rebase: pass in a regular set to _setrebasesetvisibility()
Trivial refactoring to simplify the next patch.
2017-03-10 23:06:31 -08:00
Durham Goode
dbb351335e rebase: move actual rebase into a single transaction
Previously, rebasing would open several transaction over the course of rebasing
several commits. Opening a transaction can have notable overhead (like copying
the dirstate) which can add up when rebasing many commits.

This patch adds a single large transaction around the actual commit rebase
operation, with a catch for intervention which serializes the current state if
we need to drop back to the terminal for user intervention. Amazingly, almost
all the tests seem to pass.

On large repos with large working copies, this can speed up rebasing 7 commits
by 25%. I'd expect the percentage to be a bit larger for rebasing even more
commits.

There are minor test changes because we're rolling back the entire transaction
during unexpected exceptions instead of just stopping mid-rebase, so there's no
more backup bundle. It also leave an unknown file in the working copy, since our
clean up 'hg update' doesn't delete unknown files.
2017-03-07 16:27:32 -08:00
Durham Goode
defe69adff rebase: allow aborting if last-message.txt is missing
Previously, if .hg/rebasestate existed but .hg/last-message.txt was missing, 'hg
rebase --abort' would say there's no rebase in progress but 'hg checkout foo'
would say 'abort: rebase in progress'. It turns out loading the collapse message
will throw a "no rebase in progress" error if the file doesn't exist, even
though .hg/rebasestate obviously indicates a rebase is in progress.

The fix is to only throw an exception if we're trying to --continue, and to just
eat the issues if we're doing --abort.

This issue is exposed by us writing the rebase state earlier in the process.
This will be used by later patches to ensure the user can appropriately 'hg
rebase --abort' if there's a crash before the first the first commit has
finished rebasing. Tests cover all of this. The only negative affect is we now
require a hg rebase --abort in a very specific exception case, as shown in the
test.
2017-03-07 16:30:31 -08:00
Durham Goode
f08a205c47 rebase: add storestatus support for transactions
This let's the status writing logic support transactions. This will be useful in
a later patch where we add a transaction around the entire rebase.
2017-03-07 14:04:29 -08:00
Durham Goode
a8f314881e rebase: move storestatus onto rebaseruntime
The rebaseruntime class already has the restorestatus function, so let's make it
own the store status function too. This get's rid of a lot of unnecessary
argument passing and will make a future patch cleaner that refactors storestatus
to support transactions.
2017-03-07 14:11:44 -08:00
Durham Goode
a4583d843e rebase: clear updatestate during rebase --abort in more cases
Previously, rebase --abort would only call update if you were on a node that had
already been rebased. This meant that if the rebase failed during the rebase of
the first commit, the working copy would be left dirty (with a .hg/updatestate
file) and rebase --abort would not have update to clean it up.

The fix is to also perform an update if you're still on the target node or on
the original working copy node (since the working copy may be dirty, we still
need to do the update). We don't want to perform an update in all cases though
because of issue4009.

A subsequent patch makes this case much more common, since it causes the entire
rebase transaction to rollback during unexpected exceptions. This causes the
existing test-rebase-abort.t to cover this case.
2017-03-07 14:19:08 -08:00
Yuya Nishihara
d63d83be69 revset: import set classes directly from smartset module
Follows up 97d0be4019ac.
2017-02-19 18:16:09 +09:00
Martin von Zweigbergk
35aa8c2fe5 rebase: fix code comment to refer to right issue (4504, not 4505)
The comment was introduced in 0a14c8556910 (rebase: ensure rebase
revision remains visible (issue4504), 2015-01-27), which mentions the
right issue in the description.
2017-02-01 08:47:27 -08:00