mercurial/patch.py
changeset 13699 d3c0e0033f13
parent 13395 104c9ed93fc5
child 13700 63307feb59dd
equal deleted inserted replaced
13698:f30ce5983896 13699:d3c0e0033f13
   678             del self.hunk[-1]
   678             del self.hunk[-1]
   679             del self.a[-1]
   679             del self.a[-1]
   680             del self.b[-1]
   680             del self.b[-1]
   681             self.lena -= 1
   681             self.lena -= 1
   682             self.lenb -= 1
   682             self.lenb -= 1
       
   683         self._fixnewline(lr)
   683 
   684 
   684     def read_context_hunk(self, lr):
   685     def read_context_hunk(self, lr):
   685         self.desc = lr.readline()
   686         self.desc = lr.readline()
   686         m = contextdesc.match(self.desc)
   687         m = contextdesc.match(self.desc)
   687         if not m:
   688         if not m:
   780                     self.b.append(x[1:])
   781                     self.b.append(x[1:])
   781         # @@ -start,len +start,len @@
   782         # @@ -start,len +start,len @@
   782         self.desc = "@@ -%d,%d +%d,%d @@\n" % (self.starta, self.lena,
   783         self.desc = "@@ -%d,%d +%d,%d @@\n" % (self.starta, self.lena,
   783                                              self.startb, self.lenb)
   784                                              self.startb, self.lenb)
   784         self.hunk[0] = self.desc
   785         self.hunk[0] = self.desc
   785 
   786         self._fixnewline(lr)
   786     def fix_newline(self):
   787 
   787         diffhelpers.fix_newline(self.hunk, self.a, self.b)
   788     def _fixnewline(self, lr):
       
   789         l = lr.readline()
       
   790         if l.startswith('\ '):
       
   791             diffhelpers.fix_newline(self.hunk, self.a, self.b)
       
   792         else:
       
   793             lr.push(l)
   788 
   794 
   789     def complete(self):
   795     def complete(self):
   790         return len(self.a) == self.lena and len(self.b) == self.lenb
   796         return len(self.a) == self.lena and len(self.b) == self.lenb
   791 
   797 
   792     def createfile(self):
   798     def createfile(self):
   991     "file" event.
   997     "file" event.
   992     - ("git", gitchanges): current diff is in git format, gitchanges
   998     - ("git", gitchanges): current diff is in git format, gitchanges
   993     maps filenames to gitpatch records. Unique event.
   999     maps filenames to gitpatch records. Unique event.
   994     """
  1000     """
   995     changed = {}
  1001     changed = {}
   996     current_hunk = None
       
   997     afile = ""
  1002     afile = ""
   998     bfile = ""
  1003     bfile = ""
   999     state = None
  1004     state = None
  1000     hunknum = 0
  1005     hunknum = 0
  1001     emitfile = False
  1006     emitfile = False
  1009     while True:
  1014     while True:
  1010         newfile = newgitfile = False
  1015         newfile = newgitfile = False
  1011         x = lr.readline()
  1016         x = lr.readline()
  1012         if not x:
  1017         if not x:
  1013             break
  1018             break
  1014         if current_hunk:
       
  1015             if x.startswith('\ '):
       
  1016                 current_hunk.fix_newline()
       
  1017             yield 'hunk', current_hunk
       
  1018             current_hunk = None
       
  1019         if (state == BFILE and ((not context and x[0] == '@') or
  1019         if (state == BFILE and ((not context and x[0] == '@') or
  1020             ((context is not False) and x.startswith('***************')))):
  1020             ((context is not False) and x.startswith('***************')))):
  1021             if context is None and x.startswith('***************'):
  1021             if context is None and x.startswith('***************'):
  1022                 context = True
  1022                 context = True
  1023             gpatch = changed.get(bfile)
  1023             gpatch = changed.get(bfile)
  1024             create = afile == '/dev/null' or gpatch and gpatch.op == 'ADD'
  1024             create = afile == '/dev/null' or gpatch and gpatch.op == 'ADD'
  1025             remove = bfile == '/dev/null' or gpatch and gpatch.op == 'DELETE'
  1025             remove = bfile == '/dev/null' or gpatch and gpatch.op == 'DELETE'
  1026             current_hunk = hunk(x, hunknum + 1, lr, context, create, remove)
  1026             h = hunk(x, hunknum + 1, lr, context, create, remove)
  1027             hunknum += 1
  1027             hunknum += 1
  1028             if emitfile:
  1028             if emitfile:
  1029                 emitfile = False
  1029                 emitfile = False
  1030                 yield 'file', (afile, bfile, current_hunk)
  1030                 yield 'file', (afile, bfile, h)
       
  1031             yield 'hunk', h
  1031         elif state == BFILE and x.startswith('GIT binary patch'):
  1032         elif state == BFILE and x.startswith('GIT binary patch'):
  1032             current_hunk = binhunk(changed[bfile])
  1033             h = binhunk(changed[bfile])
  1033             hunknum += 1
  1034             hunknum += 1
  1034             if emitfile:
  1035             if emitfile:
  1035                 emitfile = False
  1036                 emitfile = False
  1036                 yield 'file', ('a/' + afile, 'b/' + bfile, current_hunk)
  1037                 yield 'file', ('a/' + afile, 'b/' + bfile, h)
  1037             current_hunk.extract(lr)
  1038             h.extract(lr)
       
  1039             yield 'hunk', h
  1038         elif x.startswith('diff --git'):
  1040         elif x.startswith('diff --git'):
  1039             # check for git diff, scanning the whole patch file if needed
  1041             # check for git diff, scanning the whole patch file if needed
  1040             m = gitre.match(x)
  1042             m = gitre.match(x)
  1041             if m:
  1043             if m:
  1042                 afile, bfile = m.group(1, 2)
  1044                 afile, bfile = m.group(1, 2)
  1081 
  1083 
  1082         if newgitfile or newfile:
  1084         if newgitfile or newfile:
  1083             emitfile = True
  1085             emitfile = True
  1084             state = BFILE
  1086             state = BFILE
  1085             hunknum = 0
  1087             hunknum = 0
  1086     if current_hunk:
       
  1087         if current_hunk.complete():
       
  1088             yield 'hunk', current_hunk
       
  1089         else:
       
  1090             raise PatchError(_("malformed patch %s %s") % (afile,
       
  1091                              current_hunk.desc))
       
  1092 
  1088 
  1093 def applydiff(ui, fp, changed, strip=1, eolmode='strict'):
  1089 def applydiff(ui, fp, changed, strip=1, eolmode='strict'):
  1094     """Reads a patch from fp and tries to apply it.
  1090     """Reads a patch from fp and tries to apply it.
  1095 
  1091 
  1096     The dict 'changed' is filled in with all of the filenames changed
  1092     The dict 'changed' is filled in with all of the filenames changed