comparison hgext/histedit.py @ 17407:31c123a2f273

histedit: factored out diff/patch logic This patch is the first step towards a refactoring of the histedit extension to use underlying graft machinery instead of diff/patch as discussed in issue3527. Replacing diff/patch with graft is necessary to fix, for example, issue3582.
author Leah Xue <leahxue@fb.com>
date Tue, 21 Aug 2012 16:06:34 -0700
parents 96189d60d810
children 8e1fa8a32f2b
comparison
equal deleted inserted replaced
17406:fc14953e8e34 17407:31c123a2f273
173 # d, drop = remove commit from history 173 # d, drop = remove commit from history
174 # m, mess = edit message without changing commit content 174 # m, mess = edit message without changing commit content
175 # 175 #
176 """) 176 """)
177 177
178 def foldchanges(ui, repo, node1, node2, opts):
179 """Produce a new changeset that represents the diff from node1 to node2."""
180 try:
181 fd, patchfile = tempfile.mkstemp(prefix='hg-histedit-')
182 fp = os.fdopen(fd, 'w')
183 diffopts = patch.diffopts(ui, opts)
184 diffopts.git = True
185 diffopts.ignorews = False
186 diffopts.ignorewsamount = False
187 diffopts.ignoreblanklines = False
188 gen = patch.diff(repo, node1, node2, opts=diffopts)
189 for chunk in gen:
190 fp.write(chunk)
191 fp.close()
192 files = set()
193 patch.patch(ui, repo, patchfile, files=files, eolmode=None)
194 finally:
195 os.unlink(patchfile)
196 return files
197
178 def between(repo, old, new, keep): 198 def between(repo, old, new, keep):
179 revs = [old] 199 revs = [old]
180 current = old 200 current = old
181 while current != new: 201 while current != new:
182 ctx = repo[current] 202 ctx = repo[current]
198 oldctx = repo[ha] 218 oldctx = repo[ha]
199 if oldctx.parents()[0] == ctx: 219 if oldctx.parents()[0] == ctx:
200 ui.debug('node %s unchanged\n' % ha) 220 ui.debug('node %s unchanged\n' % ha)
201 return oldctx, [], [], [] 221 return oldctx, [], [], []
202 hg.update(repo, ctx.node()) 222 hg.update(repo, ctx.node())
203 fd, patchfile = tempfile.mkstemp(prefix='hg-histedit-')
204 fp = os.fdopen(fd, 'w')
205 diffopts = patch.diffopts(ui, opts)
206 diffopts.git = True
207 diffopts.ignorews = False
208 diffopts.ignorewsamount = False
209 diffopts.ignoreblanklines = False
210 gen = patch.diff(repo, oldctx.parents()[0].node(), ha, opts=diffopts)
211 for chunk in gen:
212 fp.write(chunk)
213 fp.close()
214 try: 223 try:
215 files = set() 224 files = foldchanges(ui, repo, oldctx.p1().node() , ha, opts)
216 try: 225 if not files:
217 patch.patch(ui, repo, patchfile, files=files, eolmode=None) 226 ui.warn(_('%s: empty changeset')
218 if not files: 227 % node.hex(ha))
219 ui.warn(_('%s: empty changeset') 228 return ctx, [], [], []
220 % node.hex(ha))
221 return ctx, [], [], []
222 finally:
223 os.unlink(patchfile)
224 except Exception: 229 except Exception:
225 raise util.Abort(_('Fix up the change and run ' 230 raise util.Abort(_('Fix up the change and run '
226 'hg histedit --continue')) 231 'hg histedit --continue'))
227 n = repo.commit(text=oldctx.description(), user=oldctx.user(), 232 n = repo.commit(text=oldctx.description(), user=oldctx.user(),
228 date=oldctx.date(), extra=oldctx.extra()) 233 date=oldctx.date(), extra=oldctx.extra())
230 235
231 236
232 def edit(ui, repo, ctx, ha, opts): 237 def edit(ui, repo, ctx, ha, opts):
233 oldctx = repo[ha] 238 oldctx = repo[ha]
234 hg.update(repo, ctx.node()) 239 hg.update(repo, ctx.node())
235 fd, patchfile = tempfile.mkstemp(prefix='hg-histedit-')
236 fp = os.fdopen(fd, 'w')
237 diffopts = patch.diffopts(ui, opts)
238 diffopts.git = True
239 diffopts.ignorews = False
240 diffopts.ignorewsamount = False
241 diffopts.ignoreblanklines = False
242 gen = patch.diff(repo, oldctx.parents()[0].node(), ha, opts=diffopts)
243 for chunk in gen:
244 fp.write(chunk)
245 fp.close()
246 try: 240 try:
247 files = set() 241 files = foldchanges(ui, repo, oldctx.p1().node() , ha, opts)
248 try:
249 patch.patch(ui, repo, patchfile, files=files, eolmode=None)
250 finally:
251 os.unlink(patchfile)
252 except Exception: 242 except Exception:
253 pass 243 pass
254 raise util.Abort(_('Make changes as needed, you may commit or record as ' 244 raise util.Abort(_('Make changes as needed, you may commit or record as '
255 'needed now.\nWhen you are finished, run hg' 245 'needed now.\nWhen you are finished, run hg'
256 ' histedit --continue to resume.')) 246 ' histedit --continue to resume.'))
257 247
258 def fold(ui, repo, ctx, ha, opts): 248 def fold(ui, repo, ctx, ha, opts):
259 oldctx = repo[ha] 249 oldctx = repo[ha]
260 hg.update(repo, ctx.node()) 250 hg.update(repo, ctx.node())
261 fd, patchfile = tempfile.mkstemp(prefix='hg-histedit-')
262 fp = os.fdopen(fd, 'w')
263 diffopts = patch.diffopts(ui, opts)
264 diffopts.git = True
265 diffopts.ignorews = False
266 diffopts.ignorewsamount = False
267 diffopts.ignoreblanklines = False
268 gen = patch.diff(repo, oldctx.parents()[0].node(), ha, opts=diffopts)
269 for chunk in gen:
270 fp.write(chunk)
271 fp.close()
272 try: 251 try:
273 files = set() 252 files = foldchanges(ui, repo, oldctx.p1().node() , ha, opts)
274 try: 253 if not files:
275 patch.patch(ui, repo, patchfile, files=files, eolmode=None) 254 ui.warn(_('%s: empty changeset')
276 if not files: 255 % node.hex(ha))
277 ui.warn(_('%s: empty changeset') 256 return ctx, [], [], []
278 % node.hex(ha))
279 return ctx, [], [], []
280 finally:
281 os.unlink(patchfile)
282 except Exception: 257 except Exception:
283 raise util.Abort(_('Fix up the change and run ' 258 raise util.Abort(_('Fix up the change and run '
284 'hg histedit --continue')) 259 'hg histedit --continue'))
285 n = repo.commit(text='fold-temp-revision %s' % ha, user=oldctx.user(), 260 n = repo.commit(text='fold-temp-revision %s' % ha, user=oldctx.user(),
286 date=oldctx.date(), extra=oldctx.extra()) 261 date=oldctx.date(), extra=oldctx.extra())
287 return finishfold(ui, repo, ctx, oldctx, n, opts, []) 262 return finishfold(ui, repo, ctx, oldctx, n, opts, [])
288 263
289 def finishfold(ui, repo, ctx, oldctx, newnode, opts, internalchanges): 264 def finishfold(ui, repo, ctx, oldctx, newnode, opts, internalchanges):
290 parent = ctx.parents()[0].node() 265 parent = ctx.parents()[0].node()
291 hg.update(repo, parent) 266 hg.update(repo, parent)
292 fd, patchfile = tempfile.mkstemp(prefix='hg-histedit-') 267 files = foldchanges(ui, repo, parent, newnode, opts)
293 fp = os.fdopen(fd, 'w')
294 diffopts = patch.diffopts(ui, opts)
295 diffopts.git = True
296 diffopts.ignorews = False
297 diffopts.ignorewsamount = False
298 diffopts.ignoreblanklines = False
299 gen = patch.diff(repo, parent, newnode, opts=diffopts)
300 for chunk in gen:
301 fp.write(chunk)
302 fp.close()
303 files = set()
304 try:
305 patch.patch(ui, repo, patchfile, files=files, eolmode=None)
306 finally:
307 os.unlink(patchfile)
308 newmessage = '\n***\n'.join( 268 newmessage = '\n***\n'.join(
309 [ctx.description()] + 269 [ctx.description()] +
310 [repo[r].description() for r in internalchanges] + 270 [repo[r].description() for r in internalchanges] +
311 [oldctx.description()]) + '\n' 271 [oldctx.description()]) + '\n'
312 # If the changesets are from the same author, keep it. 272 # If the changesets are from the same author, keep it.
324 284
325 285
326 def message(ui, repo, ctx, ha, opts): 286 def message(ui, repo, ctx, ha, opts):
327 oldctx = repo[ha] 287 oldctx = repo[ha]
328 hg.update(repo, ctx.node()) 288 hg.update(repo, ctx.node())
329 fd, patchfile = tempfile.mkstemp(prefix='hg-histedit-')
330 fp = os.fdopen(fd, 'w')
331 diffopts = patch.diffopts(ui, opts)
332 diffopts.git = True
333 diffopts.ignorews = False
334 diffopts.ignorewsamount = False
335 diffopts.ignoreblanklines = False
336 gen = patch.diff(repo, oldctx.parents()[0].node(), ha, opts=diffopts)
337 for chunk in gen:
338 fp.write(chunk)
339 fp.close()
340 try: 289 try:
341 files = set() 290 files = foldchanges(ui, repo, oldctx.p1().node() , ha, opts)
342 try:
343 patch.patch(ui, repo, patchfile, files=files, eolmode=None)
344 finally:
345 os.unlink(patchfile)
346 except Exception: 291 except Exception:
347 raise util.Abort(_('Fix up the change and run ' 292 raise util.Abort(_('Fix up the change and run '
348 'hg histedit --continue')) 293 'hg histedit --continue'))
349 message = oldctx.description() + '\n' 294 message = oldctx.description() + '\n'
350 message = ui.edit(message, ui.username()) 295 message = ui.edit(message, ui.username())