comparison tests/test-graft.t @ 42222:57203e0210f8

copies: calculate mergecopies() based on pathcopies() When copies are stored in changesets, we need a changeset-centric version of mergecopies() just like we have a changeset-centric version of pathcopies(). I think the natural way of thinking about mergecopies() is in terms of pathcopies() from the base to each of the commits. So if we can rewrite mergecopies() based on two such pathcopies() calls, we'll get the changeset-centric version for free. That's what this patch does. A nice bonus is that it ends up being a lot simpler. mergecopies() has accumulated a lot of technical debt over time. One good example is the code for dealing with grafts (the "partial/incomplete/dirty" stuff). Since pathcopies() already deals with backwards renames and ping-pong renames, we get that for free. I've run tests with hard-coded debug logging for "fullcopy" and while I haven't looked at every difference it produces, all the ones I have looked at seemed reasonable to me. I'm a little surprised that no more tests fail when run with '--extra-config-opt experimental.copies.read-from=compatibility' compared to before this patch. This patch also fixes the broken cases in test-annotate.t and test-fastannotate.t. It also enables the part of test-copies.t that was previously disabled exactly because mergecopies() needed to get a changeset-centric version. One drawback of the rewritten code is that we may now make remotefilelog prefetch more files. We used to prefetch files that were unique to either side of the merge compared to the other. We now prefetch files that are unique to either side of the merge compared to the base. This means that if you added the same file to each side, we would not prefetch it before, but we would now. Such cases are probably quite rare, but one likely scenario where they happen is when moving from a commit to its successor (or the other way around). The user will probably already have the files in the cache in such cases, so it's probably not a big deal. Some timings for calculating mergecopies between two revisions (revisions shown on each line, all using the common ancestor as base): In the hg repo: 4.8 4.9: 0.21s -> 0.21s 4.0 4.8: 0.35s -> 0.63s In and old copy of the mozilla-unified repo: FIREFOX_BETA_60_BASE^ FIREFOX_BETA_60_BASE: 0.82s -> 0.82s FIREFOX_NIGHTLY_59_END FIREFOX_BETA_60_BASE: 2.5s -> 2.6s FIREFOX_BETA_59_END FIREFOX_BETA_60_BASE: 3.9s -> 4.1s FIREFOX_AURORA_50_BASE FIREFOX_BETA_60_BASE: 31s -> 33s So it's measurably slower in most cases. The most significant difference is in the hg repo between revisions 4.0 and 4.8. In that case it seems to come from the fact that pathcopies() uses fctx.isintroducedafter() (in _tracefile), while the old mergecopies() used fctx.linkrev() (in _checkcopies()). That results in a single call to filectx._adjustlinkrev(), which is responsible for the entire difference in time (in my repo). So we pay a performance penalty but we get more correct code (see change in test-mv-cp-st-diff.t). Deleting the "== f.filenode()" in _tracefile() recovers the lost performance in the hg repo. There were are few other optimizations in _checkcopies() that I could not measure any impact from. One was from the "seen" set. Another was from a "continue" when the file was not in the destination manifest (corresponding to "am" in _tracefile). Also note that merge copies are not calculated when updating with a clean working copy, which is probably the most common case. I therefore think the much simpler code is worth the slowdown. Differential Revision: https://phab.mercurial-scm.org/D6255
author Martin von Zweigbergk <martinvonz@google.com>
date Thu, 11 Apr 2019 23:22:54 -0700
parents a68036b849b0
children 8988e640a8ac
comparison
equal deleted inserted replaced
42221:c83c08cf02b7 42222:57203e0210f8
73 73
74 Specifying child as --base revision fails safely (perhaps slightly confusing, but consistent) 74 Specifying child as --base revision fails safely (perhaps slightly confusing, but consistent)
75 75
76 $ hg graft -r 2 --base 3 76 $ hg graft -r 2 --base 3
77 grafting 2:5c095ad7e90f "2" 77 grafting 2:5c095ad7e90f "2"
78 note: possible conflict - c was deleted and renamed to:
79 a
78 note: graft of 2:5c095ad7e90f created no changes to commit 80 note: graft of 2:5c095ad7e90f created no changes to commit
79 81
80 Can't continue without starting: 82 Can't continue without starting:
81 83
82 $ hg -q up -cr tip 84 $ hg -q up -cr tip
218 b 220 b
219 committing manifest 221 committing manifest
220 committing changelog 222 committing changelog
221 updating the branch cache 223 updating the branch cache
222 grafting 5:97f8bfe72746 "5" 224 grafting 5:97f8bfe72746 "5"
225 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
226 src: 'c' -> dst: 'b'
227 checking for directory renames
223 resolving manifests 228 resolving manifests
224 branchmerge: True, force: True, partial: False 229 branchmerge: True, force: True, partial: False
225 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746 230 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
226 e: remote is newer -> g 231 e: remote is newer -> g
227 getting e 232 getting e
231 committing changelog 236 committing changelog
232 updating the branch cache 237 updating the branch cache
233 $ HGEDITOR=cat hg graft 4 3 --log --debug 238 $ HGEDITOR=cat hg graft 4 3 --log --debug
234 scanning for duplicate grafts 239 scanning for duplicate grafts
235 grafting 4:9c233e8e184d "4" 240 grafting 4:9c233e8e184d "4"
241 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
242 src: 'c' -> dst: 'b'
243 checking for directory renames
236 resolving manifests 244 resolving manifests
237 branchmerge: True, force: True, partial: False 245 branchmerge: True, force: True, partial: False
238 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d 246 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
239 preserving e for resolve of e 247 preserving e for resolve of e
240 d: remote is newer -> g 248 d: remote is newer -> g
1127 $ hg up -q "desc("E0")" 1135 $ hg up -q "desc("E0")"
1128 $ HGEDITOR="echo C2 >" hg graft -r 'desc("C0")' --edit 1136 $ HGEDITOR="echo C2 >" hg graft -r 'desc("C0")' --edit
1129 grafting 2:f58c7e2b28fa "C0" 1137 grafting 2:f58c7e2b28fa "C0"
1130 merging f1e and f1b to f1e 1138 merging f1e and f1b to f1e
1131 merging f2a and f2c to f2c 1139 merging f2a and f2c to f2c
1132 merging f5b and f5a to f5a
1133 1140
1134 Test the cases A.1 (f4x) and A.7 (f3x). 1141 Test the cases A.1 (f4x) and A.7 (f3x).
1135 1142
1136 $ HGEDITOR="echo D2 >" hg graft -r 'desc("D0")' --edit 1143 $ HGEDITOR="echo D2 >" hg graft -r 'desc("D0")' --edit
1137 grafting 3:b69f5839d2d9 "D0" 1144 grafting 3:b69f5839d2d9 "D0"