169 ) |
169 ) |
170 return cm |
170 return cm |
171 |
171 |
172 |
172 |
173 def _revinfo_getter(repo): |
173 def _revinfo_getter(repo): |
174 """return a function that return multiple data given a <rev>"i |
174 """returns a function that returns the following data given a <rev>" |
175 |
175 |
176 * p1: revision number of first parent |
176 * p1: revision number of first parent |
177 * p2: revision number of first parent |
177 * p2: revision number of first parent |
178 * p1copies: mapping of copies from p1 |
178 * changes: a ChangingFiles object |
179 * p2copies: mapping of copies from p2 |
|
180 * removed: a list of removed files |
|
181 * ismerged: a callback to know if file was merged in that revision |
|
182 """ |
179 """ |
183 cl = repo.changelog |
180 cl = repo.changelog |
184 parents = cl.parentrevs |
181 parents = cl.parentrevs |
185 |
|
186 def get_ismerged(rev): |
|
187 ctx = repo[rev] |
|
188 |
|
189 def ismerged(path): |
|
190 if path not in ctx.files(): |
|
191 return False |
|
192 fctx = ctx[path] |
|
193 parents = fctx._filelog.parents(fctx._filenode) |
|
194 nb_parents = 0 |
|
195 for n in parents: |
|
196 if n != node.nullid: |
|
197 nb_parents += 1 |
|
198 return nb_parents >= 2 |
|
199 |
|
200 return ismerged |
|
201 |
182 |
202 changelogrevision = cl.changelogrevision |
183 changelogrevision = cl.changelogrevision |
203 |
184 |
204 # A small cache to avoid doing the work twice for merges |
185 # A small cache to avoid doing the work twice for merges |
205 # |
186 # |
230 p1, p2 = parents(rev) |
211 p1, p2 = parents(rev) |
231 value = None |
212 value = None |
232 e = merge_caches.pop(rev, None) |
213 e = merge_caches.pop(rev, None) |
233 if e is not None: |
214 if e is not None: |
234 return e |
215 return e |
235 c = changelogrevision(rev) |
216 value = (p1, p2, changelogrevision(rev).changes) |
236 p1copies = c.p1copies |
|
237 p2copies = c.p2copies |
|
238 removed = c.filesremoved |
|
239 if p1 != node.nullrev and p2 != node.nullrev: |
217 if p1 != node.nullrev and p2 != node.nullrev: |
240 # XXX some case we over cache, IGNORE |
218 # XXX some case we over cache, IGNORE |
241 value = merge_caches[rev] = ( |
219 merge_caches[rev] = value |
242 p1, |
|
243 p2, |
|
244 p1copies, |
|
245 p2copies, |
|
246 removed, |
|
247 get_ismerged(rev), |
|
248 ) |
|
249 |
|
250 if value is None: |
|
251 value = (p1, p2, p1copies, p2copies, removed, get_ismerged(rev)) |
|
252 return value |
220 return value |
253 |
221 |
254 return revinfo |
222 return revinfo |
255 |
223 |
256 |
224 |
322 copies = all_copies.pop(r, None) |
290 copies = all_copies.pop(r, None) |
323 if copies is None: |
291 if copies is None: |
324 # this is a root |
292 # this is a root |
325 copies = {} |
293 copies = {} |
326 for i, c in enumerate(children[r]): |
294 for i, c in enumerate(children[r]): |
327 p1, p2, p1copies, p2copies, removed, ismerged = revinfo(c) |
295 p1, p2, changes = revinfo(c) |
328 if r == p1: |
296 if r == p1: |
329 parent = 1 |
297 parent = 1 |
330 childcopies = p1copies |
298 childcopies = changes.copied_from_p1 |
331 else: |
299 else: |
332 assert r == p2 |
300 assert r == p2 |
333 parent = 2 |
301 parent = 2 |
334 childcopies = p2copies |
302 childcopies = changes.copied_from_p2 |
335 if not alwaysmatch: |
303 if not alwaysmatch: |
336 childcopies = { |
304 childcopies = { |
337 dst: src for dst, src in childcopies.items() if match(dst) |
305 dst: src for dst, src in childcopies.items() if match(dst) |
338 } |
306 } |
339 newcopies = copies |
307 newcopies = copies |
343 prev = copies.get(source) |
311 prev = copies.get(source) |
344 if prev is not None and prev[1] is not None: |
312 if prev is not None and prev[1] is not None: |
345 source = prev[1] |
313 source = prev[1] |
346 newcopies[dest] = (c, source) |
314 newcopies[dest] = (c, source) |
347 assert newcopies is not copies |
315 assert newcopies is not copies |
348 for f in removed: |
316 for f in changes.removed: |
349 if f in newcopies: |
317 if f in newcopies: |
350 if newcopies is copies: |
318 if newcopies is copies: |
351 # copy on write to avoid affecting potential other |
319 # copy on write to avoid affecting potential other |
352 # branches. when there are no other branches, this |
320 # branches. when there are no other branches, this |
353 # could be avoided. |
321 # could be avoided. |
364 # This is an arbitrary choice made anew when implementing |
332 # This is an arbitrary choice made anew when implementing |
365 # changeset based copies. It was made without regards with |
333 # changeset based copies. It was made without regards with |
366 # potential filelog related behavior. |
334 # potential filelog related behavior. |
367 if parent == 1: |
335 if parent == 1: |
368 _merge_copies_dict( |
336 _merge_copies_dict( |
369 othercopies, newcopies, isancestor, ismerged |
337 othercopies, newcopies, isancestor, changes |
370 ) |
338 ) |
371 else: |
339 else: |
372 _merge_copies_dict( |
340 _merge_copies_dict( |
373 newcopies, othercopies, isancestor, ismerged |
341 newcopies, othercopies, isancestor, changes |
374 ) |
342 ) |
375 all_copies[c] = newcopies |
343 all_copies[c] = newcopies |
376 |
344 |
377 final_copies = {} |
345 final_copies = {} |
378 for dest, (tt, source) in all_copies[targetrev].items(): |
346 for dest, (tt, source) in all_copies[targetrev].items(): |
379 if source is not None: |
347 if source is not None: |
380 final_copies[dest] = source |
348 final_copies[dest] = source |
381 return final_copies |
349 return final_copies |
382 |
350 |
383 |
351 |
384 def _merge_copies_dict(minor, major, isancestor, ismerged): |
352 def _merge_copies_dict(minor, major, isancestor, changes): |
385 """merge two copies-mapping together, minor and major |
353 """merge two copies-mapping together, minor and major |
386 |
354 |
387 In case of conflict, value from "major" will be picked. |
355 In case of conflict, value from "major" will be picked. |
388 |
356 |
389 - `isancestors(low_rev, high_rev)`: callable return True if `low_rev` is an |
357 - `isancestors(low_rev, high_rev)`: callable return True if `low_rev` is an |
404 # content from "major" wins, unless it is older |
372 # content from "major" wins, unless it is older |
405 # than the branch point or there is a merge |
373 # than the branch point or there is a merge |
406 if ( |
374 if ( |
407 new_tt == other_tt |
375 new_tt == other_tt |
408 or not isancestor(new_tt, other_tt) |
376 or not isancestor(new_tt, other_tt) |
409 or ismerged(dest) |
377 or dest in changes.merged |
410 ): |
378 ): |
411 minor[dest] = value |
379 minor[dest] = value |
412 |
380 |
413 |
381 |
414 def _revinfo_getter_extra(repo): |
382 def _revinfo_getter_extra(repo): |