mercurial/patch.py
changeset 14370 17cea10c343e
parent 14369 f8932d540088
child 14381 d4192500586a
equal deleted inserted replaced
14369:f8932d540088 14370:17cea10c343e
   475     def exists(self, fname):
   475     def exists(self, fname):
   476         return os.path.lexists(self._join(fname))
   476         return os.path.lexists(self._join(fname))
   477 
   477 
   478     def setmode(self, fname, islink, isexec):
   478     def setmode(self, fname, islink, isexec):
   479         util.setflags(self._join(fname), islink, isexec)
   479         util.setflags(self._join(fname), islink, isexec)
       
   480 
       
   481 class workingbackend(fsbackend):
       
   482     def __init__(self, ui, repo, similarity):
       
   483         super(workingbackend, self).__init__(ui, repo.root)
       
   484         self.repo = repo
       
   485         self.similarity = similarity
       
   486         self.removed = set()
       
   487         self.changed = set()
       
   488         self.copied = []
       
   489 
       
   490     def writelines(self, fname, lines, mode):
       
   491         super(workingbackend, self).writelines(fname, lines, mode)
       
   492         self.changed.add(fname)
       
   493 
       
   494     def unlink(self, fname):
       
   495         super(workingbackend, self).unlink(fname)
       
   496         self.removed.add(fname)
       
   497         self.changed.add(fname)
       
   498 
       
   499     def copy(self, src, dst):
       
   500         super(workingbackend, self).copy(src, dst)
       
   501         self.copied.append((src, dst))
       
   502         self.changed.add(dst)
       
   503 
       
   504     def setmode(self, fname, islink, isexec):
       
   505         super(workingbackend, self).setmode(fname, islink, isexec)
       
   506         self.changed.add(fname)
       
   507 
       
   508     def close(self):
       
   509         wctx = self.repo[None]
       
   510         addremoved = set(self.changed)
       
   511         for src, dst in self.copied:
       
   512             scmutil.dirstatecopy(self.ui, self.repo, wctx, src, dst)
       
   513             addremoved.discard(src)
       
   514         if (not self.similarity) and self.removed:
       
   515             wctx.remove(sorted(self.removed))
       
   516         if addremoved:
       
   517             cwd = self.repo.getcwd()
       
   518             if cwd:
       
   519                 addremoved = [util.pathto(self.repo.root, cwd, f)
       
   520                               for f in addremoved]
       
   521             scmutil.addremove(self.repo, addremoved, similarity=self.similarity)
       
   522         return sorted(self.changed)
   480 
   523 
   481 # @@ -start,len +start,len @@ or @@ -start +start @@ if len is 1
   524 # @@ -start,len +start,len @@ or @@ -start +start @@ if len is 1
   482 unidesc = re.compile('@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@')
   525 unidesc = re.compile('@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@')
   483 contextdesc = re.compile('(---|\*\*\*) (\d+)(,(\d+))? (---|\*\*\*)')
   526 contextdesc = re.compile('(---|\*\*\*) (\d+)(,(\d+))? (---|\*\*\*)')
   484 eolmodes = ['strict', 'crlf', 'lf', 'auto']
   527 eolmodes = ['strict', 'crlf', 'lf', 'auto']
  1167     found and 1 if there was any fuzz.
  1210     found and 1 if there was any fuzz.
  1168 
  1211 
  1169     If 'eolmode' is 'strict', the patch content and patched file are
  1212     If 'eolmode' is 'strict', the patch content and patched file are
  1170     read in binary mode. Otherwise, line endings are ignored when
  1213     read in binary mode. Otherwise, line endings are ignored when
  1171     patching then normalized according to 'eolmode'.
  1214     patching then normalized according to 'eolmode'.
  1172 
       
  1173     Callers probably want to call '_updatedir' after this to
       
  1174     apply certain categories of changes not done by this function.
       
  1175     """
  1215     """
  1176     return _applydiff(ui, fp, patchfile, backend, changed, strip=strip,
  1216     return _applydiff(ui, fp, patchfile, backend, changed, strip=strip,
  1177                       eolmode=eolmode)
  1217                       eolmode=eolmode)
  1178 
  1218 
  1179 def _applydiff(ui, fp, patcher, backend, changed, strip=1, eolmode='strict'):
  1219 def _applydiff(ui, fp, patcher, backend, changed, strip=1, eolmode='strict'):
  1309     if code:
  1349     if code:
  1310         raise PatchError(_("patch command failed: %s") %
  1350         raise PatchError(_("patch command failed: %s") %
  1311                          util.explainexit(code)[0])
  1351                          util.explainexit(code)[0])
  1312     return fuzz
  1352     return fuzz
  1313 
  1353 
  1314 def internalpatch(ui, repo, patchobj, strip, cwd, files=None, eolmode='strict',
  1354 def internalpatch(ui, repo, patchobj, strip, files=None, eolmode='strict',
  1315                   similarity=0):
  1355                   similarity=0):
  1316     """use builtin patch to apply <patchobj> to the working directory.
  1356     """use builtin patch to apply <patchobj> to the working directory.
  1317     returns whether patch was applied with fuzz factor."""
  1357     returns whether patch was applied with fuzz factor."""
  1318 
  1358 
  1319     if files is None:
  1359     if files is None:
  1322         eolmode = ui.config('patch', 'eol', 'strict')
  1362         eolmode = ui.config('patch', 'eol', 'strict')
  1323     if eolmode.lower() not in eolmodes:
  1363     if eolmode.lower() not in eolmodes:
  1324         raise util.Abort(_('unsupported line endings type: %s') % eolmode)
  1364         raise util.Abort(_('unsupported line endings type: %s') % eolmode)
  1325     eolmode = eolmode.lower()
  1365     eolmode = eolmode.lower()
  1326 
  1366 
  1327     backend = fsbackend(ui, cwd)
  1367     backend = workingbackend(ui, repo, similarity)
  1328     try:
  1368     try:
  1329         fp = open(patchobj, 'rb')
  1369         fp = open(patchobj, 'rb')
  1330     except TypeError:
  1370     except TypeError:
  1331         fp = patchobj
  1371         fp = patchobj
  1332     try:
  1372     try:
  1333         ret = applydiff(ui, fp, files, backend, strip=strip, eolmode=eolmode)
  1373         ret = applydiff(ui, fp, files, backend, strip=strip, eolmode=eolmode)
  1334     finally:
  1374     finally:
  1335         if fp != patchobj:
  1375         if fp != patchobj:
  1336             fp.close()
  1376             fp.close()
  1337         touched = _updatedir(ui, repo, files, similarity)
  1377         files.update(dict.fromkeys(backend.close()))
  1338         files.update(dict.fromkeys(touched))
       
  1339     if ret < 0:
  1378     if ret < 0:
  1340         raise PatchError(_('patch failed to apply'))
  1379         raise PatchError(_('patch failed to apply'))
  1341     return ret > 0
  1380     return ret > 0
  1342 
  1381 
  1343 def patch(ui, repo, patchname, strip=1, cwd=None, files=None, eolmode='strict',
  1382 def patch(ui, repo, patchname, strip=1, cwd=None, files=None, eolmode='strict',
  1362                 return _externalpatch(patcher, patchname, ui, strip, cwd,
  1401                 return _externalpatch(patcher, patchname, ui, strip, cwd,
  1363                                       files)
  1402                                       files)
  1364             finally:
  1403             finally:
  1365                 touched = _updatedir(ui, repo, files, similarity)
  1404                 touched = _updatedir(ui, repo, files, similarity)
  1366                 files.update(dict.fromkeys(touched))
  1405                 files.update(dict.fromkeys(touched))
  1367         return internalpatch(ui, repo, patchname, strip, cwd, files, eolmode,
  1406         return internalpatch(ui, repo, patchname, strip, files, eolmode,
  1368                              similarity)
  1407                              similarity)
  1369     except PatchError, err:
  1408     except PatchError, err:
  1370         raise util.Abort(str(err))
  1409         raise util.Abort(str(err))
  1371 
  1410 
  1372 def changedfiles(ui, repo, patchpath, strip=1):
  1411 def changedfiles(ui, repo, patchpath, strip=1):