Mercurial > hg
comparison mercurial/copies.py @ 26656:3e3d783b0d59
copies: factor out setupctx into _makegetfctx
This reduces the scope of mergecopies a bit
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Wed, 19 Aug 2015 15:17:33 -0500 |
parents | f3c6540f2cd1 |
children | 1ae898cfe857 |
comparison
equal
deleted
inserted
replaced
26655:f3c6540f2cd1 | 26656:3e3d783b0d59 |
---|---|
235 if u2: | 235 if u2: |
236 repo.ui.debug(" unmatched files in other:\n %s\n" | 236 repo.ui.debug(" unmatched files in other:\n %s\n" |
237 % "\n ".join(u2)) | 237 % "\n ".join(u2)) |
238 return u1, u2 | 238 return u1, u2 |
239 | 239 |
240 def _makegetfctx(ctx): | |
241 """return a 'getfctx' function suitable for checkcopies usage | |
242 | |
243 We have to re-setup the function building 'filectx' for each | |
244 'checkcopies' to ensure the linkrev adjustement is properly setup for | |
245 each. Linkrev adjustment is important to avoid bug in rename | |
246 detection. Moreover, having a proper '_ancestrycontext' setup ensures | |
247 the performance impact of this adjustment is kept limited. Without it, | |
248 each file could do a full dag traversal making the time complexity of | |
249 the operation explode (see issue4537). | |
250 | |
251 This function exists here mostly to limit the impact on stable. Feel | |
252 free to refactor on default. | |
253 """ | |
254 rev = ctx.rev() | |
255 repo = ctx._repo | |
256 ac = getattr(ctx, '_ancestrycontext', None) | |
257 if ac is None: | |
258 revs = [rev] | |
259 if rev is None: | |
260 revs = [p.rev() for p in ctx.parents()] | |
261 ac = repo.changelog.ancestors(revs, inclusive=True) | |
262 ctx._ancestrycontext = ac | |
263 def makectx(f, n): | |
264 if len(n) != 20: # in a working context? | |
265 if ctx.rev() is None: | |
266 return ctx.filectx(f) | |
267 return repo[None][f] | |
268 fctx = repo.filectx(f, fileid=n) | |
269 # setup only needed for filectx not create from a changectx | |
270 fctx._ancestrycontext = ac | |
271 fctx._descendantrev = rev | |
272 return fctx | |
273 return util.lrucachefunc(makectx) | |
274 | |
240 def mergecopies(repo, c1, c2, ca): | 275 def mergecopies(repo, c1, c2, ca): |
241 """ | 276 """ |
242 Find moves and copies between context c1 and c2 that are relevant | 277 Find moves and copies between context c1 and c2 that are relevant |
243 for merging. | 278 for merging. |
244 | 279 |
281 | 316 |
282 m1 = c1.manifest() | 317 m1 = c1.manifest() |
283 m2 = c2.manifest() | 318 m2 = c2.manifest() |
284 ma = ca.manifest() | 319 ma = ca.manifest() |
285 | 320 |
286 | |
287 def setupctx(ctx): | |
288 """return a 'getfctx' function suitable for checkcopies usage | |
289 | |
290 We have to re-setup the function building 'filectx' for each | |
291 'checkcopies' to ensure the linkrev adjustement is properly setup for | |
292 each. Linkrev adjustment is important to avoid bug in rename | |
293 detection. Moreover, having a proper '_ancestrycontext' setup ensures | |
294 the performance impact of this adjustment is kept limited. Without it, | |
295 each file could do a full dag traversal making the time complexity of | |
296 the operation explode (see issue4537). | |
297 | |
298 This function exists here mostly to limit the impact on stable. Feel | |
299 free to refactor on default. | |
300 """ | |
301 rev = ctx.rev() | |
302 ac = getattr(ctx, '_ancestrycontext', None) | |
303 repo = ctx._repo | |
304 if ac is None: | |
305 revs = [rev] | |
306 if rev is None: | |
307 revs = [p.rev() for p in ctx.parents()] | |
308 ac = ctx._repo.changelog.ancestors(revs, inclusive=True) | |
309 ctx._ancestrycontext = ac | |
310 def makectx(f, n): | |
311 if len(n) != 20: # in a working context? | |
312 if ctx.rev() is None: | |
313 return ctx.filectx(f) | |
314 return repo[None][f] | |
315 fctx = repo.filectx(f, fileid=n) | |
316 # setup only needed for filectx not create from a changectx | |
317 fctx._ancestrycontext = ac | |
318 fctx._descendantrev = rev | |
319 return fctx | |
320 return util.lrucachefunc(makectx) | |
321 | |
322 copy1, copy2, = {}, {} | 321 copy1, copy2, = {}, {} |
323 movewithdir1, movewithdir2 = {}, {} | 322 movewithdir1, movewithdir2 = {}, {} |
324 fullcopy1, fullcopy2 = {}, {} | 323 fullcopy1, fullcopy2 = {}, {} |
325 diverge = {} | 324 diverge = {} |
326 | 325 |
327 addedinm1 = m1.filesnotin(ma) | 326 addedinm1 = m1.filesnotin(ma) |
328 addedinm2 = m2.filesnotin(ma) | 327 addedinm2 = m2.filesnotin(ma) |
329 u1, u2 = _computenonoverlap(repo, c1, c2, addedinm1, addedinm2) | 328 u1, u2 = _computenonoverlap(repo, c1, c2, addedinm1, addedinm2) |
330 | 329 |
331 for f in u1: | 330 for f in u1: |
332 getfctx = setupctx(c1) | 331 getfctx = _makegetfctx(c1) |
333 checkcopies(getfctx, f, m1, m2, ca, limit, diverge, copy1, fullcopy1) | 332 checkcopies(getfctx, f, m1, m2, ca, limit, diverge, copy1, fullcopy1) |
334 | 333 |
335 for f in u2: | 334 for f in u2: |
336 getfctx = setupctx(c2) | 335 getfctx = _makegetfctx(c2) |
337 checkcopies(getfctx, f, m2, m1, ca, limit, diverge, copy2, fullcopy2) | 336 checkcopies(getfctx, f, m2, m1, ca, limit, diverge, copy2, fullcopy2) |
338 | 337 |
339 copy = dict(copy1.items() + copy2.items()) | 338 copy = dict(copy1.items() + copy2.items()) |
340 movewithdir = dict(movewithdir1.items() + movewithdir2.items()) | 339 movewithdir = dict(movewithdir1.items() + movewithdir2.items()) |
341 fullcopy = dict(fullcopy1.items() + fullcopy2.items()) | 340 fullcopy = dict(fullcopy1.items() + fullcopy2.items()) |
358 if bothnew: | 357 if bothnew: |
359 repo.ui.debug(" unmatched files new in both:\n %s\n" | 358 repo.ui.debug(" unmatched files new in both:\n %s\n" |
360 % "\n ".join(bothnew)) | 359 % "\n ".join(bothnew)) |
361 bothdiverge, _copy, _fullcopy = {}, {}, {} | 360 bothdiverge, _copy, _fullcopy = {}, {}, {} |
362 for f in bothnew: | 361 for f in bothnew: |
363 getfctx = setupctx(c1) | 362 getfctx = _makegetfctx(c1) |
364 checkcopies(getfctx, f, m1, m2, ca, limit, bothdiverge, | 363 checkcopies(getfctx, f, m1, m2, ca, limit, bothdiverge, |
365 _copy, _fullcopy) | 364 _copy, _fullcopy) |
366 getfctx = setupctx(c2) | 365 getfctx = _makegetfctx(c2) |
367 checkcopies(getfctx, f, m2, m1, ca, limit, bothdiverge, | 366 checkcopies(getfctx, f, m2, m1, ca, limit, bothdiverge, |
368 _copy, _fullcopy) | 367 _copy, _fullcopy) |
369 for of, fl in bothdiverge.items(): | 368 for of, fl in bothdiverge.items(): |
370 if len(fl) == 2 and fl[0] == fl[1]: | 369 if len(fl) == 2 and fl[0] == fl[1]: |
371 copy[fl[0]] = of # not actually divergent, just matching renames | 370 copy[fl[0]] = of # not actually divergent, just matching renames |