##// END OF EJS Templates
patch: extract fs access from patchfile into fsbackend...
Patrick Mezard -
r14348:c1c71910 default
parent child Browse files
Show More
@@ -595,11 +595,11 b' def reposetup(ui, repo):'
595 wlock.release()
595 wlock.release()
596
596
597 # monkeypatches
597 # monkeypatches
598 def kwpatchfile_init(orig, self, ui, fname, opener,
598 def kwpatchfile_init(orig, self, ui, fname, backend,
599 missing=False, eolmode=None):
599 missing=False, eolmode=None):
600 '''Monkeypatch/wrap patch.patchfile.__init__ to avoid
600 '''Monkeypatch/wrap patch.patchfile.__init__ to avoid
601 rejects or conflicts due to expanded keywords in working dir.'''
601 rejects or conflicts due to expanded keywords in working dir.'''
602 orig(self, ui, fname, opener, missing, eolmode)
602 orig(self, ui, fname, backend, missing, eolmode)
603 # shrink keywords read from working dir
603 # shrink keywords read from working dir
604 self.lines = kwt.shrinklines(self.fname, self.lines)
604 self.lines = kwt.shrinklines(self.fname, self.lines)
605
605
@@ -381,48 +381,42 b' class linereader(object):'
381 break
381 break
382 yield l
382 yield l
383
383
384 # @@ -start,len +start,len @@ or @@ -start +start @@ if len is 1
384 class abstractbackend(object):
385 unidesc = re.compile('@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@')
385 def __init__(self, ui):
386 contextdesc = re.compile('(---|\*\*\*) (\d+)(,(\d+))? (---|\*\*\*)')
387 eolmodes = ['strict', 'crlf', 'lf', 'auto']
388
389 class patchfile(object):
390 def __init__(self, ui, fname, opener, missing=False, eolmode='strict'):
391 self.fname = fname
392 self.eolmode = eolmode
393 self.eol = None
394 self.opener = opener
395 self.ui = ui
386 self.ui = ui
396 self.lines = []
387
397 self.exists = False
388 def readlines(self, fname):
398 self.missing = missing
389 """Return target file lines, or its content as a single line
399 if not missing:
390 for symlinks.
400 try:
391 """
401 self.lines = self.readlines(fname)
392 raise NotImplementedError
402 self.exists = True
393
403 except IOError:
394 def writelines(self, fname, lines):
404 pass
395 """Write lines to target file."""
405 else:
396 raise NotImplementedError
406 self.ui.warn(_("unable to find '%s' for patching\n") % self.fname)
407
397
408 self.hash = {}
398 def unlink(self, fname):
409 self.dirty = False
399 """Unlink target file."""
410 self.offset = 0
400 raise NotImplementedError
411 self.skew = 0
401
412 self.rej = []
402 def writerej(self, fname, failed, total, lines):
413 self.fileprinted = False
403 """Write rejected lines for fname. total is the number of hunks
414 self.printfile(False)
404 which failed to apply and total the total number of hunks for this
415 self.hunks = 0
405 files.
406 """
407 pass
408
409 class fsbackend(abstractbackend):
410 def __init__(self, ui, opener):
411 super(fsbackend, self).__init__(ui)
412 self.opener = opener
416
413
417 def readlines(self, fname):
414 def readlines(self, fname):
418 if os.path.islink(fname):
415 if os.path.islink(fname):
419 return [os.readlink(fname)]
416 return [os.readlink(fname)]
420 fp = self.opener(fname, 'r')
417 fp = self.opener(fname, 'r')
421 try:
418 try:
422 lr = linereader(fp, self.eolmode != 'strict')
419 return list(fp)
423 lines = list(lr)
424 self.eol = lr.eol
425 return lines
426 finally:
420 finally:
427 fp.close()
421 fp.close()
428
422
@@ -442,20 +436,7 b' class patchfile(object):'
442 raise
436 raise
443 fp = self.opener(fname, 'w')
437 fp = self.opener(fname, 'w')
444 try:
438 try:
445 if self.eolmode == 'auto':
439 fp.writelines(lines)
446 eol = self.eol
447 elif self.eolmode == 'crlf':
448 eol = '\r\n'
449 else:
450 eol = '\n'
451
452 if self.eolmode != 'strict' and eol and eol != '\n':
453 for l in lines:
454 if l and l[-1] == '\n':
455 l = l[:-1] + eol
456 fp.write(l)
457 else:
458 fp.writelines(lines)
459 if islink:
440 if islink:
460 self.opener.symlink(fp.getvalue(), fname)
441 self.opener.symlink(fp.getvalue(), fname)
461 if st_mode is not None:
442 if st_mode is not None:
@@ -466,6 +447,79 b' class patchfile(object):'
466 def unlink(self, fname):
447 def unlink(self, fname):
467 os.unlink(fname)
448 os.unlink(fname)
468
449
450 def writerej(self, fname, failed, total, lines):
451 fname = fname + ".rej"
452 self.ui.warn(
453 _("%d out of %d hunks FAILED -- saving rejects to file %s\n") %
454 (failed, total, fname))
455 fp = self.opener(fname, 'w')
456 fp.writelines(lines)
457 fp.close()
458
459 # @@ -start,len +start,len @@ or @@ -start +start @@ if len is 1
460 unidesc = re.compile('@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@')
461 contextdesc = re.compile('(---|\*\*\*) (\d+)(,(\d+))? (---|\*\*\*)')
462 eolmodes = ['strict', 'crlf', 'lf', 'auto']
463
464 class patchfile(object):
465 def __init__(self, ui, fname, backend, missing=False, eolmode='strict'):
466 self.fname = fname
467 self.eolmode = eolmode
468 self.eol = None
469 self.backend = backend
470 self.ui = ui
471 self.lines = []
472 self.exists = False
473 self.missing = missing
474 if not missing:
475 try:
476 self.lines = self.backend.readlines(fname)
477 if self.lines:
478 # Normalize line endings
479 if self.lines[0].endswith('\r\n'):
480 self.eol = '\r\n'
481 elif self.lines[0].endswith('\n'):
482 self.eol = '\n'
483 if eolmode != 'strict':
484 nlines = []
485 for l in self.lines:
486 if l.endswith('\r\n'):
487 l = l[:-2] + '\n'
488 nlines.append(l)
489 self.lines = nlines
490 self.exists = True
491 except IOError:
492 pass
493 else:
494 self.ui.warn(_("unable to find '%s' for patching\n") % self.fname)
495
496 self.hash = {}
497 self.dirty = 0
498 self.offset = 0
499 self.skew = 0
500 self.rej = []
501 self.fileprinted = False
502 self.printfile(False)
503 self.hunks = 0
504
505 def writelines(self, fname, lines):
506 if self.eolmode == 'auto':
507 eol = self.eol
508 elif self.eolmode == 'crlf':
509 eol = '\r\n'
510 else:
511 eol = '\n'
512
513 if self.eolmode != 'strict' and eol and eol != '\n':
514 rawlines = []
515 for l in lines:
516 if l and l[-1] == '\n':
517 l = l[:-1] + eol
518 rawlines.append(l)
519 lines = rawlines
520
521 self.backend.writelines(fname, lines)
522
469 def printfile(self, warn):
523 def printfile(self, warn):
470 if self.fileprinted:
524 if self.fileprinted:
471 return
525 return
@@ -503,18 +557,10 b' class patchfile(object):'
503 # creates rejects in the same form as the original patch. A file
557 # creates rejects in the same form as the original patch. A file
504 # header is inserted so that you can run the reject through patch again
558 # header is inserted so that you can run the reject through patch again
505 # without having to type the filename.
559 # without having to type the filename.
506
507 if not self.rej:
560 if not self.rej:
508 return
561 return
509
562 self.backend.writerej(self.fname, len(self.rej), self.hunks,
510 fname = self.fname + ".rej"
563 self.makerejlines(self.fname))
511 self.ui.warn(
512 _("%d out of %d hunks FAILED -- saving rejects to file %s\n") %
513 (len(self.rej), self.hunks, fname))
514
515 fp = self.opener(fname, 'w')
516 fp.writelines(self.makerejlines(self.fname))
517 fp.close()
518
564
519 def apply(self, h):
565 def apply(self, h):
520 if not h.complete():
566 if not h.complete():
@@ -535,7 +581,7 b' class patchfile(object):'
535
581
536 if isinstance(h, binhunk):
582 if isinstance(h, binhunk):
537 if h.rmfile():
583 if h.rmfile():
538 self.unlink(self.fname)
584 self.backend.unlink(self.fname)
539 else:
585 else:
540 self.lines[:] = h.new()
586 self.lines[:] = h.new()
541 self.offset += len(h.new())
587 self.offset += len(h.new())
@@ -563,7 +609,7 b' class patchfile(object):'
563 # fast case code
609 # fast case code
564 if self.skew == 0 and diffhelpers.testhunk(old, self.lines, start) == 0:
610 if self.skew == 0 and diffhelpers.testhunk(old, self.lines, start) == 0:
565 if h.rmfile():
611 if h.rmfile():
566 self.unlink(self.fname)
612 self.backend.unlink(self.fname)
567 else:
613 else:
568 self.lines[start : start + h.lena] = h.new()
614 self.lines[start : start + h.lena] = h.new()
569 self.offset += h.lenb - h.lena
615 self.offset += h.lenb - h.lena
@@ -1112,7 +1158,7 b' def _applydiff(ui, fp, patcher, copyfn, '
1112 err = 0
1158 err = 0
1113 current_file = None
1159 current_file = None
1114 cwd = os.getcwd()
1160 cwd = os.getcwd()
1115 opener = scmutil.opener(cwd)
1161 backend = fsbackend(ui, scmutil.opener(cwd))
1116
1162
1117 for state, values in iterhunks(fp):
1163 for state, values in iterhunks(fp):
1118 if state == 'hunk':
1164 if state == 'hunk':
@@ -1130,7 +1176,7 b' def _applydiff(ui, fp, patcher, copyfn, '
1130 try:
1176 try:
1131 current_file, missing = selectfile(afile, bfile,
1177 current_file, missing = selectfile(afile, bfile,
1132 first_hunk, strip)
1178 first_hunk, strip)
1133 current_file = patcher(ui, current_file, opener,
1179 current_file = patcher(ui, current_file, backend,
1134 missing=missing, eolmode=eolmode)
1180 missing=missing, eolmode=eolmode)
1135 except PatchError, inst:
1181 except PatchError, inst:
1136 ui.warn(str(inst) + '\n')
1182 ui.warn(str(inst) + '\n')
General Comments 0
You need to be logged in to leave comments. Login now