mercurial/patch.py
changeset 14366 992a7e398ddd
parent 14352 077cdf172580
child 14367 468d7d1744b4
equal deleted inserted replaced
14365:a8e3931e3fb5 14366:992a7e398ddd
   400 class fsbackend(abstractbackend):
   400 class fsbackend(abstractbackend):
   401     def __init__(self, ui, basedir):
   401     def __init__(self, ui, basedir):
   402         super(fsbackend, self).__init__(ui)
   402         super(fsbackend, self).__init__(ui)
   403         self.opener = scmutil.opener(basedir)
   403         self.opener = scmutil.opener(basedir)
   404 
   404 
       
   405     def _join(self, f):
       
   406         return os.path.join(self.opener.base, f)
       
   407 
   405     def readlines(self, fname):
   408     def readlines(self, fname):
   406         if os.path.islink(fname):
   409         if os.path.islink(self._join(fname)):
   407             return [os.readlink(fname)]
   410             return [os.readlink(self._join(fname))]
   408         fp = self.opener(fname, 'r')
   411         fp = self.opener(fname, 'r')
   409         try:
   412         try:
   410             return list(fp)
   413             return list(fp)
   411         finally:
   414         finally:
   412             fp.close()
   415             fp.close()
   414     def writelines(self, fname, lines):
   417     def writelines(self, fname, lines):
   415         # Ensure supplied data ends in fname, being a regular file or
   418         # Ensure supplied data ends in fname, being a regular file or
   416         # a symlink. _updatedir will -too magically- take care
   419         # a symlink. _updatedir will -too magically- take care
   417         # of setting it to the proper type afterwards.
   420         # of setting it to the proper type afterwards.
   418         st_mode = None
   421         st_mode = None
   419         islink = os.path.islink(fname)
   422         islink = os.path.islink(self._join(fname))
   420         if islink:
   423         if islink:
   421             fp = cStringIO.StringIO()
   424             fp = cStringIO.StringIO()
   422         else:
   425         else:
   423             try:
   426             try:
   424                 st_mode = os.lstat(fname).st_mode & 0777
   427                 st_mode = os.lstat(self._join(fname)).st_mode & 0777
   425             except OSError, e:
   428             except OSError, e:
   426                 if e.errno != errno.ENOENT:
   429                 if e.errno != errno.ENOENT:
   427                     raise
   430                     raise
   428             fp = self.opener(fname, 'w')
   431             fp = self.opener(fname, 'w')
   429         try:
   432         try:
   430             fp.writelines(lines)
   433             fp.writelines(lines)
   431             if islink:
   434             if islink:
   432                 self.opener.symlink(fp.getvalue(), fname)
   435                 self.opener.symlink(fp.getvalue(), fname)
   433             if st_mode is not None:
   436             if st_mode is not None:
   434                 os.chmod(fname, st_mode)
   437                 os.chmod(self._join(fname), st_mode)
   435         finally:
   438         finally:
   436             fp.close()
   439             fp.close()
   437 
   440 
   438     def unlink(self, fname):
   441     def unlink(self, fname):
   439         os.unlink(fname)
   442         os.unlink(self._join(fname))
   440 
   443 
   441     def writerej(self, fname, failed, total, lines):
   444     def writerej(self, fname, failed, total, lines):
   442         fname = fname + ".rej"
   445         fname = fname + ".rej"
   443         self.ui.warn(
   446         self.ui.warn(
   444             _("%d out of %d hunks FAILED -- saving rejects to file %s\n") %
   447             _("%d out of %d hunks FAILED -- saving rejects to file %s\n") %
   463                     _("cannot create %s: unable to create destination directory")
   466                     _("cannot create %s: unable to create destination directory")
   464                     % dst)
   467                     % dst)
   465         util.copyfile(abssrc, absdst)
   468         util.copyfile(abssrc, absdst)
   466 
   469 
   467     def exists(self, fname):
   470     def exists(self, fname):
   468         return os.path.lexists(fname)
   471         return os.path.lexists(self._join(fname))
   469 
   472 
   470 # @@ -start,len +start,len @@ or @@ -start +start @@ if len is 1
   473 # @@ -start,len +start,len @@ or @@ -start +start @@ if len is 1
   471 unidesc = re.compile('@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@')
   474 unidesc = re.compile('@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@')
   472 contextdesc = re.compile('(---|\*\*\*) (\d+)(,(\d+))? (---|\*\*\*)')
   475 contextdesc = re.compile('(---|\*\*\*) (\d+)(,(\d+))? (---|\*\*\*)')
   473 eolmodes = ['strict', 'crlf', 'lf', 'auto']
   476 eolmodes = ['strict', 'crlf', 'lf', 'auto']
  1142             newfile = False
  1145             newfile = False
  1143             emitfile = True
  1146             emitfile = True
  1144             state = BFILE
  1147             state = BFILE
  1145             hunknum = 0
  1148             hunknum = 0
  1146 
  1149 
  1147 def applydiff(ui, fp, changed, strip=1, eolmode='strict'):
  1150 def applydiff(ui, fp, changed, backend, strip=1, eolmode='strict'):
  1148     """Reads a patch from fp and tries to apply it.
  1151     """Reads a patch from fp and tries to apply it.
  1149 
  1152 
  1150     The dict 'changed' is filled in with all of the filenames changed
  1153     The dict 'changed' is filled in with all of the filenames changed
  1151     by the patch. Returns 0 for a clean patch, -1 if any rejects were
  1154     by the patch. Returns 0 for a clean patch, -1 if any rejects were
  1152     found and 1 if there was any fuzz.
  1155     found and 1 if there was any fuzz.
  1156     patching then normalized according to 'eolmode'.
  1159     patching then normalized according to 'eolmode'.
  1157 
  1160 
  1158     Callers probably want to call '_updatedir' after this to
  1161     Callers probably want to call '_updatedir' after this to
  1159     apply certain categories of changes not done by this function.
  1162     apply certain categories of changes not done by this function.
  1160     """
  1163     """
  1161     return _applydiff(ui, fp, patchfile, changed, strip=strip,
  1164     return _applydiff(ui, fp, patchfile, backend, changed, strip=strip,
  1162                       eolmode=eolmode)
  1165                       eolmode=eolmode)
  1163 
  1166 
  1164 def _applydiff(ui, fp, patcher, changed, strip=1, eolmode='strict'):
  1167 def _applydiff(ui, fp, patcher, backend, changed, strip=1, eolmode='strict'):
  1165     rejects = 0
  1168     rejects = 0
  1166     err = 0
  1169     err = 0
  1167     current_file = None
  1170     current_file = None
  1168     backend = fsbackend(ui, os.getcwd())
       
  1169 
  1171 
  1170     for state, values in iterhunks(fp):
  1172     for state, values in iterhunks(fp):
  1171         if state == 'hunk':
  1173         if state == 'hunk':
  1172             if not current_file:
  1174             if not current_file:
  1173                 continue
  1175                 continue
  1301         eolmode = ui.config('patch', 'eol', 'strict')
  1303         eolmode = ui.config('patch', 'eol', 'strict')
  1302     if eolmode.lower() not in eolmodes:
  1304     if eolmode.lower() not in eolmodes:
  1303         raise util.Abort(_('unsupported line endings type: %s') % eolmode)
  1305         raise util.Abort(_('unsupported line endings type: %s') % eolmode)
  1304     eolmode = eolmode.lower()
  1306     eolmode = eolmode.lower()
  1305 
  1307 
       
  1308     backend = fsbackend(ui, cwd)
  1306     try:
  1309     try:
  1307         fp = open(patchobj, 'rb')
  1310         fp = open(patchobj, 'rb')
  1308     except TypeError:
  1311     except TypeError:
  1309         fp = patchobj
  1312         fp = patchobj
  1310     if cwd:
       
  1311         curdir = os.getcwd()
       
  1312         os.chdir(cwd)
       
  1313     try:
  1313     try:
  1314         ret = applydiff(ui, fp, files, strip=strip, eolmode=eolmode)
  1314         ret = applydiff(ui, fp, files, backend, strip=strip, eolmode=eolmode)
  1315     finally:
  1315     finally:
  1316         if cwd:
       
  1317             os.chdir(curdir)
       
  1318         if fp != patchobj:
  1316         if fp != patchobj:
  1319             fp.close()
  1317             fp.close()
  1320         touched = _updatedir(ui, repo, files, similarity)
  1318         touched = _updatedir(ui, repo, files, similarity)
  1321         files.update(dict.fromkeys(touched))
  1319         files.update(dict.fromkeys(touched))
  1322     if ret < 0:
  1320     if ret < 0: