mercurial/merge.py
branchstable
changeset 20593 3678707e4017
parent 20592 303cbfe3dcc8
child 20594 ba619c50a355
equal deleted inserted replaced
20592:303cbfe3dcc8 20593:3678707e4017
    13 import error, util, filemerge, copies, subrepo, worker, dicthelpers
    13 import error, util, filemerge, copies, subrepo, worker, dicthelpers
    14 import errno, os, shutil
    14 import errno, os, shutil
    15 
    15 
    16 _pack = struct.pack
    16 _pack = struct.pack
    17 _unpack = struct.unpack
    17 _unpack = struct.unpack
       
    18 
       
    19 def _droponode(data):
       
    20     # used for compatibility for v1
       
    21     bits = data.split("\0")
       
    22     bits = bits[:-2] + bits[-1:]
       
    23     return "\0".join(bits)
    18 
    24 
    19 class mergestate(object):
    25 class mergestate(object):
    20     '''track 3-way merge state of individual files
    26     '''track 3-way merge state of individual files
    21 
    27 
    22     it is stored on disk when needed. Two file are used, one with an old
    28     it is stored on disk when needed. Two file are used, one with an old
    68                                    % rtype))
    74                                    % rtype))
    69         self._dirty = False
    75         self._dirty = False
    70     def _readrecords(self):
    76     def _readrecords(self):
    71         v1records = self._readrecordsv1()
    77         v1records = self._readrecordsv1()
    72         v2records = self._readrecordsv2()
    78         v2records = self._readrecordsv2()
    73         allv2 = set(v2records)
    79         oldv2 = set() # old format version of v2 record
    74         for rev in v1records:
    80         for rec in v2records:
    75             if rev not in allv2:
    81             if rec[0] == 'L':
       
    82                 oldv2.add(rec)
       
    83             elif rec[0] == 'F':
       
    84                 # drop the onode data (not contained in v1)
       
    85                 oldv2.add(('F', _droponode(rec[1])))
       
    86         for rec in v1records:
       
    87             if rec not in oldv2:
    76                 # v1 file is newer than v2 file, use it
    88                 # v1 file is newer than v2 file, use it
    77                 # we have to infer the "other" changeset of the merge
    89                 # we have to infer the "other" changeset of the merge
    78                 # we cannot do better than that with v1 of the format
    90                 # we cannot do better than that with v1 of the format
    79                 mctx = self._repo[None].parents()[-1]
    91                 mctx = self._repo[None].parents()[-1]
    80                 v1records.append(('O', mctx.hex()))
    92                 v1records.append(('O', mctx.hex()))
       
    93                 # add place holder "other" file node information
       
    94                 # nobody is using it yet so we do no need to fetch the data
       
    95                 # if mctx was wrong `mctx[bits[-2]]` may fails.
       
    96                 for idx, r in enumerate(v1records):
       
    97                     if r[0] == 'F':
       
    98                         bits = r[1].split("\0")
       
    99                         bits.insert(-2, '')
       
   100                         v1records[idx] = (r[0], "\0".join(bits))
    81                 return v1records
   101                 return v1records
    82         else:
   102         else:
    83             return v2records
   103             return v2records
    84     def _readrecordsv1(self):
   104     def _readrecordsv1(self):
    85         records = []
   105         records = []
   133         lrecords = irecords.next()
   153         lrecords = irecords.next()
   134         assert lrecords[0] == 'L'
   154         assert lrecords[0] == 'L'
   135         f.write(hex(self._local) + "\n")
   155         f.write(hex(self._local) + "\n")
   136         for rtype, data in irecords:
   156         for rtype, data in irecords:
   137             if rtype == "F":
   157             if rtype == "F":
   138                 f.write("%s\n" % data)
   158                 f.write("%s\n" % _droponode(data))
   139         f.close()
   159         f.close()
   140     def _writerecordsv2(self, records):
   160     def _writerecordsv2(self, records):
   141         f = self._repo.opener(self.statepathv2, "w")
   161         f = self._repo.opener(self.statepathv2, "w")
   142         for key, data in records:
   162         for key, data in records:
   143             assert len(key) == 1
   163             assert len(key) == 1
   145             f.write(_pack(format, key, len(data), data))
   165             f.write(_pack(format, key, len(data), data))
   146         f.close()
   166         f.close()
   147     def add(self, fcl, fco, fca, fd):
   167     def add(self, fcl, fco, fca, fd):
   148         hash = util.sha1(fcl.path()).hexdigest()
   168         hash = util.sha1(fcl.path()).hexdigest()
   149         self._repo.opener.write("merge/" + hash, fcl.data())
   169         self._repo.opener.write("merge/" + hash, fcl.data())
   150         self._state[fd] = ['u', hash, fcl.path(), fca.path(),
   170         self._state[fd] = ['u', hash, fcl.path(),
   151                            hex(fca.filenode()), fco.path(), fcl.flags()]
   171                            fca.path(), hex(fca.filenode()),
       
   172                            fco.path(), hex(fco.filenode()),
       
   173                            fcl.flags()]
   152         self._dirty = True
   174         self._dirty = True
   153     def __contains__(self, dfile):
   175     def __contains__(self, dfile):
   154         return dfile in self._state
   176         return dfile in self._state
   155     def __getitem__(self, dfile):
   177     def __getitem__(self, dfile):
   156         return self._state[dfile][0]
   178         return self._state[dfile][0]
   165         self._state[dfile][0] = state
   187         self._state[dfile][0] = state
   166         self._dirty = True
   188         self._dirty = True
   167     def resolve(self, dfile, wctx, octx):
   189     def resolve(self, dfile, wctx, octx):
   168         if self[dfile] == 'r':
   190         if self[dfile] == 'r':
   169             return 0
   191             return 0
   170         state, hash, lfile, afile, anode, ofile, flags = self._state[dfile]
   192         stateentry = self._state[dfile]
       
   193         state, hash, lfile, afile, anode, ofile, onode, flags = stateentry
   171         fcd = wctx[dfile]
   194         fcd = wctx[dfile]
   172         fco = octx[ofile]
   195         fco = octx[ofile]
   173         fca = self._repo.filectx(afile, fileid=anode)
   196         fca = self._repo.filectx(afile, fileid=anode)
   174         # "premerge" x flags
   197         # "premerge" x flags
   175         flo = fco.flags()
   198         flo = fco.flags()