Commit Graph

409 Commits

Author SHA1 Message Date
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
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
Valters Vingolds
0b2827adb4 rebase: provide detailed hint to abort message if working dir is not clean
Detailed hint message is now provided when 'pull --rebase' operation detects
unclean working dir, for example:
  abort: uncommitted changes
  (cannot pull with rebase: please commit or shelve your changes first)

Added tests for uncommitted merge, and for subrepo support verifying that same
hint is also passed to subrepo state check.
2017-01-10 09:32:27 +01:00
Valters Vingolds
736c95f47e rebase: fail-fast the pull if working dir is not clean (BC)
Refuse to run 'hg pull --rebase' if there are uncommitted changes:
so that instead of going ahead with fetching changes and then suddenly aborting
the rebase, we can warn user of uncommitted changes (or unclean repo state)
right up front.
In tests, we create a 'histedit' session to verify that also an unfinished
state is detected and handled.
2017-01-01 13:16:29 +01:00
Valters Vingolds
ec79496a8a rebase: use repo.vfs.exists in 'hg summary' hook 2017-01-06 09:58:41 +01:00
Augie Fackler
d2c2a6fb47 rebase: un-wrap function signature since it fits in 80 columns 2016-12-24 15:38:27 -05:00
Jun Wu
3f639e27a5 rebase: calculate ancestors for --base separately (issue5420)
Previously, the --base option only works with a single "branch" - if there
is one changeset in the "--base" revset whose branching point(s) is/are
different from another changeset in the "--base" revset, "rebase" will error
out with:

  abort: source is ancestor of destination

This happens if the user has multiple draft branches, and uses "hg rebase -b
'draft()' -d master", for example. The error message looks cryptic to users
who don't know the implementation detail.

This patch changes the logic to calculate the common ancestor for every
"base" changeset separately so we won't (incorrectly) select "source" which
is an ancestor of the destination.

This patch should not change the behavior where all changesets specified by
"--base" have the same branching point(s).

A new situation is: some of the specified changesets could be rebased, while
some couldn't (because they are descendants of the destination, or they do
not share a common ancestor with the destination). The current behavior is
to show "nothing to rebase" and exits with 1.

This patch maintains the current behavior (show "nothing to rebase") even if
part of the "--base" revset could be rebased. A clearer error message may be
"cannot find branching point for X", or "X is a descendant of destination".
The error message issue is tracked by issue5422 separately.

A test is added with all kinds of tricky cases I could think of for now.
2016-11-28 05:45:22 +00:00
Augie Fackler
34a63fb4c6 rebase: refer to checkunresolved by its new name 2016-11-21 21:32:39 -05:00
Augie Fackler
85ea394346 rebase: refer to dirstateguard by its new name 2016-11-21 21:27:12 -05:00
Durham Goode
0f5c8089bc rebase: move bookmark update to before rebase clearing
Bookmark fixing should probably happen before the rebase starts to clean up, so
let's move it before clearrebased. This will also help a future patch where we
want to add more clear logic to the existing clear section.
2016-11-10 09:21:41 -08:00
Mads Kiilerich
38cb771268 spelling: fixes of non-dictionary words 2016-10-17 23:16:55 +02:00
timeless
ae4cf4bf09 rebase: check for conflicts before continuing
When there are unresolved merge conflicts, there is no reason
to make the user wait for rebase to process all of the
already rebased commits just to complain that it cannot do
anything. Abort early.
2016-11-02 18:59:29 +00:00
timeless
0deb5c6d90 rebase: rename merge to mergemod 2016-11-02 18:56:07 +00:00
Xidorn Quan
a5b2da437e rebase: rebase changesets in topo order (issue5370) (BC)
There are two reasons that rebase should be done this way:
1. This would make rebasing faster because it would minimize the total
   number of files to be checked out in the process, as it don't need
   to switch back and forth between branches.
2. It makes resolving conflicts easier as user has a better context.

