Show More
@@ -838,14 +838,16 b' class linereader:' | |||||
838 | return l |
|
838 | return l | |
839 | return self.fp.readline() |
|
839 | return self.fp.readline() | |
840 |
|
840 | |||
841 | def applydiff(ui, fp, changed, strip=1, sourcefile=None, reverse=False, |
|
841 | def iterhunks(ui, fp, sourcefile=None): | |
842 | rejmerge=None, updatedir=None): |
|
842 | """Read a patch and yield the following events: | |
843 | """reads a patch from fp and tries to apply it. The dict 'changed' is |
|
843 | - ("file", afile, bfile, firsthunk): select a new target file. | |
844 | filled in with all of the filenames changed by the patch. Returns 0 |
|
844 | - ("hunk", hunk): a new hunk is ready to be applied, follows a | |
845 | for a clean patch, -1 if any rejects were found and 1 if there was |
|
845 | "file" event. | |
846 | any fuzz.""" |
|
846 | - ("git", gitchanges): current diff is in git format, gitchanges | |
|
847 | maps filenames to gitpatch records. Unique event. | |||
|
848 | """ | |||
847 |
|
849 | |||
848 |
def scangitpatch(fp, firstline |
|
850 | def scangitpatch(fp, firstline): | |
849 | '''git patches can modify a file, then copy that file to |
|
851 | '''git patches can modify a file, then copy that file to | |
850 | a new file, but expect the source to be the unmodified form. |
|
852 | a new file, but expect the source to be the unmodified form. | |
851 | So we scan the patch looking for that case so we can do |
|
853 | So we scan the patch looking for that case so we can do | |
@@ -858,46 +860,28 b' def applydiff(ui, fp, changed, strip=1, ' | |||||
858 | fp = cStringIO.StringIO(fp.read()) |
|
860 | fp = cStringIO.StringIO(fp.read()) | |
859 |
|
861 | |||
860 | (dopatch, gitpatches) = readgitpatch(fp, firstline) |
|
862 | (dopatch, gitpatches) = readgitpatch(fp, firstline) | |
861 | for gp in gitpatches: |
|
|||
862 | if gp.op in ('COPY', 'RENAME'): |
|
|||
863 | copyfile(gp.oldpath, gp.path, basedir=cwd) |
|
|||
864 |
|
||||
865 | fp.seek(pos) |
|
863 | fp.seek(pos) | |
866 |
|
864 | |||
867 | return fp, dopatch, gitpatches |
|
865 | return fp, dopatch, gitpatches | |
868 |
|
866 | |||
|
867 | changed = {} | |||
869 | current_hunk = None |
|
868 | current_hunk = None | |
870 | current_file = None |
|
|||
871 | afile = "" |
|
869 | afile = "" | |
872 | bfile = "" |
|
870 | bfile = "" | |
873 | state = None |
|
871 | state = None | |
874 | hunknum = 0 |
|
872 | hunknum = 0 | |
875 | rejects = 0 |
|
873 | emitfile = False | |
876 |
|
874 | |||
877 | git = False |
|
875 | git = False | |
878 | gitre = re.compile('diff --git (a/.*) (b/.*)') |
|
876 | gitre = re.compile('diff --git (a/.*) (b/.*)') | |
879 |
|
877 | |||
880 | # our states |
|
878 | # our states | |
881 | BFILE = 1 |
|
879 | BFILE = 1 | |
882 | err = 0 |
|
|||
883 | context = None |
|
880 | context = None | |
884 | lr = linereader(fp) |
|
881 | lr = linereader(fp) | |
885 | dopatch = True |
|
882 | dopatch = True | |
886 | gitworkdone = False |
|
883 | gitworkdone = False | |
887 |
|
884 | |||
888 | def getpatchfile(afile, bfile, hunk): |
|
|||
889 | try: |
|
|||
890 | if sourcefile: |
|
|||
891 | targetfile = patchfile(ui, sourcefile) |
|
|||
892 | else: |
|
|||
893 | targetfile = selectfile(afile, bfile, hunk, |
|
|||
894 | strip, reverse) |
|
|||
895 | targetfile = patchfile(ui, targetfile) |
|
|||
896 | return targetfile |
|
|||
897 | except PatchError, err: |
|
|||
898 | ui.warn(str(err) + '\n') |
|
|||
899 | return None |
|
|||
900 |
|
||||
901 | while True: |
|
885 | while True: | |
902 | newfile = False |
|
886 | newfile = False | |
903 | x = lr.readline() |
|
887 | x = lr.readline() | |
@@ -906,11 +890,7 b' def applydiff(ui, fp, changed, strip=1, ' | |||||
906 | if current_hunk: |
|
890 | if current_hunk: | |
907 | if x.startswith('\ '): |
|
891 | if x.startswith('\ '): | |
908 | current_hunk.fix_newline() |
|
892 | current_hunk.fix_newline() | |
909 | ret = current_file.apply(current_hunk, reverse) |
|
893 | yield 'hunk', current_hunk | |
910 | if ret >= 0: |
|
|||
911 | changed.setdefault(current_file.fname, (None, None)) |
|
|||
912 | if ret > 0: |
|
|||
913 | err = 1 |
|
|||
914 | current_hunk = None |
|
894 | current_hunk = None | |
915 | gitworkdone = False |
|
895 | gitworkdone = False | |
916 | if ((sourcefile or state == BFILE) and ((not context and x[0] == '@') or |
|
896 | if ((sourcefile or state == BFILE) and ((not context and x[0] == '@') or | |
@@ -924,21 +904,15 b' def applydiff(ui, fp, changed, strip=1, ' | |||||
924 | current_hunk = None |
|
904 | current_hunk = None | |
925 | continue |
|
905 | continue | |
926 | hunknum += 1 |
|
906 | hunknum += 1 | |
927 |
if |
|
907 | if emitfile: | |
928 | current_file = getpatchfile(afile, bfile, current_hunk) |
|
908 | emitfile = False | |
929 | if not current_file: |
|
909 | yield 'file', (afile, bfile, current_hunk) | |
930 | current_file, current_hunk = None, None |
|
|||
931 | rejects += 1 |
|
|||
932 | continue |
|
|||
933 | elif state == BFILE and x.startswith('GIT binary patch'): |
|
910 | elif state == BFILE and x.startswith('GIT binary patch'): | |
934 | current_hunk = binhunk(changed[bfile[2:]][1]) |
|
911 | current_hunk = binhunk(changed[bfile[2:]][1]) | |
935 | hunknum += 1 |
|
912 | hunknum += 1 | |
936 |
if |
|
913 | if emitfile: | |
937 | current_file = getpatchfile(afile, bfile, current_hunk) |
|
914 | emitfile = False | |
938 | if not current_file: |
|
915 | yield 'file', (afile, bfile, current_hunk) | |
939 | current_file, current_hunk = None, None |
|
|||
940 | rejects += 1 |
|
|||
941 | continue |
|
|||
942 | current_hunk.extract(fp) |
|
916 | current_hunk.extract(fp) | |
943 | elif x.startswith('diff --git'): |
|
917 | elif x.startswith('diff --git'): | |
944 | # check for git diff, scanning the whole patch file if needed |
|
918 | # check for git diff, scanning the whole patch file if needed | |
@@ -948,6 +922,7 b' def applydiff(ui, fp, changed, strip=1, ' | |||||
948 | if not git: |
|
922 | if not git: | |
949 | git = True |
|
923 | git = True | |
950 | fp, dopatch, gitpatches = scangitpatch(fp, x) |
|
924 | fp, dopatch, gitpatches = scangitpatch(fp, x) | |
|
925 | yield 'git', gitpatches | |||
951 | for gp in gitpatches: |
|
926 | for gp in gitpatches: | |
952 | changed[gp.path] = (gp.op, gp) |
|
927 | changed[gp.path] = (gp.op, gp) | |
953 | # else error? |
|
928 | # else error? | |
@@ -984,34 +959,76 b' def applydiff(ui, fp, changed, strip=1, ' | |||||
984 | bfile = parsefilename(l2) |
|
959 | bfile = parsefilename(l2) | |
985 |
|
960 | |||
986 | if newfile: |
|
961 | if newfile: | |
987 |
if |
|
962 | emitfile = True | |
|
963 | state = BFILE | |||
|
964 | hunknum = 0 | |||
|
965 | if current_hunk: | |||
|
966 | if current_hunk.complete(): | |||
|
967 | yield 'hunk', current_hunk | |||
|
968 | else: | |||
|
969 | raise PatchError(_("malformed patch %s %s") % (afile, | |||
|
970 | current_hunk.desc)) | |||
|
971 | ||||
|
972 | if hunknum == 0 and dopatch and not gitworkdone: | |||
|
973 | raise NoHunks | |||
|
974 | ||||
|
975 | def applydiff(ui, fp, changed, strip=1, sourcefile=None, reverse=False, | |||
|
976 | rejmerge=None, updatedir=None): | |||
|
977 | """reads a patch from fp and tries to apply it. The dict 'changed' is | |||
|
978 | filled in with all of the filenames changed by the patch. Returns 0 | |||
|
979 | for a clean patch, -1 if any rejects were found and 1 if there was | |||
|
980 | any fuzz.""" | |||
|
981 | ||||
|
982 | rejects = 0 | |||
|
983 | err = 0 | |||
|
984 | current_file = None | |||
|
985 | gitpatches = None | |||
|
986 | ||||
|
987 | def closefile(): | |||
|
988 | if not current_file: | |||
|
989 | return 0 | |||
988 |
|
|
990 | current_file.close() | |
989 |
|
|
991 | if rejmerge: | |
990 |
|
|
992 | rejmerge(current_file) | |
991 |
|
|
993 | return len(current_file.rej) | |
992 | state = BFILE |
|
994 | ||
993 | current_file = None |
|
995 | for state, values in iterhunks(ui, fp, sourcefile): | |
994 |
|
|
996 | if state == 'hunk': | |
995 |
if current_ |
|
997 | if not current_file: | |
996 | if current_hunk.complete(): |
|
998 | continue | |
|
999 | current_hunk = values | |||
997 | ret = current_file.apply(current_hunk, reverse) |
|
1000 | ret = current_file.apply(current_hunk, reverse) | |
998 | if ret >= 0: |
|
1001 | if ret >= 0: | |
999 | changed.setdefault(current_file.fname, (None, None)) |
|
1002 | changed.setdefault(current_file.fname, (None, None)) | |
1000 | if ret > 0: |
|
1003 | if ret > 0: | |
1001 | err = 1 |
|
1004 | err = 1 | |
|
1005 | elif state == 'file': | |||
|
1006 | rejects += closefile() | |||
|
1007 | afile, bfile, first_hunk = values | |||
|
1008 | try: | |||
|
1009 | if sourcefile: | |||
|
1010 | current_file = patchfile(ui, sourcefile) | |||
1002 | else: |
|
1011 | else: | |
1003 | fname = current_file and current_file.fname or None |
|
1012 | current_file = selectfile(afile, bfile, first_hunk, | |
1004 | raise PatchError(_("malformed patch %s %s") % (fname, |
|
1013 | strip, reverse) | |
1005 |
|
|
1014 | current_file = patchfile(ui, current_file) | |
1006 | if current_file: |
|
1015 | except PatchError, err: | |
1007 | current_file.close() |
|
1016 | ui.warn(str(err) + '\n') | |
1008 | if rejmerge: |
|
1017 | current_file, current_hunk = None, None | |
1009 | rejmerge(current_file) |
|
1018 | rejects += 1 | |
1010 | rejects += len(current_file.rej) |
|
1019 | continue | |
|
1020 | elif state == 'git': | |||
|
1021 | gitpatches = values | |||
|
1022 | for gp in gitpatches: | |||
|
1023 | if gp.op in ('COPY', 'RENAME'): | |||
|
1024 | copyfile(gp.oldpath, gp.path) | |||
|
1025 | changed[gp.path] = (gp.op, gp) | |||
|
1026 | else: | |||
|
1027 | raise util.Abort(_('unsupported parser state: %s') % state) | |||
1011 |
|
1028 | |||
1012 | if not rejects and hunknum == 0 and dopatch and not gitworkdone: |
|
1029 | rejects += closefile() | |
1013 | raise NoHunks |
|
1030 | ||
1014 | if updatedir and git: |
|
1031 | if updatedir and gitpatches: | |
1015 | updatedir(gitpatches) |
|
1032 | updatedir(gitpatches) | |
1016 | if rejects: |
|
1033 | if rejects: | |
1017 | return -1 |
|
1034 | return -1 |
@@ -3,7 +3,6 b' Patch queue now empty' | |||||
3 | % push patch with missing target |
|
3 | % push patch with missing target | |
4 | applying changeb |
|
4 | applying changeb | |
5 | unable to find b or b for patching |
|
5 | unable to find b or b for patching | |
6 | unable to find b or b for patching |
|
|||
7 | patch failed, unable to continue (try -v) |
|
6 | patch failed, unable to continue (try -v) | |
8 | patch failed, rejects left in working dir |
|
7 | patch failed, rejects left in working dir | |
9 | Errors during apply, please fix and refresh changeb |
|
8 | Errors during apply, please fix and refresh changeb |
General Comments 0
You need to be logged in to leave comments.
Login now