Mercurial > hg
comparison mercurial/patch.py @ 14370:17cea10c343e
patch: add a workingbackend dirstate layer on top of fsbackend
_updatedir() is no longer used by internalpatch()
The change in test-mq-missingfiles.t comes from workingbackend not considering
the missing 'b' file as changed, thus not calling addremove() on it.
author | Patrick Mezard <pmezard@gmail.com> |
---|---|
date | Wed, 18 May 2011 23:48:17 +0200 |
parents | f8932d540088 |
children | d4192500586a |
comparison
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): |