# HG changeset patch # User Gábor Stefanik # Date 2016-10-04 10:51:54 # Node ID a005c33d0bd785745a905e87f34e90885d0f8cc4 # Parent 856ead835f56b4b364af17a9a750ae576e1b3f1a mergecopies: add logic to process incomplete data We first combine incomplete copies on the two sides of the topological CA into complete copies. Any leftover incomplete copies are then combined with the incomplete divergences to reconstruct divergences spanning over the topological CA. Finally we promote any divergences falsely flagged as incomplete to full divergences. Right now, there is nothing generating incomplete copy/divergence data, so this code does nothing. Changes to _checkcopies to populate these dicts are coming later in this series. diff --git a/mercurial/copies.py b/mercurial/copies.py --- a/mercurial/copies.py +++ b/mercurial/copies.py @@ -289,6 +289,22 @@ def _makegetfctx(ctx): return fctx return util.lrucachefunc(makectx) +def _combinecopies(copyfrom, copyto, finalcopy, diverge, incompletediverge): + """combine partial copy paths""" + remainder = {} + for f in copyfrom: + if f in copyto: + finalcopy[copyto[f]] = copyfrom[f] + del copyto[f] + for f in incompletediverge: + assert f not in diverge + ic = incompletediverge[f] + if ic[0] in copyto: + diverge[f] = [copyto[ic[0]], ic[1]] + else: + remainder[f] = ic + return remainder + def mergecopies(repo, c1, c2, base): """ Find moves and copies between context c1 and c2 that are relevant @@ -360,14 +376,21 @@ def mergecopies(repo, c1, c2, base): # - diverge = record all diverges in this dict # - copy = record all non-divergent copies in this dict # - fullcopy = record all copies in this dict + # - incomplete = record non-divergent partial copies here + # - incompletediverge = record divergent partial copies here diverge = {} # divergence data is shared + incompletediverge = {} data1 = {'copy': {}, 'fullcopy': {}, + 'incomplete': {}, 'diverge': diverge, + 'incompletediverge': incompletediverge, } data2 = {'copy': {}, 'fullcopy': {}, + 'incomplete': {}, 'diverge': diverge, + 'incompletediverge': incompletediverge, } # find interesting file sets from manifests @@ -398,6 +421,13 @@ def mergecopies(repo, c1, c2, base): copy = dict(data1['copy'].items() + data2['copy'].items()) fullcopy = dict(data1['fullcopy'].items() + data2['fullcopy'].items()) + if dirtyc1: + _combinecopies(data2['incomplete'], data1['incomplete'], copy, diverge, + incompletediverge) + else: + _combinecopies(data1['incomplete'], data2['incomplete'], copy, diverge, + incompletediverge) + renamedelete = {} renamedeleteset = set() divergeset = set() @@ -416,13 +446,36 @@ def mergecopies(repo, c1, c2, base): repo.ui.debug(" unmatched files new in both:\n %s\n" % "\n ".join(bothnew)) bothdiverge = {} - bothdata = {'copy': {}, - 'fullcopy': {}, - 'diverge': bothdiverge, - } + bothincompletediverge = {} + both1 = {'copy': {}, + 'fullcopy': {}, + 'incomplete': {}, + 'diverge': bothdiverge, + 'incompletediverge': bothincompletediverge + } + both2 = {'copy': {}, + 'fullcopy': {}, + 'incomplete': {}, + 'diverge': bothdiverge, + 'incompletediverge': bothincompletediverge + } for f in bothnew: - _checkcopies(c1, f, m1, m2, base, tca, limit, bothdata) - _checkcopies(c2, f, m2, m1, base, tca, limit, bothdata) + _checkcopies(c1, f, m1, m2, base, tca, limit, both1) + _checkcopies(c2, f, m2, m1, base, tca, limit, both2) + if dirtyc1: + assert both2['incomplete'] == {} + remainder = _combinecopies({}, both1['incomplete'], copy, bothdiverge, + bothincompletediverge) + else: + assert both1['incomplete'] == {} + remainder = _combinecopies({}, both2['incomplete'], copy, bothdiverge, + bothincompletediverge) + for f in remainder: + assert f not in bothdiverge + ic = remainder[f] + if ic[0] in (m1 if dirtyc1 else m2): + # backed-out rename on one side, but watch out for deleted files + bothdiverge[f] = ic for of, fl in bothdiverge.items(): if len(fl) == 2 and fl[0] == fl[1]: copy[fl[0]] = of # not actually divergent, just matching renames