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