comparison mercurial/metadata.py @ 44941:edd08aa193fb

files: extract code for extra filtering of the `removed` entry into copies We want to reduce the set of `removed` files that to the set of files actually removed. That `removed` set is used as of the changeset centric algorithm, having smaller sets means less processing and faster computation. In this changeset we extract the code to be a function of it own. We will make use of it in the next changesets. Differential Revision: https://phab.mercurial-scm.org/D8588
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Wed, 27 May 2020 12:45:39 +0200
parents 4c1d39215034
children 25512a65cefd
comparison
equal deleted inserted replaced
44940:4c1d39215034 44941:edd08aa193fb
9 9
10 import multiprocessing 10 import multiprocessing
11 11
12 from . import ( 12 from . import (
13 error, 13 error,
14 node,
14 pycompat, 15 pycompat,
15 util, 16 util,
16 ) 17 )
17 18
18 from .revlogutils import ( 19 from .revlogutils import (
27 added = [] 28 added = []
28 for f in ctx.files(): 29 for f in ctx.files():
29 if not any(f in p for p in ctx.parents()): 30 if not any(f in p for p in ctx.parents()):
30 added.append(f) 31 added.append(f)
31 return added 32 return added
33
34
35 def get_removal_filter(ctx, x=None):
36 """return a function to detect files "wrongly" detected as `removed`
37
38 When a file is removed relative to p1 in a merge, this
39 function determines whether the absence is due to a
40 deletion from a parent, or whether the merge commit
41 itself deletes the file. We decide this by doing a
42 simplified three way merge of the manifest entry for
43 the file. There are two ways we decide the merge
44 itself didn't delete a file:
45 - neither parent (nor the merge) contain the file
46 - exactly one parent contains the file, and that
47 parent has the same filelog entry as the merge
48 ancestor (or all of them if there two). In other
49 words, that parent left the file unchanged while the
50 other one deleted it.
51 One way to think about this is that deleting a file is
52 similar to emptying it, so the list of changed files
53 should be similar either way. The computation
54 described above is not done directly in _filecommit
55 when creating the list of changed files, however
56 it does something very similar by comparing filelog
57 nodes.
58 """
59
60 if x is not None:
61 p1, p2, m1, m2 = x
62 else:
63 p1 = ctx.p1()
64 p2 = ctx.p2()
65 m1 = p1.manifest()
66 m2 = p2.manifest()
67
68 @util.cachefunc
69 def mas():
70 p1n = p1.node()
71 p2n = p2.node()
72 cahs = ctx.repo().changelog.commonancestorsheads(p1n, p2n)
73 if not cahs:
74 cahs = [node.nullrev]
75 return [ctx.repo()[r].manifest() for r in cahs]
76
77 def deletionfromparent(f):
78 if f in m1:
79 return f not in m2 and all(
80 f in ma and ma.find(f) == m1.find(f) for ma in mas()
81 )
82 elif f in m2:
83 return all(f in ma and ma.find(f) == m2.find(f) for ma in mas())
84 else:
85 return True
86
87 return deletionfromparent
32 88
33 89
34 def computechangesetfilesremoved(ctx): 90 def computechangesetfilesremoved(ctx):
35 """return the list of files removed in a changeset 91 """return the list of files removed in a changeset
36 """ 92 """