comparison hgext/rebase.py @ 7278:45495d784ad6

rebase: avoid redundant merges (issue1301)
author Stefano Tortarolo <stefano.tortarolo@gmail.com>
date Tue, 16 Sep 2008 17:51:14 +0200
parents 292fb2ad2846
children ddab62b2fec4
comparison
equal deleted inserted replaced
7277:3e000e2bf5f6 7278:45495d784ad6
11 11
12 For more information: 12 For more information:
13 http://www.selenic.com/mercurial/wiki/index.cgi/RebaseProject 13 http://www.selenic.com/mercurial/wiki/index.cgi/RebaseProject
14 ''' 14 '''
15 15
16 from mercurial import util, repair, merge, cmdutil, dispatch, commands, extensions 16 from mercurial import util, repair, merge, cmdutil, dispatch, commands
17 from mercurial import extensions, ancestor
17 from mercurial.commands import templateopts 18 from mercurial.commands import templateopts
18 from mercurial.node import nullrev 19 from mercurial.node import nullrev
19 from mercurial.i18n import _ 20 from mercurial.i18n import _
20 import os, errno 21 import os, errno
22
23 def rebasemerge(repo, rev, first=False):
24 'return the correct ancestor'
25 oldancestor = ancestor.ancestor
26
27 def newancestor(a, b, pfunc):
28 ancestor.ancestor = oldancestor
29 anc = ancestor.ancestor(a, b, pfunc)
30 if b == rev:
31 return repo[rev].parents()[0].rev()
32 return ancestor.ancestor(a, b, pfunc)
33
34 if not first:
35 ancestor.ancestor = newancestor
36 else:
37 repo.ui.debug(_("First revision, do not change ancestor\n"))
38 stats = merge.update(repo, rev, True, True, False)
39 return stats
21 40
22 def rebase(ui, repo, **opts): 41 def rebase(ui, repo, **opts):
23 """move changeset (and descendants) to a different branch 42 """move changeset (and descendants) to a different branch
24 43
25 Rebase uses repeated merging to graft changesets from one part of history 44 Rebase uses repeated merging to graft changesets from one part of history
114 133
115 def concludenode(repo, rev, p1, p2, state, collapse, last=False, skipped={}): 134 def concludenode(repo, rev, p1, p2, state, collapse, last=False, skipped={}):
116 """Skip commit if collapsing has been required and rev is not the last 135 """Skip commit if collapsing has been required and rev is not the last
117 revision, commit otherwise 136 revision, commit otherwise
118 """ 137 """
138 repo.ui.debug(_(" set parents\n"))
139 if collapse and not last:
140 repo.dirstate.setparents(repo[p1].node())
141 return None
142
119 repo.dirstate.setparents(repo[p1].node(), repo[p2].node()) 143 repo.dirstate.setparents(repo[p1].node(), repo[p2].node())
120
121 if collapse and not last:
122 return None
123 144
124 # Commit, record the old nodeid 145 # Commit, record the old nodeid
125 m, a, r = repo.status()[:3] 146 m, a, r = repo.status()[:3]
126 newrev = nullrev 147 newrev = nullrev
127 try: 148 try:
145 repo.dirstate.invalidate() 166 repo.dirstate.invalidate()
146 raise 167 raise
147 168
148 def rebasenode(repo, rev, target, state, skipped, targetancestors, collapse): 169 def rebasenode(repo, rev, target, state, skipped, targetancestors, collapse):
149 'Rebase a single revision' 170 'Rebase a single revision'
150 repo.ui.debug(_("rebasing %d:%s\n") % (rev, repo[rev].node())) 171 repo.ui.debug(_("rebasing %d:%s\n") % (rev, repo[rev]))
151 172
152 p1, p2 = defineparents(repo, rev, target, state, targetancestors) 173 p1, p2 = defineparents(repo, rev, target, state, targetancestors)
153 174
175 repo.ui.debug(_(" future parents are %d and %d\n") % (repo[p1].rev(),
176 repo[p2].rev()))
177
154 # Merge phase 178 # Merge phase
155 if len(repo.parents()) != 2: 179 if len(repo.parents()) != 2:
156 # Update to target and merge it with local 180 # Update to target and merge it with local
157 merge.update(repo, p1, False, True, False) 181 if repo['.'].rev() != repo[p1].rev():
182 repo.ui.debug(_(" update to %d:%s\n") % (repo[p1].rev(), repo[p1]))
183 merge.update(repo, p1, False, True, False)
184 else:
185 repo.ui.debug(_(" already in target\n"))
158 repo.dirstate.write() 186 repo.dirstate.write()
159 stats = merge.update(repo, rev, True, False, False) 187 repo.ui.debug(_(" merge against %d:%s\n") % (repo[rev].rev(), repo[rev]))
188 first = repo[rev].rev() == repo[min(state)].rev()
189 stats = rebasemerge(repo, rev, first)
160 190
161 if stats[3] > 0: 191 if stats[3] > 0:
162 raise util.Abort(_('fix unresolved conflicts with hg resolve then ' 192 raise util.Abort(_('fix unresolved conflicts with hg resolve then '
163 'run hg rebase --continue')) 193 'run hg rebase --continue'))
164 else: # we have an interrupted rebase 194 else: # we have an interrupted rebase