This commit changes the behavior in "Test multiple root handling" of
test-rebase-obsolete.t. It is an expected change which reflects the new
behavior that commits in a branch are grouped together when rebased.
2016-09-17 17:02:56 +10:00
timeless
1be7bec44c rebase: use single quotes in use warning 2016-09-20 23:44:28 +00:00
Martin von Zweigbergk
a0ebc57925 rebase: make debug logging more consistent
We emit some lines that mix revision numbers with nodeids, which makes
little sense to me.
2016-09-13 13:49:42 -07:00
timeless
faab59b629 rebase: properly calculate total commits to rebase (issue5347)
Before this, predecessor commits were being included in the count
2016-08-26 00:16:51 +00:00
Augie Fackler
4e1c384d0a extensions: change magic "shipped with hg" string
I've caught multiple extensions in the wild lying about being
'internal', so it's time to move the goalposts on people. Goalpost
moving will continue until third party extensions stop trying to
defeat the system.
2016-08-23 11:26:08 -04:00
Simon Farnsworth
196af0f28e rebase: turn rebase revs into set before filtering obsolete
When the inhibit extension from mutable-history is enabled, it attempts to
iterate over the rebaseset to prevent the nodes being rebased from being
marked obsolete. This happens at the same time as rebase's
_filterobsoleterevs function trying to iterate over the rebaseset to figure
out which ones are obsolete. The two of these iterating over the same
revset generatorset cause a 'generator already executing' exception. This is
probably a flaw in the revset implementation, since iterating over the same
set twice should be supported.

This regression was introduced in 5d16ebe7b14, since it changed
_filterobsoleterevs to be called before the rebaseset was turned into a
set(). For now let’s just make the rebaseset an actual set again before
calling that function. This was caught by the inhibit tests.

The relevant call stack from test-inhibit.t:

   File "/tmp/hgtests.jgjrN5/install/lib/python/hgext/rebase.py", line 285, in _preparenewrebase
     obsrevs = _filterobsoleterevs(self.repo, rebaseset)
   File "/data/hgbuild/facebook-hg-rpms/mutable-history/hgext/inhibit.py", line 197, in _filterobsoleterevswrap
     r = orig(repo, rebasesetrevs, *args, **kwargs)
   File "/tmp/hgtests.jgjrN5/install/lib/python/hgext/rebase.py", line 1380, in _filterobsoleterevs
     return set(r for r in revs if repo[r].obsolete())
   File "/tmp/hgtests.jgjrN5/install/lib/python/hgext/rebase.py", line 1380, in <genexpr>
     return set(r for r in revs if repo[r].obsolete())
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/revset.py", line 3079, in _iterordered
     val2 = next(iter2)
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/revset.py", line 3417, in gen
     yield nextrev()
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/revset.py", line 3424, in _consumegen
     for item in self._gen:
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/revset.py", line 71, in iterate
     cl = repo.changelog
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/repoview.py", line 319, in changelog
     revs = filterrevs(unfi, self.filtername)
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/repoview.py", line 261, in filterrevs
     repo.filteredrevcache[filtername] = func(repo.unfiltered())
   File "/data/hgbuild/facebook-hg-rpms/mutable-history/hgext/directaccess.py", line 65, in _computehidden
     hidden = repoview.filterrevs(repo, 'visible')
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/repoview.py", line 261, in filterrevs
     repo.filteredrevcache[filtername] = func(repo.unfiltered())
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/repoview.py", line 175, in computehidden
     hideable = hideablerevs(repo)
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/repoview.py", line 33, in hideablerevs
     return obsolete.getrevs(repo, 'obsolete')
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/obsolete.py", line 1097, in getrevs
     repo.obsstore.caches[name] = cachefuncs[name](repo)
   File "/data/hgbuild/facebook-hg-rpms/mutable-history/hgext/inhibit.py", line 255, in _computeobsoleteset
     if getrev(n) not in blacklist:
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/revset.py", line 3264, in __contains__
     return x in self._r1 or x in self._r2
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/revset.py", line 3348, in __contains__
     for l in self._consumegen():
   File "/tmp/hgtests.jgjrN5/install/lib/python/mercurial/revset.py", line 3424, in _consumegen
     for item in self._gen:
 ValueError: generator already executing
2016-07-19 03:29:53 -07:00
Kostia Balytskyi
847780e6fe rebase: remove sortedstate-related confusion
The following rebase implementation details are frustrating:
- storing a list of sorted revision numbers in a field named sortedstate
- having sortedstate be a field of the rebaseruntime class
- using sortedstate[-1] as opposed to a more intuitive max(self.state) to
  compute the latest revision in the state

