diff --git a/hgext/rebase.py b/hgext/rebase.py --- a/hgext/rebase.py +++ b/hgext/rebase.py @@ -34,7 +34,6 @@ dirstateguard, error, extensions, - hg, lock, merge as mergemod, mergeutil, @@ -533,22 +532,12 @@ if 'qtip' in repo.tags(): updatemq(repo, self.state, self.skipped, **opts) - # restore original working directory - # (we do this before stripping) - newwd = self.state.get(self.originalwd, self.originalwd) - if newwd < 0: - # original directory is a parent of rebase set root or ignored - newwd = self.originalwd - if newwd not in [c.rev() for c in repo[None].parents()]: - ui.note(_("update back to initial working directory parent\n")) - hg.updaterepo(repo, newwd, False) - collapsedas = None if not self.keepf: if self.collapsef: collapsedas = newnode clearrebased(ui, repo, self.destmap, self.state, self.skipped, - collapsedas, self.keepf) + collapsedas, self.keepf, self.originalwd) clearstatus(repo) clearcollapsemsg(repo) @@ -1513,7 +1502,7 @@ return originalwd, destmap, state def clearrebased(ui, repo, destmap, state, skipped, collapsedas=None, - keepf=False): + keepf=False, originalwd=None): """dispose of rebased revision at the end of the rebase If `collapsedas` is not None, the rebase was a collapse whose result if the @@ -1521,6 +1510,8 @@ If `keepf` is not True, the rebase has --keep set and no nodes should be removed (but bookmarks still need to be moved). + + If `originalwd` is not None, working parent will be moved. """ tonode = repo.changelog.node mapping = {} @@ -1535,7 +1526,9 @@ succs = (newnode,) value['new'] = succs mapping[tonode(rev)] = value - scmutil.cleanupnodes(repo, mapping, 'rebase') + if originalwd is not None: + originalwd = repo[originalwd].node() + scmutil.cleanupnodes(repo, mapping, 'rebase', workingparent=originalwd) def pullrebase(orig, ui, repo, *args, **opts): 'Call rebase after pull if the latter has been invoked with --rebase' diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py --- a/mercurial/scmutil.py +++ b/mercurial/scmutil.py @@ -579,11 +579,11 @@ def __contains__(self, node): return self._revcontains(self._torev(node)) -def cleanupnodes(repo, mapping, operation): +def cleanupnodes(repo, mapping, operation, workingparent=None): """do common cleanups when old nodes are replaced by new nodes - That includes writing obsmarkers or stripping nodes, and moving bookmarks. - (we might also want to move working directory parent in the future) + That includes writing obsmarkers or stripping nodes, moving bookmarks, and + optionally moving working parent. mapping is {oldnode: {'new': [newnode], 'move': newnode}}, where 'new' decide obsolete markers, and 'move' decide bookmark move, which could be @@ -596,6 +596,11 @@ - {oldnode: [newnode]}, equal to {oldnode: {'new': [newnode]}} - {oldnode}, equal to {oldnode: []} + + If workingparent is not None, it's the desired node that needs to update + to. The node may be adjusted using the bookmark movement logic. Uncommitted + changes will be discarded, the caller is responsible for checking the + cleanness of working copy. """ if not mapping: return @@ -606,6 +611,8 @@ elif all('new' not in v and 'move' not in v for v in mapping.values()): mapping = {n: {'new': newnodes} for n, newnodes in mapping.items()} + bmarkwp = '' # an invalid bookmark name to indicate working parent + with repo.transaction('cleanup') as tr: # Move bookmarks bmarks = repo._bookmarks @@ -613,6 +620,8 @@ allnewnodes = [n for v in mapping.values() for n in v.get('new', ())] for oldnode, value in mapping.items(): oldbmarks = repo.nodebookmarks(oldnode) + if workingparent is not None and oldnode == workingparent: + oldbmarks = oldbmarks + [bmarkwp] if not oldbmarks: continue newnode = value.get('move') @@ -641,6 +650,9 @@ allnewnodes, newnode, oldnode) deletenodes = _containsnode(repo, deleterevs) for name in oldbmarks: + if name is bmarkwp: # working parent adjustment + workingparent = newnode + continue bmarkchanges.append((name, newnode)) for b in bookmarks.divergent2delete(repo, deletenodes, name): bmarkchanges.append((b, None)) @@ -648,6 +660,12 @@ if bmarkchanges: bmarks.applychanges(repo, tr, bmarkchanges) + # Working parent movement + if workingparent and [workingparent] != [r.node() + for r in repo[None].parents()]: + from . import hg # avoid import cycle + hg.updaterepo(repo, workingparent, False) + # Obsolete or strip nodes if obsolete.isenabled(repo, obsolete.createmarkersopt): # If a node is already obsoleted, and we want to obsolete it diff --git a/tests/test-rebase-conflicts.t b/tests/test-rebase-conflicts.t --- a/tests/test-rebase-conflicts.t +++ b/tests/test-rebase-conflicts.t @@ -283,7 +283,6 @@ updating the branch cache rebased as 2a7f09cac94c rebase merging completed - update back to initial working directory parent resolving manifests branchmerge: False, force: False, partial: False ancestor: 2a7f09cac94c, local: 2a7f09cac94c+, remote: d79e2059b5c0