mercurial/copies.py
changeset 30195 88626de195f8
parent 30194 8c69c52ced98
child 30196 d738cda70894
equal deleted inserted replaced
30194:8c69c52ced98 30195:88626de195f8
   372     u1r, u2r = _computenonoverlap(repo, c1, c2, addedinm1, addedinm2)
   372     u1r, u2r = _computenonoverlap(repo, c1, c2, addedinm1, addedinm2)
   373     u1u, u2u = u1r, u2r
   373     u1u, u2u = u1r, u2r
   374     bothnew = sorted(addedinm1 & addedinm2)
   374     bothnew = sorted(addedinm1 & addedinm2)
   375 
   375 
   376     for f in u1u:
   376     for f in u1u:
   377         _checkcopies(c1, f, m1, m2, base, limit, data1)
   377         _checkcopies(c1, f, m1, m2, base, tca, limit, data1)
   378 
   378 
   379     for f in u2u:
   379     for f in u2u:
   380         _checkcopies(c2, f, m2, m1, base, limit, data2)
   380         _checkcopies(c2, f, m2, m1, base, tca, limit, data2)
   381 
   381 
   382     copy = dict(data1['copy'].items() + data2['copy'].items())
   382     copy = dict(data1['copy'].items() + data2['copy'].items())
   383     fullcopy = dict(data1['fullcopy'].items() + data2['fullcopy'].items())
   383     fullcopy = dict(data1['fullcopy'].items() + data2['fullcopy'].items())
   384 
   384 
   385     renamedelete = {}
   385     renamedelete = {}
   403     bothdata = {'copy': {},
   403     bothdata = {'copy': {},
   404                 'fullcopy': {},
   404                 'fullcopy': {},
   405                 'diverge': bothdiverge,
   405                 'diverge': bothdiverge,
   406                }
   406                }
   407     for f in bothnew:
   407     for f in bothnew:
   408         _checkcopies(c1, f, m1, m2, base, limit, bothdata)
   408         _checkcopies(c1, f, m1, m2, base, tca, limit, bothdata)
   409         _checkcopies(c2, f, m2, m1, base, limit, bothdata)
   409         _checkcopies(c2, f, m2, m1, base, tca, limit, bothdata)
   410     for of, fl in bothdiverge.items():
   410     for of, fl in bothdiverge.items():
   411         if len(fl) == 2 and fl[0] == fl[1]:
   411         if len(fl) == 2 and fl[0] == fl[1]:
   412             copy[fl[0]] = of # not actually divergent, just matching renames
   412             copy[fl[0]] = of # not actually divergent, just matching renames
   413 
   413 
   414     if fullcopy and repo.ui.debugflag:
   414     if fullcopy and repo.ui.debugflag:
   519             elif f1r == f2r or f1r < limit or f2r < limit:
   519             elif f1r == f2r or f1r < limit or f2r < limit:
   520                 return False # copy no longer relevant
   520                 return False # copy no longer relevant
   521     except StopIteration:
   521     except StopIteration:
   522         return False
   522         return False
   523 
   523 
   524 def _checkcopies(ctx, f, m1, m2, base, limit, data):
   524 def _checkcopies(ctx, f, m1, m2, base, tca, limit, data):
   525     """
   525     """
   526     check possible copies of f from m1 to m2
   526     check possible copies of f from m1 to m2
   527 
   527 
   528     ctx = starting context for f in m1
   528     ctx = starting context for f in m1
   529     f = the filename to check (as in m1)
   529     f = the filename to check (as in m1)
   530     m1 = the source manifest
   530     m1 = the source manifest
   531     m2 = the destination manifest
   531     m2 = the destination manifest
   532     base = the changectx used as a merge base
   532     base = the changectx used as a merge base
       
   533     tca = topological common ancestor for graft-like scenarios
   533     limit = the rev number to not search beyond
   534     limit = the rev number to not search beyond
   534     data = dictionary of dictionary to store copy data. (see mergecopies)
   535     data = dictionary of dictionary to store copy data. (see mergecopies)
   535 
   536 
   536     note: limit is only an optimization, and there is no guarantee that
   537     note: limit is only an optimization, and there is no guarantee that
   537     irrelevant revisions will not be limited
   538     irrelevant revisions will not be limited
   538     there is no easy way to make this algorithm stop in a guaranteed way
   539     there is no easy way to make this algorithm stop in a guaranteed way
   539     once it "goes behind a certain revision".
   540     once it "goes behind a certain revision".
   540     """
   541     """
   541 
   542 
   542     mb = base.manifest()
   543     mb = base.manifest()
       
   544     # Might be true if this call is about finding backward renames,
       
   545     # This happens in the case of grafts because the DAG is then rotated.
       
   546     # If the file exists in both the base and the source, we are not looking
       
   547     # for a rename on the source side, but on the part of the DAG that is
       
   548     # traversed backwards.
       
   549     #
       
   550     # In the case there is both backward and forward renames (before and after
       
   551     # the base) this is more complicated as we must detect a divergence. This
       
   552     # is currently broken and hopefully some later code update will make that
       
   553     # work (we use 'backwards = False' in that case)
       
   554     backwards = base != tca and f in mb
   543     getfctx = _makegetfctx(ctx)
   555     getfctx = _makegetfctx(ctx)
   544 
   556 
   545     of = None
   557     of = None
   546     seen = set([f])
   558     seen = set([f])
   547     for oc in getfctx(f, m1[f]).ancestors():
   559     for oc in getfctx(f, m1[f]).ancestors():
   552             if ocr < limit:
   564             if ocr < limit:
   553                 break
   565                 break
   554             continue
   566             continue
   555         seen.add(of)
   567         seen.add(of)
   556 
   568 
   557         data['fullcopy'][f] = of # remember for dir rename detection
   569         # remember for dir rename detection
       
   570         if backwards:
       
   571             data['fullcopy'][of] = f # grafting backwards through renames
       
   572         else:
       
   573             data['fullcopy'][f] = of
   558         if of not in m2:
   574         if of not in m2:
   559             continue # no match, keep looking
   575             continue # no match, keep looking
   560         if m2[of] == mb.get(of):
   576         if m2[of] == mb.get(of):
   561             return # no merge needed, quit early
   577             return # no merge needed, quit early
   562         c2 = getfctx(of, m2[of])
   578         c2 = getfctx(of, m2[of])
   563         # c2 might be a plain new file on added on destination side that is
   579         # c2 might be a plain new file on added on destination side that is
   564         # unrelated to the droids we are looking for.
   580         # unrelated to the droids we are looking for.
   565         cr = _related(oc, c2, base.rev())
   581         cr = _related(oc, c2, tca.rev())
   566         if cr and (of == f or of == c2.path()): # non-divergent
   582         if cr and (of == f or of == c2.path()): # non-divergent
   567             if of in mb:
   583             if backwards:
       
   584                 data['copy'][of] = f
       
   585             elif of in mb:
   568                 data['copy'][f] = of
   586                 data['copy'][f] = of
   569             return
   587             return
   570 
   588 
   571     if of in mb:
   589     if of in mb:
   572         data['diverge'].setdefault(of, []).append(f)
   590         data['diverge'].setdefault(of, []).append(f)