This commit fixes those imperfections.
2016-07-14 03:12:09 -07:00
Kostia Balytskyi
1c4ad1d1d3 rebase: replace extrafn field with _makeextrafn invocations
As per Yuya's advice, we would like to slightly reduce the amount of state
which is stored in rebaseruntime class. In this case, we don't need to store
extrafn field, as we can produce the necessary value by calling _makeextrafn
and the perf overhead is negligible.
2016-07-14 02:59:27 -07:00
Kostia Balytskyi
a6f612e44f rebase: move handling of obsolete commits to be a separate RR class method 2016-07-01 14:09:53 +02:00
Kostia Balytskyi
c56035ebe4 rebase: move rebase finish logic to be a method of the RR class
Rebase finish logic includes collapsing working directorystate into
a single commit, moving bookmarks, clearing status and collapsemsg files,
reporting skipped commits to the user and obsoleting precursors of the
newly created commits.
2016-07-01 14:09:53 +02:00
Kostia Balytskyi
aa32920473 rebase: move core rebase logic to be a method of the RR class 2016-07-01 14:09:53 +02:00
Kostia Balytskyi
5b06bb7da5 rebase: move local variable 'extrafn' to the RR class 2016-07-01 14:09:53 +02:00
Kostia Balytskyi
ae0baad3c5 rebase: move local variable 'currentbookmarks' to the RR class 2016-07-01 14:09:53 +02:00
Kostia Balytskyi
f2b722d727 rebase: make collapsing use explicit logic to decide on the rev to reuse
This code:

    for rev in sortedstate:
        ...
    ...
    newnode = concludenode(repo, rev, p1, rbsrt.external,
                           commitmsg=commitmsg,
                           extrafn=extrafn, editor=editor,
                           keepbranches=rbsrt.keepbranchesf,
                           date=rbsrt.date)

uses 'rev' variable in 'concludenode' function invocation. It is not
explicitly assigned before, but its value comes as last value or 'rev' in
a for loop, e.g. last element in a 'sortedstate'. IMO this a bad style and it
also makes it hard to refactor the function, so it is better to explicitly
define the value passed to 'concludenode'.
2016-07-01 14:09:53 +02:00
Kostia Balytskyi
936c3aec9f rebase: move new rebase preparation to be a method of the RR class
This commit moves logic that prepares the execution of a new rebase
operation to be a method of the rebaseruntime class.
2016-07-01 14:09:53 +02:00
Kostia Balytskyi
0946a3aa1d rebase: move abort/continue prep to be a method of the RR class
This commit moves logic that prepares the execution of abort and
continue phases or rebase operation to be a method of the rebaseruntime
class.
2016-07-01 14:09:53 +02:00
Kostia Balytskyi
a7adcda5dc rebase: move local variable 'obsoletenotrebased' to the RR class 2016-06-21 06:29:23 -07:00
Kostia Balytskyi
c0f90a3ffa rebase: move restorestestatus function to be a method of the RR class 2016-06-21 06:29:23 -07:00
Kostia Balytskyi
b5102baa59 rebase: move local variables related to keeping things unchanged to the RR
This commit moves the following variables, local to the rebase function to be
fields of the rebaseruntime:
 -keepf
 -keepbranchesf
 -keepopen
2016-06-21 06:29:23 -07:00
Kostia Balytskyi
7ea5cc73ed rebase: move local variables 'date' and 'extrafns' to the RR class
This commit moves the following variables, local to the rebase function to be
fields of the rebaseruntime:
 -date
 -extrafns
2016-06-21 06:29:23 -07:00
Kostia Balytskyi
66b3ef340b rebase: move collapse-related local variables to the RR class
This commit moves the following variables local to the 'rebase' function
to be fields of the rebaseruntime class:
 -collapsef
 -collapsemsg
2016-06-21 06:29:23 -07:00
Kostia Balytskyi
d75ec97b9b rebase: pass repo, ui and opts objects to the RR class constructor 2016-06-21 07:22:49 -07:00
Kostia Balytskyi
305d79a43c rebase: do not abort if all changesets have equivalents in the destination 2016-06-17 16:59:08 +01:00
Kostia Balytskyi
82f69b2833 rebase: move local variable 'targetancestors' to the RR class 2016-06-13 22:41:45 +01:00
Kostia Balytskyi
e83111af7f rebase: move local variable 'skipped' to the RR class 2016-06-13 22:40:59 +01:00
Kostia Balytskyi
648a368d05 rebase: move local variable 'target' to the RR class 2016-06-13 22:38:54 +01:00