Mercurial > public > mercurial-scm > hg
comparison mercurial/copies.py @ 46011:b9588ff9b66a
copies: avoid materializing a full directory map during copy tracing
Materializing a full copy of every directory in a treemanifest repo can be quite
expensive, even with a narrow matcher. For flat manifest repos, this should be
equivalent - it will still materialize (and cache) a dict of all of the dirs
inside of the manifest object, we just don't get a copy of it.
In a repo I have here, this brings the time for a simple rebase from 11.197s to
4.609s.
Differential Revision: https://phab.mercurial-scm.org/D9503
author | Kyle Lippincott <spectral@google.com> |
---|---|
date | Wed, 02 Dec 2020 11:05:53 -0800 |
parents | f9f8d8aa9a92 |
children | 8d54944eaeb0 |
comparison
equal
deleted
inserted
replaced
46010:61c1f29e7f4f | 46011:b9588ff9b66a |
---|---|
928 fullcopy: files copied on the same side (as ctx), including those that | 928 fullcopy: files copied on the same side (as ctx), including those that |
929 merge.manifestmerge() won't care about | 929 merge.manifestmerge() won't care about |
930 addedfiles: added files on the other side (compared to ctx) | 930 addedfiles: added files on the other side (compared to ctx) |
931 """ | 931 """ |
932 # generate a directory move map | 932 # generate a directory move map |
933 d = ctx.dirs() | |
934 invalid = set() | 933 invalid = set() |
935 dirmove = {} | 934 dirmove = {} |
936 | 935 |
937 # examine each file copy for a potential directory move, which is | 936 # examine each file copy for a potential directory move, which is |
938 # when all the files in a directory are moved to a new directory | 937 # when all the files in a directory are moved to a new directory |
939 for dst, src in pycompat.iteritems(fullcopy): | 938 for dst, src in pycompat.iteritems(fullcopy): |
940 dsrc, ddst = pathutil.dirname(src), pathutil.dirname(dst) | 939 dsrc, ddst = pathutil.dirname(src), pathutil.dirname(dst) |
941 if dsrc in invalid: | 940 if dsrc in invalid: |
942 # already seen to be uninteresting | 941 # already seen to be uninteresting |
943 continue | 942 continue |
944 elif dsrc in d and ddst in d: | 943 elif ctx.hasdir(dsrc) and ctx.hasdir(ddst): |
945 # directory wasn't entirely moved locally | 944 # directory wasn't entirely moved locally |
946 invalid.add(dsrc) | 945 invalid.add(dsrc) |
947 elif dsrc in dirmove and dirmove[dsrc] != ddst: | 946 elif dsrc in dirmove and dirmove[dsrc] != ddst: |
948 # files from the same directory moved to two different places | 947 # files from the same directory moved to two different places |
949 invalid.add(dsrc) | 948 invalid.add(dsrc) |
952 dirmove[dsrc] = ddst | 951 dirmove[dsrc] = ddst |
953 | 952 |
954 for i in invalid: | 953 for i in invalid: |
955 if i in dirmove: | 954 if i in dirmove: |
956 del dirmove[i] | 955 del dirmove[i] |
957 del d, invalid | 956 del invalid |
958 | 957 |
959 if not dirmove: | 958 if not dirmove: |
960 return {}, {} | 959 return {}, {} |
961 | 960 |
962 dirmove = {k + b"/": v + b"/" for k, v in pycompat.iteritems(dirmove)} | 961 dirmove = {k + b"/": v + b"/" for k, v in pycompat.iteritems(dirmove)} |