##// END OF EJS Templates
files: extract code for extra filtering of the `removed` entry into copies...
marmoute -
r45467:edd08aa1 default
parent child Browse files
Show More
@@ -46,6 +46,7 b' from . import ('
46 match as matchmod,
46 match as matchmod,
47 mergestate as mergestatemod,
47 mergestate as mergestatemod,
48 mergeutil,
48 mergeutil,
49 metadata,
49 namespaces,
50 namespaces,
50 narrowspec,
51 narrowspec,
51 obsolete,
52 obsolete,
@@ -3145,51 +3146,8 b' class localrepository(object):'
3145 for f in drop:
3146 for f in drop:
3146 del m[f]
3147 del m[f]
3147 if p2.rev() != nullrev:
3148 if p2.rev() != nullrev:
3148
3149 rf = metadata.get_removal_filter(ctx, (p1, p2, m1, m2))
3149 @util.cachefunc
3150 removed = [f for f in removed if not rf(f)]
3150 def mas():
3151 p1n = p1.node()
3152 p2n = p2.node()
3153 cahs = self.changelog.commonancestorsheads(p1n, p2n)
3154 if not cahs:
3155 cahs = [nullrev]
3156 return [self[r].manifest() for r in cahs]
3157
3158 def deletionfromparent(f):
3159 # When a file is removed relative to p1 in a merge, this
3160 # function determines whether the absence is due to a
3161 # deletion from a parent, or whether the merge commit
3162 # itself deletes the file. We decide this by doing a
3163 # simplified three way merge of the manifest entry for
3164 # the file. There are two ways we decide the merge
3165 # itself didn't delete a file:
3166 # - neither parent (nor the merge) contain the file
3167 # - exactly one parent contains the file, and that
3168 # parent has the same filelog entry as the merge
3169 # ancestor (or all of them if there two). In other
3170 # words, that parent left the file unchanged while the
3171 # other one deleted it.
3172 # One way to think about this is that deleting a file is
3173 # similar to emptying it, so the list of changed files
3174 # should be similar either way. The computation
3175 # described above is not done directly in _filecommit
3176 # when creating the list of changed files, however
3177 # it does something very similar by comparing filelog
3178 # nodes.
3179 if f in m1:
3180 return f not in m2 and all(
3181 f in ma and ma.find(f) == m1.find(f)
3182 for ma in mas()
3183 )
3184 elif f in m2:
3185 return all(
3186 f in ma and ma.find(f) == m2.find(f)
3187 for ma in mas()
3188 )
3189 else:
3190 return True
3191
3192 removed = [f for f in removed if not deletionfromparent(f)]
3193
3151
3194 files = changed + removed
3152 files = changed + removed
3195 md = None
3153 md = None
@@ -11,6 +11,7 b' 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 )
@@ -31,6 +32,61 b' def computechangesetfilesadded(ctx):'
31 return added
32 return added
32
33
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
88
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 """
General Comments 0
You need to be logged in to leave comments. Login now