mercurial/patch.py
changeset 4898 bc905a6c0e76
parent 4897 4574925db5c0
child 4899 1b7bbc4349e7
equal deleted inserted replaced
4897:4574925db5c0 4898:bc905a6c0e76
   220     if cwd:
   220     if cwd:
   221         curdir = os.getcwd()
   221         curdir = os.getcwd()
   222         os.chdir(cwd)
   222         os.chdir(cwd)
   223     try:
   223     try:
   224         ret = applydiff(ui, fp, files, strip=strip)
   224         ret = applydiff(ui, fp, files, strip=strip)
   225     except PatchError:
   225     except PatchError, err:
       
   226         ui.debug(err)
   226         raise util.Abort(_("patch failed to apply"))
   227         raise util.Abort(_("patch failed to apply"))
   227     if cwd:
   228     if cwd:
   228         os.chdir(curdir)
   229         os.chdir(curdir)
   229     if ret < 0:
   230     if ret < 0:
   230         raise util.Abort(_("patch failed to apply"))
   231         raise util.Abort(_("patch failed to apply"))
   267     def printfile(self, warn):
   268     def printfile(self, warn):
   268         if self.fileprinted:
   269         if self.fileprinted:
   269             return
   270             return
   270         if warn or self.ui.verbose:
   271         if warn or self.ui.verbose:
   271             self.fileprinted = True
   272             self.fileprinted = True
   272         s = _("patching file %s\n" % self.fname)
   273         s = _("patching file %s\n") % self.fname
   273         if warn:
   274         if warn:
   274             self.ui.warn(s)
   275             self.ui.warn(s)
   275         else:
   276         else:
   276             self.ui.note(s)
   277             self.ui.note(s)
   277 
   278 
   314         else:
   315         else:
   315             hunkstr = ""
   316             hunkstr = ""
   316 
   317 
   317         fname = self.fname + ".rej"
   318         fname = self.fname + ".rej"
   318         self.ui.warn(
   319         self.ui.warn(
   319                  _("%d out of %d hunk%s FAILED -- saving rejects to file %s\n" %
   320             _("%d out of %d hunk%s FAILED -- saving rejects to file %s\n") %
   320                  (len(self.rej), self.hunks, hunkstr, fname)))
   321             (len(self.rej), self.hunks, hunkstr, fname))
   321         try: os.unlink(fname)
   322         try: os.unlink(fname)
   322         except:
   323         except:
   323             pass
   324             pass
   324         fp = file(fname, 'w')
   325         fp = file(fname, 'w')
   325         base = os.path.basename(self.fname)
   326         base = os.path.basename(self.fname)
   350         self.write()
   351         self.write()
   351         self.write_rej()
   352         self.write_rej()
   352 
   353 
   353     def apply(self, h, reverse):
   354     def apply(self, h, reverse):
   354         if not h.complete():
   355         if not h.complete():
   355             raise PatchError("bad hunk #%d %s (%d %d %d %d)" %
   356             raise PatchError(_("bad hunk #%d %s (%d %d %d %d)") %
   356                             (h.number, h.desc, len(h.a), h.lena, len(h.b),
   357                             (h.number, h.desc, len(h.a), h.lena, len(h.b),
   357                             h.lenb))
   358                             h.lenb))
   358 
   359 
   359         self.hunks += 1
   360         self.hunks += 1
   360         if reverse:
   361         if reverse:
   361             h.reverse()
   362             h.reverse()
   362 
   363 
   363         if self.exists and h.createfile():
   364         if self.exists and h.createfile():
   364             self.ui.warn(_("file %s already exists\n" % self.fname))
   365             self.ui.warn(_("file %s already exists\n") % self.fname)
   365             self.rej.append(h)
   366             self.rej.append(h)
   366             return -1
   367             return -1
   367 
   368 
   368         if isinstance(h, binhunk):
   369         if isinstance(h, binhunk):
   369             if h.rmfile():
   370             if h.rmfile():
   421                         offset = l - orig_start - fuzzlen
   422                         offset = l - orig_start - fuzzlen
   422                         if offset == 1:
   423                         if offset == 1:
   423                             linestr = "line"
   424                             linestr = "line"
   424                         else:
   425                         else:
   425                             linestr = "lines"
   426                             linestr = "lines"
   426                         f(_("Hunk #%d succeeded at %d %s(offset %d %s).\n" %
   427                         f(_("Hunk #%d succeeded at %d %s(offset %d %s).\n") %
   427                            (h.number, l+1, fuzzstr, offset, linestr)))
   428                           (h.number, l+1, fuzzstr, offset, linestr))
   428                         return fuzzlen
   429                         return fuzzlen
   429         self.printfile(True)
   430         self.printfile(True)
   430         self.ui.warn(_("Hunk #%d FAILED at %d\n" % (h.number, orig_start)))
   431         self.ui.warn(_("Hunk #%d FAILED at %d\n") % (h.number, orig_start))
   431         self.rej.append(h)
   432         self.rej.append(h)
   432         return -1
   433         return -1
   433 
   434 
   434 class hunk:
   435 class hunk:
   435     def __init__(self, desc, num, lr, context):
   436     def __init__(self, desc, num, lr, context):
   444             self.read_unified_hunk(lr)
   445             self.read_unified_hunk(lr)
   445 
   446 
   446     def read_unified_hunk(self, lr):
   447     def read_unified_hunk(self, lr):
   447         m = unidesc.match(self.desc)
   448         m = unidesc.match(self.desc)
   448         if not m:
   449         if not m:
   449             raise PatchError("bad hunk #%d" % self.number)
   450             raise PatchError(_("bad hunk #%d") % self.number)
   450         self.starta, foo, self.lena, self.startb, foo2, self.lenb = m.groups()
   451         self.starta, foo, self.lena, self.startb, foo2, self.lenb = m.groups()
   451         if self.lena == None:
   452         if self.lena == None:
   452             self.lena = 1
   453             self.lena = 1
   453         else:
   454         else:
   454             self.lena = int(self.lena)
   455             self.lena = int(self.lena)
   470 
   471 
   471     def read_context_hunk(self, lr):
   472     def read_context_hunk(self, lr):
   472         self.desc = lr.readline()
   473         self.desc = lr.readline()
   473         m = contextdesc.match(self.desc)
   474         m = contextdesc.match(self.desc)
   474         if not m:
   475         if not m:
   475             raise PatchError("bad hunk #%d" % self.number)
   476             raise PatchError(_("bad hunk #%d") % self.number)
   476         foo, self.starta, foo2, aend, foo3 = m.groups()
   477         foo, self.starta, foo2, aend, foo3 = m.groups()
   477         self.starta = int(self.starta)
   478         self.starta = int(self.starta)
   478         if aend == None:
   479         if aend == None:
   479             aend = self.starta
   480             aend = self.starta
   480         self.lena = int(aend) - self.starta
   481         self.lena = int(aend) - self.starta
   489             if l.startswith('- ') or l.startswith('! '):
   490             if l.startswith('- ') or l.startswith('! '):
   490                 u = '-' + s
   491                 u = '-' + s
   491             elif l.startswith('  '):
   492             elif l.startswith('  '):
   492                 u = ' ' + s
   493                 u = ' ' + s
   493             else:
   494             else:
   494                 raise PatchError("bad hunk #%d old text line %d" % (self.number, x))
   495                 raise PatchError(_("bad hunk #%d old text line %d") %
       
   496                                  (self.number, x))
   495             self.a.append(u)
   497             self.a.append(u)
   496             self.hunk.append(u)
   498             self.hunk.append(u)
   497 
   499 
   498         l = lr.readline()
   500         l = lr.readline()
   499         if l.startswith('\ '):
   501         if l.startswith('\ '):
   501             self.a[-1] = s
   503             self.a[-1] = s
   502             self.hunk[-1] = s
   504             self.hunk[-1] = s
   503             l = lr.readline()
   505             l = lr.readline()
   504         m = contextdesc.match(l)
   506         m = contextdesc.match(l)
   505         if not m:
   507         if not m:
   506             raise PatchError("bad hunk #%d" % self.number)
   508             raise PatchError(_("bad hunk #%d") % self.number)
   507         foo, self.startb, foo2, bend, foo3 = m.groups()
   509         foo, self.startb, foo2, bend, foo3 = m.groups()
   508         self.startb = int(self.startb)
   510         self.startb = int(self.startb)
   509         if bend == None:
   511         if bend == None:
   510             bend = self.startb
   512             bend = self.startb
   511         self.lenb = int(bend) - self.startb
   513         self.lenb = int(bend) - self.startb
   530             elif len(self.b) == 0:
   532             elif len(self.b) == 0:
   531                 # this can happen when the hunk does not add any lines
   533                 # this can happen when the hunk does not add any lines
   532                 lr.push(l)
   534                 lr.push(l)
   533                 break
   535                 break
   534             else:
   536             else:
   535                 raise PatchError("bad hunk #%d old text line %d" % (self.number, x))
   537                 raise PatchError(_("bad hunk #%d old text line %d") %
       
   538                                  (self.number, x))
   536             self.b.append(s)
   539             self.b.append(s)
   537             while True:
   540             while True:
   538                 if hunki >= len(self.hunk):
   541                 if hunki >= len(self.hunk):
   539                     h = ""
   542                     h = ""
   540                 else:
   543                 else:
   674         self.hunk.append(line)
   677         self.hunk.append(line)
   675         while line and not line.startswith('literal '):
   678         while line and not line.startswith('literal '):
   676             line = fp.readline()
   679             line = fp.readline()
   677             self.hunk.append(line)
   680             self.hunk.append(line)
   678         if not line:
   681         if not line:
   679             raise PatchError('could not extract binary patch')
   682             raise PatchError(_('could not extract binary patch'))
   680         size = int(line[8:].rstrip())
   683         size = int(line[8:].rstrip())
   681         dec = []
   684         dec = []
   682         line = fp.readline()
   685         line = fp.readline()
   683         self.hunk.append(line)
   686         self.hunk.append(line)
   684         while len(line) > 1:
   687         while len(line) > 1:
   690             dec.append(base85.b85decode(line[1:-1])[:l])
   693             dec.append(base85.b85decode(line[1:-1])[:l])
   691             line = fp.readline()
   694             line = fp.readline()
   692             self.hunk.append(line)
   695             self.hunk.append(line)
   693         text = zlib.decompress(''.join(dec))
   696         text = zlib.decompress(''.join(dec))
   694         if len(text) != size:
   697         if len(text) != size:
   695             raise PatchError('binary patch is %d bytes, not %d' %
   698             raise PatchError(_('binary patch is %d bytes, not %d') %
   696                              len(text), size)
   699                              len(text), size)
   697         self.text = text
   700         self.text = text
   698 
   701 
   699 def parsefilename(str):
   702 def parsefilename(str):
   700     # --- filename \t|space stuff
   703     # --- filename \t|space stuff
   713         if count == 0:
   716         if count == 0:
   714             return path.rstrip()
   717             return path.rstrip()
   715         while count > 0:
   718         while count > 0:
   716             i = path.find(os.sep, i)
   719             i = path.find(os.sep, i)
   717             if i == -1:
   720             if i == -1:
   718                 raise PatchError("Unable to strip away %d dirs from %s" %
   721                 raise PatchError(_("unable to strip away %d dirs from %s") %
   719                                  (count, path))
   722                                  (count, path))
   720             i += 1
   723             i += 1
   721             # consume '//' in the path
   724             # consume '//' in the path
   722             while i < pathlen - 1 and path[i] == os.sep:
   725             while i < pathlen - 1 and path[i] == os.sep:
   723                 i += 1
   726                 i += 1
   735         goodb = os.path.exists(bfile) and not nullb
   738         goodb = os.path.exists(bfile) and not nullb
   736     createfunc = hunk.createfile
   739     createfunc = hunk.createfile
   737     if reverse:
   740     if reverse:
   738         createfunc = hunk.rmfile
   741         createfunc = hunk.rmfile
   739     if not goodb and not gooda and not createfunc():
   742     if not goodb and not gooda and not createfunc():
   740         raise PatchError(_("Unable to find %s or %s for patching\n" %
   743         raise PatchError(_("unable to find %s or %s for patching") %
   741                         (afile, bfile)))
   744                          (afile, bfile))
   742     if gooda and goodb:
   745     if gooda and goodb:
   743         fname = bfile
   746         fname = bfile
   744         if afile in bfile:
   747         if afile in bfile:
   745             fname = afile
   748             fname = afile
   746     elif gooda:
   749     elif gooda:
   833             ((context or context == None) and x.startswith('***************')))):
   836             ((context or context == None) and x.startswith('***************')))):
   834             try:
   837             try:
   835                 if context == None and x.startswith('***************'):
   838                 if context == None and x.startswith('***************'):
   836                     context = True
   839                     context = True
   837                 current_hunk = hunk(x, hunknum + 1, lr, context)
   840                 current_hunk = hunk(x, hunknum + 1, lr, context)
   838             except PatchError:
   841             except PatchError, err:
       
   842                 ui.debug(err)
   839                 current_hunk = None
   843                 current_hunk = None
   840                 continue
   844                 continue
   841             hunknum += 1
   845             hunknum += 1
   842             if not current_file:
   846             if not current_file:
   843                 if sourcefile:
   847                 if sourcefile:
   915             ret = current_file.apply(current_hunk, reverse)
   919             ret = current_file.apply(current_hunk, reverse)
   916             if ret > 0:
   920             if ret > 0:
   917                 err = 1
   921                 err = 1
   918         else:
   922         else:
   919             fname = current_file and current_file.fname or None
   923             fname = current_file and current_file.fname or None
   920             raise PatchError("malformed patch %s %s" % (fname,
   924             raise PatchError(_("malformed patch %s %s") % (fname,
   921                              current_hunk.desc))
   925                              current_hunk.desc))
   922     if current_file:
   926     if current_file:
   923         current_file.close()
   927         current_file.close()
   924         if rejmerge:
   928         if rejmerge:
   925             rejmerge(current_file)
   929             rejmerge(current_file)
   927     if updatedir and git:
   931     if updatedir and git:
   928         updatedir(gitpatches)
   932         updatedir(gitpatches)
   929     if rejects:
   933     if rejects:
   930         return -1
   934         return -1
   931     if hunknum == 0 and dopatch and not gitworkdone:
   935     if hunknum == 0 and dopatch and not gitworkdone:
   932         raise PatchError("No valid hunks found")
   936         raise PatchError(_("no valid hunks found"))
   933     return err
   937     return err
   934 
   938 
   935 def diffopts(ui, opts={}, untrusted=False):
   939 def diffopts(ui, opts={}, untrusted=False):
   936     def get(key, name=None):
   940     def get(key, name=None):
   937         return (opts.get(key) or
   941         return (opts.get(key) or