##// END OF EJS Templates
patch: refactor file creation/removal detection...
Patrick Mezard -
r14451:c78d41db default
parent child Browse files
Show More
@@ -595,11 +595,11 b' def reposetup(ui, repo):'
595 595 wlock.release()
596 596
597 597 # monkeypatches
598 def kwpatchfile_init(orig, self, ui, fname, backend, mode,
598 def kwpatchfile_init(orig, self, ui, fname, backend, mode, create, remove,
599 599 missing=False, eolmode=None):
600 600 '''Monkeypatch/wrap patch.patchfile.__init__ to avoid
601 601 rejects or conflicts due to expanded keywords in working dir.'''
602 orig(self, ui, fname, backend, mode, missing, eolmode)
602 orig(self, ui, fname, backend, mode, create, remove, missing, eolmode)
603 603 # shrink keywords read from working dir
604 604 self.lines = kwt.shrinklines(self.fname, self.lines)
605 605
@@ -504,7 +504,7 b" contextdesc = re.compile('(---|\\*\\*\\*) ("
504 504 eolmodes = ['strict', 'crlf', 'lf', 'auto']
505 505
506 506 class patchfile(object):
507 def __init__(self, ui, fname, backend, mode, missing=False,
507 def __init__(self, ui, fname, backend, mode, create, remove, missing=False,
508 508 eolmode='strict'):
509 509 self.fname = fname
510 510 self.eolmode = eolmode
@@ -515,6 +515,8 b' class patchfile(object):'
515 515 self.exists = False
516 516 self.missing = missing
517 517 self.mode = mode
518 self.create = create
519 self.remove = remove
518 520 if not missing:
519 521 try:
520 522 data, mode = self.backend.getfile(fname)
@@ -620,13 +622,13 b' class patchfile(object):'
620 622 self.rej.append(h)
621 623 return -1
622 624
623 if self.exists and h.createfile():
625 if self.exists and self.create:
624 626 self.ui.warn(_("file %s already exists\n") % self.fname)
625 627 self.rej.append(h)
626 628 return -1
627 629
628 630 if isinstance(h, binhunk):
629 if h.rmfile():
631 if self.remove:
630 632 self.backend.unlink(self.fname)
631 633 else:
632 634 self.lines[:] = h.new()
@@ -654,7 +656,7 b' class patchfile(object):'
654 656 # when the hunk cleanly applies at start + skew, so skip the
655 657 # fast case code
656 658 if self.skew == 0 and diffhelpers.testhunk(old, self.lines, start) == 0:
657 if h.rmfile():
659 if self.remove:
658 660 self.backend.unlink(self.fname)
659 661 else:
660 662 self.lines[start : start + h.lena] = h.new()
@@ -710,7 +712,7 b' class patchfile(object):'
710 712 return len(self.rej)
711 713
712 714 class hunk(object):
713 def __init__(self, desc, num, lr, context, create=False, remove=False):
715 def __init__(self, desc, num, lr, context):
714 716 self.number = num
715 717 self.desc = desc
716 718 self.hunk = [desc]
@@ -723,8 +725,6 b' class hunk(object):'
723 725 self.read_context_hunk(lr)
724 726 else:
725 727 self.read_unified_hunk(lr)
726 self.create = create
727 self.remove = remove and not create
728 728
729 729 def getnormalized(self):
730 730 """Return a copy with line endings normalized to LF."""
@@ -738,7 +738,7 b' class hunk(object):'
738 738 return nlines
739 739
740 740 # Dummy object, it is rebuilt manually
741 nh = hunk(self.desc, self.number, None, None, False, False)
741 nh = hunk(self.desc, self.number, None, None)
742 742 nh.number = self.number
743 743 nh.desc = self.desc
744 744 nh.hunk = self.hunk
@@ -748,8 +748,6 b' class hunk(object):'
748 748 nh.startb = self.startb
749 749 nh.lena = self.lena
750 750 nh.lenb = self.lenb
751 nh.create = self.create
752 nh.remove = self.remove
753 751 return nh
754 752
755 753 def read_unified_hunk(self, lr):
@@ -891,12 +889,6 b' class hunk(object):'
891 889 def complete(self):
892 890 return len(self.a) == self.lena and len(self.b) == self.lenb
893 891
894 def createfile(self):
895 return self.starta == 0 and self.lena == 0 and self.create
896
897 def rmfile(self):
898 return self.startb == 0 and self.lenb == 0 and self.remove
899
900 892 def fuzzit(self, l, fuzz, toponly):
901 893 # this removes context lines from the top and bottom of list 'l'. It
902 894 # checks the hunk to make sure only context lines are removed, and then
@@ -942,18 +934,11 b' class hunk(object):'
942 934
943 935 class binhunk:
944 936 'A binary patch file. Only understands literals so far.'
945 def __init__(self, gitpatch, lr):
946 self.gitpatch = gitpatch
937 def __init__(self, lr):
947 938 self.text = None
948 939 self.hunk = ['GIT binary patch\n']
949 940 self._read(lr)
950 941
951 def createfile(self):
952 return self.gitpatch.op == 'ADD'
953
954 def rmfile(self):
955 return self.gitpatch.op == 'DELETE'
956
957 942 def complete(self):
958 943 return self.text is not None
959 944
@@ -1020,10 +1005,14 b' def selectfile(backend, afile_orig, bfil'
1020 1005 # Git patches do not play games. Excluding copies from the
1021 1006 # following heuristic avoids a lot of confusion
1022 1007 fname = pathstrip(gp.path, strip - 1)[1]
1023 missing = not hunk.createfile() and not backend.exists(fname)
1024 return fname, missing
1008 create = gp.op == 'ADD'
1009 remove = gp.op == 'DELETE'
1010 missing = not create and not backend.exists(fname)
1011 return fname, missing, create, remove
1025 1012 nulla = afile_orig == "/dev/null"
1026 1013 nullb = bfile_orig == "/dev/null"
1014 create = nulla and hunk.starta == 0 and hunk.lena == 0
1015 remove = nullb and hunk.startb == 0 and hunk.lenb == 0
1027 1016 abase, afile = pathstrip(afile_orig, strip)
1028 1017 gooda = not nulla and backend.exists(afile)
1029 1018 bbase, bfile = pathstrip(bfile_orig, strip)
@@ -1031,20 +1020,16 b' def selectfile(backend, afile_orig, bfil'
1031 1020 goodb = gooda
1032 1021 else:
1033 1022 goodb = not nullb and backend.exists(bfile)
1034 createfunc = hunk.createfile
1035 missing = not goodb and not gooda and not createfunc()
1023 missing = not goodb and not gooda and not create
1036 1024
1037 1025 # some diff programs apparently produce patches where the afile is
1038 1026 # not /dev/null, but afile starts with bfile
1039 1027 abasedir = afile[:afile.rfind('/') + 1]
1040 1028 bbasedir = bfile[:bfile.rfind('/') + 1]
1041 if missing and abasedir == bbasedir and afile.startswith(bfile):
1042 # this isn't very pretty
1043 hunk.create = True
1044 if createfunc():
1045 missing = False
1046 else:
1047 hunk.create = False
1029 if (missing and abasedir == bbasedir and afile.startswith(bfile)
1030 and hunk.starta == 0 and hunk.lena == 0):
1031 create = True
1032 missing = False
1048 1033
1049 1034 # If afile is "a/b/foo" and bfile is "a/b/foo.orig" we assume the
1050 1035 # diff is between a file and its backup. In this case, the original
@@ -1065,7 +1050,7 b' def selectfile(backend, afile_orig, bfil'
1065 1050 else:
1066 1051 raise PatchError(_("undefined source and destination files"))
1067 1052
1068 return fname, missing
1053 return fname, missing, create, remove
1069 1054
1070 1055 def scangitpatch(lr, firstline):
1071 1056 """
@@ -1125,13 +1110,11 b' def iterhunks(fp):'
1125 1110 if gitpatches and gitpatches[-1][0] == bfile:
1126 1111 gp = gitpatches.pop()[1]
1127 1112 if x.startswith('GIT binary patch'):
1128 h = binhunk(gp, lr)
1113 h = binhunk(lr)
1129 1114 else:
1130 1115 if context is None and x.startswith('***************'):
1131 1116 context = True
1132 create = afile == '/dev/null' or gp and gp.op == 'ADD'
1133 remove = bfile == '/dev/null' or gp and gp.op == 'DELETE'
1134 h = hunk(x, hunknum + 1, lr, context, create, remove)
1117 h = hunk(x, hunknum + 1, lr, context)
1135 1118 hunknum += 1
1136 1119 if emitfile:
1137 1120 emitfile = False
@@ -1250,10 +1233,11 b' def _applydiff(ui, fp, patcher, backend,'
1250 1233 continue
1251 1234 try:
1252 1235 mode = gp and gp.mode or None
1253 current_file, missing = selectfile(backend, afile, bfile,
1254 first_hunk, strip, gp)
1236 current_file, missing, create, remove = selectfile(
1237 backend, afile, bfile, first_hunk, strip, gp)
1255 1238 current_file = patcher(ui, current_file, backend, mode,
1256 missing=missing, eolmode=eolmode)
1239 create, remove, missing=missing,
1240 eolmode=eolmode)
1257 1241 except PatchError, inst:
1258 1242 ui.warn(str(inst) + '\n')
1259 1243 current_file = None
@@ -1386,8 +1370,8 b' def changedfiles(ui, repo, patchpath, st'
1386 1370 changed.add(pathstrip(gp.oldpath, strip - 1)[1])
1387 1371 if not first_hunk:
1388 1372 continue
1389 current_file, missing = selectfile(backend, afile, bfile,
1390 first_hunk, strip, gp)
1373 current_file, missing, create, remove = selectfile(
1374 backend, afile, bfile, first_hunk, strip, gp)
1391 1375 changed.add(current_file)
1392 1376 elif state not in ('hunk', 'git'):
1393 1377 raise util.Abort(_('unsupported parser state: %s') % state)
General Comments 0
You need to be logged in to leave comments. Login now