266 revstofix = getrevstofix(ui, repo, opts) |
266 revstofix = getrevstofix(ui, repo, opts) |
267 basectxs = getbasectxs(repo, opts, revstofix) |
267 basectxs = getbasectxs(repo, opts, revstofix) |
268 workqueue, numitems = getworkqueue( |
268 workqueue, numitems = getworkqueue( |
269 ui, repo, pats, opts, revstofix, basectxs |
269 ui, repo, pats, opts, revstofix, basectxs |
270 ) |
270 ) |
|
271 basepaths = getbasepaths(repo, opts, workqueue, basectxs) |
271 fixers = getfixers(ui) |
272 fixers = getfixers(ui) |
272 |
273 |
273 # There are no data dependencies between the workers fixing each file |
274 # There are no data dependencies between the workers fixing each file |
274 # revision, so we can use all available parallelism. |
275 # revision, so we can use all available parallelism. |
275 def getfixes(items): |
276 def getfixes(items): |
276 for rev, path in items: |
277 for rev, path in items: |
277 ctx = repo[rev] |
278 ctx = repo[rev] |
278 olddata = ctx[path].data() |
279 olddata = ctx[path].data() |
279 metadata, newdata = fixfile( |
280 metadata, newdata = fixfile( |
280 ui, repo, opts, fixers, ctx, path, basectxs[rev] |
281 ui, repo, opts, fixers, ctx, path, basepaths, basectxs[rev] |
281 ) |
282 ) |
282 # Don't waste memory/time passing unchanged content back, but |
283 # Don't waste memory/time passing unchanged content back, but |
283 # produce one result per item either way. |
284 # produce one result per item either way. |
284 yield ( |
285 yield ( |
285 rev, |
286 rev, |
471 ) |
472 ) |
472 ) |
473 ) |
473 return files |
474 return files |
474 |
475 |
475 |
476 |
476 def lineranges(opts, path, basectxs, fixctx, content2): |
477 def lineranges(opts, path, basepaths, basectxs, fixctx, content2): |
477 """Returns the set of line ranges that should be fixed in a file |
478 """Returns the set of line ranges that should be fixed in a file |
478 |
479 |
479 Of the form [(10, 20), (30, 40)]. |
480 Of the form [(10, 20), (30, 40)]. |
480 |
481 |
481 This depends on the given base contexts; we must consider lines that have |
482 This depends on the given base contexts; we must consider lines that have |
490 # idea of how many lines are in the file, instead of reimplementing it. |
491 # idea of how many lines are in the file, instead of reimplementing it. |
491 return difflineranges(b'', content2) |
492 return difflineranges(b'', content2) |
492 |
493 |
493 rangeslist = [] |
494 rangeslist = [] |
494 for basectx in basectxs: |
495 for basectx in basectxs: |
495 basepath = copies.pathcopies(basectx, fixctx).get(path, path) |
496 basepath = basepaths.get((basectx.rev(), fixctx.rev(), path), path) |
|
497 |
496 if basepath in basectx: |
498 if basepath in basectx: |
497 content1 = basectx[basepath].data() |
499 content1 = basectx[basepath].data() |
498 else: |
500 else: |
499 content1 = b'' |
501 content1 = b'' |
500 rangeslist.extend(difflineranges(content1, content2)) |
502 rangeslist.extend(difflineranges(content1, content2)) |
501 return unionranges(rangeslist) |
503 return unionranges(rangeslist) |
|
504 |
|
505 |
|
506 def getbasepaths(repo, opts, workqueue, basectxs): |
|
507 if opts.get(b'whole'): |
|
508 # Base paths will never be fetched for line range determination. |
|
509 return {} |
|
510 |
|
511 basepaths = {} |
|
512 for rev, path in workqueue: |
|
513 fixctx = repo[rev] |
|
514 for basectx in basectxs[rev]: |
|
515 basepath = copies.pathcopies(basectx, fixctx).get(path, path) |
|
516 if basepath in basectx: |
|
517 basepaths[(basectx.rev(), fixctx.rev(), path)] = basepath |
|
518 return basepaths |
502 |
519 |
503 |
520 |
504 def unionranges(rangeslist): |
521 def unionranges(rangeslist): |
505 """Return the union of some closed intervals |
522 """Return the union of some closed intervals |
506 |
523 |
611 else: |
628 else: |
612 basectxs[rev].add(pctx) |
629 basectxs[rev].add(pctx) |
613 return basectxs |
630 return basectxs |
614 |
631 |
615 |
632 |
616 def fixfile(ui, repo, opts, fixers, fixctx, path, basectxs): |
633 def fixfile(ui, repo, opts, fixers, fixctx, path, basepaths, basectxs): |
617 """Run any configured fixers that should affect the file in this context |
634 """Run any configured fixers that should affect the file in this context |
618 |
635 |
619 Returns the file content that results from applying the fixers in some order |
636 Returns the file content that results from applying the fixers in some order |
620 starting with the file's content in the fixctx. Fixers that support line |
637 starting with the file's content in the fixctx. Fixers that support line |
621 ranges will affect lines that have changed relative to any of the basectxs |
638 ranges will affect lines that have changed relative to any of the basectxs |
627 """ |
644 """ |
628 metadata = {} |
645 metadata = {} |
629 newdata = fixctx[path].data() |
646 newdata = fixctx[path].data() |
630 for fixername, fixer in pycompat.iteritems(fixers): |
647 for fixername, fixer in pycompat.iteritems(fixers): |
631 if fixer.affects(opts, fixctx, path): |
648 if fixer.affects(opts, fixctx, path): |
632 ranges = lineranges(opts, path, basectxs, fixctx, newdata) |
649 ranges = lineranges( |
|
650 opts, path, basepaths, basectxs, fixctx, newdata |
|
651 ) |
633 command = fixer.command(ui, path, ranges) |
652 command = fixer.command(ui, path, ranges) |
634 if command is None: |
653 if command is None: |
635 continue |
654 continue |
636 ui.debug(b'subprocess: %s\n' % (command,)) |
655 ui.debug(b'subprocess: %s\n' % (command,)) |
637 proc = subprocess.Popen( |
656 proc = subprocess.Popen( |