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: |