Mercurial > hg
comparison mercurial/copies.py @ 43077:687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Done with
python3.7 contrib/byteify-strings.py -i $(hg files 'set:mercurial/**.py - mercurial/thirdparty/** + hgext/**.py - hgext/fsmonitor/pywatchman/** - mercurial/__init__.py')
black -l 80 -t py33 -S $(hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**" - hgext/fsmonitor/pywatchman/**')
# skip-blame mass-reformatting only
Differential Revision: https://phab.mercurial-scm.org/D6972
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:48:39 -0400 |
parents | 2372284d9457 |
children | d783f945a701 |
comparison
equal
deleted
inserted
replaced
43076:2372284d9457 | 43077:687b865b95ad |
---|---|
168 | 168 |
169 def _dirstatecopies(repo, match=None): | 169 def _dirstatecopies(repo, match=None): |
170 ds = repo.dirstate | 170 ds = repo.dirstate |
171 c = ds.copies().copy() | 171 c = ds.copies().copy() |
172 for k in list(c): | 172 for k in list(c): |
173 if ds[k] not in 'anm' or (match and not match(k)): | 173 if ds[k] not in b'anm' or (match and not match(k)): |
174 del c[k] | 174 del c[k] |
175 return c | 175 return c |
176 | 176 |
177 | 177 |
178 def _computeforwardmissing(a, b, match=None): | 178 def _computeforwardmissing(a, b, match=None): |
185 return mb.filesnotin(ma, match=match) | 185 return mb.filesnotin(ma, match=match) |
186 | 186 |
187 | 187 |
188 def usechangesetcentricalgo(repo): | 188 def usechangesetcentricalgo(repo): |
189 """Checks if we should use changeset-centric copy algorithms""" | 189 """Checks if we should use changeset-centric copy algorithms""" |
190 readfrom = repo.ui.config('experimental', 'copies.read-from') | 190 readfrom = repo.ui.config(b'experimental', b'copies.read-from') |
191 changesetsource = ('changeset-only', 'compatibility') | 191 changesetsource = (b'changeset-only', b'compatibility') |
192 return readfrom in changesetsource | 192 return readfrom in changesetsource |
193 | 193 |
194 | 194 |
195 def _committedforwardcopies(a, b, base, match): | 195 def _committedforwardcopies(a, b, base, match): |
196 """Like _forwardcopies(), but b.rev() cannot be None (working copy)""" | 196 """Like _forwardcopies(), but b.rev() cannot be None (working copy)""" |
199 repo = a._repo | 199 repo = a._repo |
200 | 200 |
201 if usechangesetcentricalgo(repo): | 201 if usechangesetcentricalgo(repo): |
202 return _changesetforwardcopies(a, b, match) | 202 return _changesetforwardcopies(a, b, match) |
203 | 203 |
204 debug = repo.ui.debugflag and repo.ui.configbool('devel', 'debug.copies') | 204 debug = repo.ui.debugflag and repo.ui.configbool(b'devel', b'debug.copies') |
205 dbg = repo.ui.debug | 205 dbg = repo.ui.debug |
206 if debug: | 206 if debug: |
207 dbg('debug.copies: looking into rename from %s to %s\n' % (a, b)) | 207 dbg(b'debug.copies: looking into rename from %s to %s\n' % (a, b)) |
208 limit = _findlimit(repo, a, b) | 208 limit = _findlimit(repo, a, b) |
209 if debug: | 209 if debug: |
210 dbg('debug.copies: search limit: %d\n' % limit) | 210 dbg(b'debug.copies: search limit: %d\n' % limit) |
211 am = a.manifest() | 211 am = a.manifest() |
212 basemf = None if base is None else base.manifest() | 212 basemf = None if base is None else base.manifest() |
213 | 213 |
214 # find where new files came from | 214 # find where new files came from |
215 # we currently don't try to find where old files went, too expensive | 215 # we currently don't try to find where old files went, too expensive |
229 missing = _computeforwardmissing(a, b, match=forwardmissingmatch) | 229 missing = _computeforwardmissing(a, b, match=forwardmissingmatch) |
230 | 230 |
231 ancestrycontext = a._repo.changelog.ancestors([b.rev()], inclusive=True) | 231 ancestrycontext = a._repo.changelog.ancestors([b.rev()], inclusive=True) |
232 | 232 |
233 if debug: | 233 if debug: |
234 dbg('debug.copies: missing files to search: %d\n' % len(missing)) | 234 dbg(b'debug.copies: missing files to search: %d\n' % len(missing)) |
235 | 235 |
236 for f in sorted(missing): | 236 for f in sorted(missing): |
237 if debug: | 237 if debug: |
238 dbg('debug.copies: tracing file: %s\n' % f) | 238 dbg(b'debug.copies: tracing file: %s\n' % f) |
239 fctx = b[f] | 239 fctx = b[f] |
240 fctx._ancestrycontext = ancestrycontext | 240 fctx._ancestrycontext = ancestrycontext |
241 | 241 |
242 if debug: | 242 if debug: |
243 start = util.timer() | 243 start = util.timer() |
244 opath = _tracefile(fctx, am, basemf, limit) | 244 opath = _tracefile(fctx, am, basemf, limit) |
245 if opath: | 245 if opath: |
246 if debug: | 246 if debug: |
247 dbg('debug.copies: rename of: %s\n' % opath) | 247 dbg(b'debug.copies: rename of: %s\n' % opath) |
248 cm[f] = opath | 248 cm[f] = opath |
249 if debug: | 249 if debug: |
250 dbg( | 250 dbg( |
251 'debug.copies: time: %f seconds\n' | 251 b'debug.copies: time: %f seconds\n' |
252 % (util.timer() - start) | 252 % (util.timer() - start) |
253 ) | 253 ) |
254 return cm | 254 return cm |
255 | 255 |
256 | 256 |
340 copies = _committedforwardcopies(a, b, base, match) | 340 copies = _committedforwardcopies(a, b, base, match) |
341 return copies | 341 return copies |
342 | 342 |
343 | 343 |
344 def _backwardrenames(a, b, match): | 344 def _backwardrenames(a, b, match): |
345 if a._repo.ui.config('experimental', 'copytrace') == 'off': | 345 if a._repo.ui.config(b'experimental', b'copytrace') == b'off': |
346 return {} | 346 return {} |
347 | 347 |
348 # Even though we're not taking copies into account, 1:n rename situations | 348 # Even though we're not taking copies into account, 1:n rename situations |
349 # can still exist (e.g. hg cp a b; hg mv a c). In those cases we | 349 # can still exist (e.g. hg cp a b; hg mv a c). In those cases we |
350 # arbitrarily pick one of the renames. | 350 # arbitrarily pick one of the renames. |
364 | 364 |
365 | 365 |
366 def pathcopies(x, y, match=None): | 366 def pathcopies(x, y, match=None): |
367 """find {dst@y: src@x} copy mapping for directed compare""" | 367 """find {dst@y: src@x} copy mapping for directed compare""" |
368 repo = x._repo | 368 repo = x._repo |
369 debug = repo.ui.debugflag and repo.ui.configbool('devel', 'debug.copies') | 369 debug = repo.ui.debugflag and repo.ui.configbool(b'devel', b'debug.copies') |
370 if debug: | 370 if debug: |
371 repo.ui.debug('debug.copies: searching copies from %s to %s\n' % (x, y)) | 371 repo.ui.debug( |
372 b'debug.copies: searching copies from %s to %s\n' % (x, y) | |
373 ) | |
372 if x == y or not x or not y: | 374 if x == y or not x or not y: |
373 return {} | 375 return {} |
374 a = y.ancestor(x) | 376 a = y.ancestor(x) |
375 if a == x: | 377 if a == x: |
376 if debug: | 378 if debug: |
377 repo.ui.debug('debug.copies: search mode: forward\n') | 379 repo.ui.debug(b'debug.copies: search mode: forward\n') |
378 if y.rev() is None and x == y.p1(): | 380 if y.rev() is None and x == y.p1(): |
379 # short-circuit to avoid issues with merge states | 381 # short-circuit to avoid issues with merge states |
380 return _dirstatecopies(repo, match) | 382 return _dirstatecopies(repo, match) |
381 copies = _forwardcopies(x, y, match=match) | 383 copies = _forwardcopies(x, y, match=match) |
382 elif a == y: | 384 elif a == y: |
383 if debug: | 385 if debug: |
384 repo.ui.debug('debug.copies: search mode: backward\n') | 386 repo.ui.debug(b'debug.copies: search mode: backward\n') |
385 copies = _backwardrenames(x, y, match=match) | 387 copies = _backwardrenames(x, y, match=match) |
386 else: | 388 else: |
387 if debug: | 389 if debug: |
388 repo.ui.debug('debug.copies: search mode: combined\n') | 390 repo.ui.debug(b'debug.copies: search mode: combined\n') |
389 base = None | 391 base = None |
390 if a.rev() != node.nullrev: | 392 if a.rev() != node.nullrev: |
391 base = x | 393 base = x |
392 copies = _chain( | 394 copies = _chain( |
393 _backwardrenames(x, a, match=match), | 395 _backwardrenames(x, a, match=match), |
451 | 453 |
452 # avoid silly behavior for parent -> working dir | 454 # avoid silly behavior for parent -> working dir |
453 if c2.node() is None and c1.node() == repo.dirstate.p1(): | 455 if c2.node() is None and c1.node() == repo.dirstate.p1(): |
454 return _dirstatecopies(repo, narrowmatch), {}, {}, {}, {} | 456 return _dirstatecopies(repo, narrowmatch), {}, {}, {}, {} |
455 | 457 |
456 copytracing = repo.ui.config('experimental', 'copytrace') | 458 copytracing = repo.ui.config(b'experimental', b'copytrace') |
457 if stringutil.parsebool(copytracing) is False: | 459 if stringutil.parsebool(copytracing) is False: |
458 # stringutil.parsebool() returns None when it is unable to parse the | 460 # stringutil.parsebool() returns None when it is unable to parse the |
459 # value, so we should rely on making sure copytracing is on such cases | 461 # value, so we should rely on making sure copytracing is on such cases |
460 return {}, {}, {}, {}, {} | 462 return {}, {}, {}, {}, {} |
461 | 463 |
464 return _fullcopytracing(repo, c1, c2, base) | 466 return _fullcopytracing(repo, c1, c2, base) |
465 | 467 |
466 # Copy trace disabling is explicitly below the node == p1 logic above | 468 # Copy trace disabling is explicitly below the node == p1 logic above |
467 # because the logic above is required for a simple copy to be kept across a | 469 # because the logic above is required for a simple copy to be kept across a |
468 # rebase. | 470 # rebase. |
469 if copytracing == 'heuristics': | 471 if copytracing == b'heuristics': |
470 # Do full copytracing if only non-public revisions are involved as | 472 # Do full copytracing if only non-public revisions are involved as |
471 # that will be fast enough and will also cover the copies which could | 473 # that will be fast enough and will also cover the copies which could |
472 # be missed by heuristics | 474 # be missed by heuristics |
473 if _isfullcopytraceable(repo, c1, base): | 475 if _isfullcopytraceable(repo, c1, base): |
474 return _fullcopytracing(repo, c1, c2, base) | 476 return _fullcopytracing(repo, c1, c2, base) |
488 """ | 490 """ |
489 if c1.rev() is None: | 491 if c1.rev() is None: |
490 c1 = c1.p1() | 492 c1 = c1.p1() |
491 if c1.mutable() and base.mutable(): | 493 if c1.mutable() and base.mutable(): |
492 sourcecommitlimit = repo.ui.configint( | 494 sourcecommitlimit = repo.ui.configint( |
493 'experimental', 'copytrace.sourcecommitlimit' | 495 b'experimental', b'copytrace.sourcecommitlimit' |
494 ) | 496 ) |
495 commits = len(repo.revs('%d::%d', base.rev(), c1.rev())) | 497 commits = len(repo.revs(b'%d::%d', base.rev(), c1.rev())) |
496 return commits < sourcecommitlimit | 498 return commits < sourcecommitlimit |
497 return False | 499 return False |
498 | 500 |
499 | 501 |
500 def _checksinglesidecopies( | 502 def _checksinglesidecopies( |
590 addedinm1 = m1.filesnotin(mb, repo.narrowmatch()) | 592 addedinm1 = m1.filesnotin(mb, repo.narrowmatch()) |
591 addedinm2 = m2.filesnotin(mb, repo.narrowmatch()) | 593 addedinm2 = m2.filesnotin(mb, repo.narrowmatch()) |
592 u1 = sorted(addedinm1 - addedinm2) | 594 u1 = sorted(addedinm1 - addedinm2) |
593 u2 = sorted(addedinm2 - addedinm1) | 595 u2 = sorted(addedinm2 - addedinm1) |
594 | 596 |
595 header = " unmatched files in %s" | 597 header = b" unmatched files in %s" |
596 if u1: | 598 if u1: |
597 repo.ui.debug("%s:\n %s\n" % (header % 'local', "\n ".join(u1))) | 599 repo.ui.debug(b"%s:\n %s\n" % (header % b'local', b"\n ".join(u1))) |
598 if u2: | 600 if u2: |
599 repo.ui.debug("%s:\n %s\n" % (header % 'other', "\n ".join(u2))) | 601 repo.ui.debug(b"%s:\n %s\n" % (header % b'other', b"\n ".join(u2))) |
600 | 602 |
601 fullcopy = copies1.copy() | 603 fullcopy = copies1.copy() |
602 fullcopy.update(copies2) | 604 fullcopy.update(copies2) |
603 if not fullcopy: | 605 if not fullcopy: |
604 return copy, {}, diverge, renamedelete, {} | 606 return copy, {}, diverge, renamedelete, {} |
605 | 607 |
606 if repo.ui.debugflag: | 608 if repo.ui.debugflag: |
607 repo.ui.debug( | 609 repo.ui.debug( |
608 " all copies found (* = to merge, ! = divergent, " | 610 b" all copies found (* = to merge, ! = divergent, " |
609 "% = renamed and deleted):\n" | 611 b"% = renamed and deleted):\n" |
610 ) | 612 ) |
611 for f in sorted(fullcopy): | 613 for f in sorted(fullcopy): |
612 note = "" | 614 note = b"" |
613 if f in copy: | 615 if f in copy: |
614 note += "*" | 616 note += b"*" |
615 if f in divergeset: | 617 if f in divergeset: |
616 note += "!" | 618 note += b"!" |
617 if f in renamedeleteset: | 619 if f in renamedeleteset: |
618 note += "%" | 620 note += b"%" |
619 repo.ui.debug( | 621 repo.ui.debug( |
620 " src: '%s' -> dst: '%s' %s\n" % (fullcopy[f], f, note) | 622 b" src: '%s' -> dst: '%s' %s\n" % (fullcopy[f], f, note) |
621 ) | 623 ) |
622 del divergeset | 624 del divergeset |
623 | 625 |
624 repo.ui.debug(" checking for directory renames\n") | 626 repo.ui.debug(b" checking for directory renames\n") |
625 | 627 |
626 # generate a directory move map | 628 # generate a directory move map |
627 d1, d2 = c1.dirs(), c2.dirs() | 629 d1, d2 = c1.dirs(), c2.dirs() |
628 invalid = set() | 630 invalid = set() |
629 dirmove = {} | 631 dirmove = {} |
654 del d1, d2, invalid | 656 del d1, d2, invalid |
655 | 657 |
656 if not dirmove: | 658 if not dirmove: |
657 return copy, {}, diverge, renamedelete, {} | 659 return copy, {}, diverge, renamedelete, {} |
658 | 660 |
659 dirmove = {k + "/": v + "/" for k, v in dirmove.iteritems()} | 661 dirmove = {k + b"/": v + b"/" for k, v in dirmove.iteritems()} |
660 | 662 |
661 for d in dirmove: | 663 for d in dirmove: |
662 repo.ui.debug( | 664 repo.ui.debug( |
663 " discovered dir src: '%s' -> dst: '%s'\n" % (d, dirmove[d]) | 665 b" discovered dir src: '%s' -> dst: '%s'\n" % (d, dirmove[d]) |
664 ) | 666 ) |
665 | 667 |
666 movewithdir = {} | 668 movewithdir = {} |
667 # check unaccounted nonoverlapping files against directory moves | 669 # check unaccounted nonoverlapping files against directory moves |
668 for f in u1 + u2: | 670 for f in u1 + u2: |
672 # new file added in a directory that was moved, move it | 674 # new file added in a directory that was moved, move it |
673 df = dirmove[d] + f[len(d) :] | 675 df = dirmove[d] + f[len(d) :] |
674 if df not in copy: | 676 if df not in copy: |
675 movewithdir[f] = df | 677 movewithdir[f] = df |
676 repo.ui.debug( | 678 repo.ui.debug( |
677 (" pending file src: '%s' -> " "dst: '%s'\n") | 679 (b" pending file src: '%s' -> " b"dst: '%s'\n") |
678 % (f, df) | 680 % (f, df) |
679 ) | 681 ) |
680 break | 682 break |
681 | 683 |
682 return copy, movewithdir, diverge, renamedelete, dirmove | 684 return copy, movewithdir, diverge, renamedelete, dirmove |
714 | 716 |
715 copies = {} | 717 copies = {} |
716 | 718 |
717 changedfiles = set() | 719 changedfiles = set() |
718 m1 = c1.manifest() | 720 m1 = c1.manifest() |
719 if not repo.revs('%d::%d', base.rev(), c2.rev()): | 721 if not repo.revs(b'%d::%d', base.rev(), c2.rev()): |
720 # If base is not in c2 branch, we switch to fullcopytracing | 722 # If base is not in c2 branch, we switch to fullcopytracing |
721 repo.ui.debug( | 723 repo.ui.debug( |
722 "switching to full copytracing as base is not " | 724 b"switching to full copytracing as base is not " |
723 "an ancestor of c2\n" | 725 b"an ancestor of c2\n" |
724 ) | 726 ) |
725 return _fullcopytracing(repo, c1, c2, base) | 727 return _fullcopytracing(repo, c1, c2, base) |
726 | 728 |
727 ctx = c2 | 729 ctx = c2 |
728 while ctx != base: | 730 while ctx != base: |
729 if len(ctx.parents()) == 2: | 731 if len(ctx.parents()) == 2: |
730 # To keep things simple let's not handle merges | 732 # To keep things simple let's not handle merges |
731 repo.ui.debug("switching to full copytracing because of merges\n") | 733 repo.ui.debug(b"switching to full copytracing because of merges\n") |
732 return _fullcopytracing(repo, c1, c2, base) | 734 return _fullcopytracing(repo, c1, c2, base) |
733 changedfiles.update(ctx.files()) | 735 changedfiles.update(ctx.files()) |
734 ctx = ctx.p1() | 736 ctx = ctx.p1() |
735 | 737 |
736 cp = _forwardcopies(base, c2) | 738 cp = _forwardcopies(base, c2) |
765 # c2.filectx(f) won't fail | 767 # c2.filectx(f) won't fail |
766 f2 = c2.filectx(f) | 768 f2 = c2.filectx(f) |
767 # we can have a lot of candidates which can slow down the heuristics | 769 # we can have a lot of candidates which can slow down the heuristics |
768 # config value to limit the number of candidates moves to check | 770 # config value to limit the number of candidates moves to check |
769 maxcandidates = repo.ui.configint( | 771 maxcandidates = repo.ui.configint( |
770 'experimental', 'copytrace.movecandidateslimit' | 772 b'experimental', b'copytrace.movecandidateslimit' |
771 ) | 773 ) |
772 | 774 |
773 if len(movecandidates) > maxcandidates: | 775 if len(movecandidates) > maxcandidates: |
774 repo.ui.status( | 776 repo.ui.status( |
775 _( | 777 _( |
776 "skipping copytracing for '%s', more " | 778 b"skipping copytracing for '%s', more " |
777 "candidates than the limit: %d\n" | 779 b"candidates than the limit: %d\n" |
778 ) | 780 ) |
779 % (f, len(movecandidates)) | 781 % (f, len(movecandidates)) |
780 ) | 782 ) |
781 continue | 783 continue |
782 | 784 |
831 filter copy records. Any copies that occur between fromrev and | 833 filter copy records. Any copies that occur between fromrev and |
832 skiprev will not be duplicated, even if they appear in the set of | 834 skiprev will not be duplicated, even if they appear in the set of |
833 copies between fromrev and rev. | 835 copies between fromrev and rev. |
834 """ | 836 """ |
835 exclude = {} | 837 exclude = {} |
836 ctraceconfig = repo.ui.config('experimental', 'copytrace') | 838 ctraceconfig = repo.ui.config(b'experimental', b'copytrace') |
837 bctrace = stringutil.parsebool(ctraceconfig) | 839 bctrace = stringutil.parsebool(ctraceconfig) |
838 if skiprev is not None and ( | 840 if skiprev is not None and ( |
839 ctraceconfig == 'heuristics' or bctrace or bctrace is None | 841 ctraceconfig == b'heuristics' or bctrace or bctrace is None |
840 ): | 842 ): |
841 # copytrace='off' skips this line, but not the entire function because | 843 # copytrace='off' skips this line, but not the entire function because |
842 # the line below is O(size of the repo) during a rebase, while the rest | 844 # the line below is O(size of the repo) during a rebase, while the rest |
843 # of the function is much faster (and is required for carrying copy | 845 # of the function is much faster (and is required for carrying copy |
844 # metadata across the rebase anyway). | 846 # metadata across the rebase anyway). |