mercurial/merge.py
changeset 4397 c04c96504a12
parent 4354 8aee687f0214
child 4398 9fe267f77f56
equal deleted inserted replaced
4387:80d3f6f0d8e5 4397:c04c96504a12
   131         return l
   131         return l
   132 
   132 
   133     def checkcopies(c, man):
   133     def checkcopies(c, man):
   134         '''check possible copies for filectx c'''
   134         '''check possible copies for filectx c'''
   135         for of in findold(c):
   135         for of in findold(c):
   136             if of not in man:
   136             if of not in man: # original file not in other manifest?
   137                 continue
   137                 continue
   138             c2 = ctx(of, man[of])
   138             c2 = ctx(of, man[of])
   139             ca = c.ancestor(c2)
   139             ca = c.ancestor(c2)
   140             if not ca: # unrelated
   140             if not ca: # unrelated?
   141                 continue
   141                 continue
       
   142             # named changed on only one side?
   142             if ca.path() == c.path() or ca.path() == c2.path():
   143             if ca.path() == c.path() or ca.path() == c2.path():
   143                 fullcopy[c.path()] = of
   144                 fullcopy[c.path()] = of # remember for dir rename detection
   144                 if c == ca and c2 == ca: # no merge needed, ignore copy
   145                 if c == ca and c2 == ca: # no merge needed, ignore copy
   145                     continue
   146                     continue
   146                 copy[c.path()] = of
   147                 copy[c.path()] = of
   147 
   148 
   148     def dirs(files):
   149     def dirs(files):
   177     # generate a directory move map
   178     # generate a directory move map
   178     d1, d2 = dirs(m1), dirs(m2)
   179     d1, d2 = dirs(m1), dirs(m2)
   179     invalid = {}
   180     invalid = {}
   180     dirmove = {}
   181     dirmove = {}
   181 
   182 
       
   183     # examine each file copy for a potential directory move, which is
       
   184     # when all the files in a directory are moved to a new directory
   182     for dst, src in fullcopy.items():
   185     for dst, src in fullcopy.items():
   183         dsrc, ddst = os.path.dirname(src), os.path.dirname(dst)
   186         dsrc, ddst = os.path.dirname(src), os.path.dirname(dst)
   184         if dsrc in invalid:
   187         if dsrc in invalid:
   185             continue
   188             # already seen to be uninteresting
   186         elif (dsrc in d1 and ddst in d1) or (dsrc in d2 and ddst in d2):
   189             continue
       
   190         elif dsrc in d1 and ddst in d1:
       
   191             # directory wasn't entirely moved locally
       
   192             invalid[dsrc] = True
       
   193         elif dsrc in d2 and ddst in d2:
       
   194             # directory wasn't entirely moved remotely
   187             invalid[dsrc] = True
   195             invalid[dsrc] = True
   188         elif dsrc in dirmove and dirmove[dsrc] != ddst:
   196         elif dsrc in dirmove and dirmove[dsrc] != ddst:
       
   197             # files from the same directory moved to two different places
   189             invalid[dsrc] = True
   198             invalid[dsrc] = True
   190             del dirmove[dsrc]
   199             del dirmove[dsrc]
   191         else:
   200         else:
       
   201             # looks good so far
   192             dirmove[dsrc + "/"] = ddst + "/"
   202             dirmove[dsrc + "/"] = ddst + "/"
   193 
   203 
   194     del d1, d2, invalid
   204     del d1, d2, invalid
   195 
   205 
   196     if not dirmove:
   206     if not dirmove:
   197         return copy
   207         return copy
   198 
   208 
   199     # check unaccounted nonoverlapping files
   209     # check unaccounted nonoverlapping files against directory moves
   200     for f in u1 + u2:
   210     for f in u1 + u2:
   201         if f not in fullcopy:
   211         if f not in fullcopy:
   202             for d in dirmove:
   212             for d in dirmove:
   203                 if f.startswith(d):
   213                 if f.startswith(d):
       
   214                     # new file added in a directory that was moved, move it
   204                     copy[f] = dirmove[d] + f[len(d):]
   215                     copy[f] = dirmove[d] + f[len(d):]
   205                     break
   216                     break
   206 
   217 
   207     return copy
   218     return copy
   208 
   219