Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/patch.py @ 10749:03225f14c495
Merge with stable
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Sat, 20 Mar 2010 16:57:24 -0500 |
parents | 16b9aa398c28 fb06e357e698 |
children | 440786f7f18b |
comparison
equal
deleted
inserted
replaced
10746:16b9aa398c28 | 10749:03225f14c495 |
---|---|
1010 | 1010 |
1011 # our states | 1011 # our states |
1012 BFILE = 1 | 1012 BFILE = 1 |
1013 context = None | 1013 context = None |
1014 lr = linereader(fp) | 1014 lr = linereader(fp) |
1015 dopatch = True | |
1016 # gitworkdone is True if a git operation (copy, rename, ...) was | 1015 # gitworkdone is True if a git operation (copy, rename, ...) was |
1017 # performed already for the current file. Useful when the file | 1016 # performed already for the current file. Useful when the file |
1018 # section may have no hunk. | 1017 # section may have no hunk. |
1019 gitworkdone = False | 1018 gitworkdone = False |
1019 empty = None | |
1020 | 1020 |
1021 while True: | 1021 while True: |
1022 newfile = False | 1022 newfile = newgitfile = False |
1023 x = lr.readline() | 1023 x = lr.readline() |
1024 if not x: | 1024 if not x: |
1025 break | 1025 break |
1026 if current_hunk: | 1026 if current_hunk: |
1027 if x.startswith('\ '): | 1027 if x.startswith('\ '): |
1028 current_hunk.fix_newline() | 1028 current_hunk.fix_newline() |
1029 yield 'hunk', current_hunk | 1029 yield 'hunk', current_hunk |
1030 current_hunk = None | 1030 current_hunk = None |
1031 gitworkdone = False | 1031 empty = False |
1032 if ((sourcefile or state == BFILE) and ((not context and x[0] == '@') or | 1032 if ((sourcefile or state == BFILE) and ((not context and x[0] == '@') or |
1033 ((context is not False) and x.startswith('***************')))): | 1033 ((context is not False) and x.startswith('***************')))): |
1034 try: | 1034 try: |
1035 if context is None and x.startswith('***************'): | 1035 if context is None and x.startswith('***************'): |
1036 context = True | 1036 context = True |
1044 continue | 1044 continue |
1045 hunknum += 1 | 1045 hunknum += 1 |
1046 if emitfile: | 1046 if emitfile: |
1047 emitfile = False | 1047 emitfile = False |
1048 yield 'file', (afile, bfile, current_hunk) | 1048 yield 'file', (afile, bfile, current_hunk) |
1049 empty = False | |
1049 elif state == BFILE and x.startswith('GIT binary patch'): | 1050 elif state == BFILE and x.startswith('GIT binary patch'): |
1050 current_hunk = binhunk(changed[bfile]) | 1051 current_hunk = binhunk(changed[bfile]) |
1051 hunknum += 1 | 1052 hunknum += 1 |
1052 if emitfile: | 1053 if emitfile: |
1053 emitfile = False | 1054 emitfile = False |
1054 yield 'file', ('a/' + afile, 'b/' + bfile, current_hunk) | 1055 yield 'file', ('a/' + afile, 'b/' + bfile, current_hunk) |
1056 empty = False | |
1055 current_hunk.extract(lr) | 1057 current_hunk.extract(lr) |
1056 elif x.startswith('diff --git'): | 1058 elif x.startswith('diff --git'): |
1057 # check for git diff, scanning the whole patch file if needed | 1059 # check for git diff, scanning the whole patch file if needed |
1058 m = gitre.match(x) | 1060 m = gitre.match(x) |
1061 gitworkdone = False | |
1059 if m: | 1062 if m: |
1060 afile, bfile = m.group(1, 2) | 1063 afile, bfile = m.group(1, 2) |
1061 if not git: | 1064 if not git: |
1062 git = True | 1065 git = True |
1063 dopatch, gitpatches = scangitpatch(lr, x) | 1066 gitpatches = scangitpatch(lr, x)[1] |
1064 yield 'git', gitpatches | 1067 yield 'git', gitpatches |
1065 for gp in gitpatches: | 1068 for gp in gitpatches: |
1066 changed[gp.path] = gp | 1069 changed[gp.path] = gp |
1067 # else error? | 1070 # else error? |
1068 # copy/rename + modify should modify target, not source | 1071 # copy/rename + modify should modify target, not source |
1069 gp = changed.get(bfile) | 1072 gp = changed.get(bfile) |
1070 if gp and gp.op in ('COPY', 'DELETE', 'RENAME', 'ADD'): | 1073 if gp and (gp.op in ('COPY', 'DELETE', 'RENAME', 'ADD') |
1074 or gp.mode): | |
1071 afile = bfile | 1075 afile = bfile |
1072 gitworkdone = True | 1076 gitworkdone = True |
1073 newfile = True | 1077 newgitfile = True |
1074 elif x.startswith('---'): | 1078 elif x.startswith('---'): |
1075 # check for a unified diff | 1079 # check for a unified diff |
1076 l2 = lr.readline() | 1080 l2 = lr.readline() |
1077 if not l2.startswith('+++'): | 1081 if not l2.startswith('+++'): |
1078 lr.push(l2) | 1082 lr.push(l2) |
1096 context = True | 1100 context = True |
1097 afile = parsefilename(x) | 1101 afile = parsefilename(x) |
1098 bfile = parsefilename(l2) | 1102 bfile = parsefilename(l2) |
1099 | 1103 |
1100 if newfile: | 1104 if newfile: |
1105 if empty: | |
1106 raise NoHunks | |
1107 empty = not gitworkdone | |
1108 gitworkdone = False | |
1109 | |
1110 if newgitfile or newfile: | |
1101 emitfile = True | 1111 emitfile = True |
1102 state = BFILE | 1112 state = BFILE |
1103 hunknum = 0 | 1113 hunknum = 0 |
1104 if current_hunk: | 1114 if current_hunk: |
1105 if current_hunk.complete(): | 1115 if current_hunk.complete(): |
1106 yield 'hunk', current_hunk | 1116 yield 'hunk', current_hunk |
1117 empty = False | |
1107 else: | 1118 else: |
1108 raise PatchError(_("malformed patch %s %s") % (afile, | 1119 raise PatchError(_("malformed patch %s %s") % (afile, |
1109 current_hunk.desc)) | 1120 current_hunk.desc)) |
1110 | 1121 |
1111 if hunknum == 0 and dopatch and not gitworkdone: | 1122 if (empty is None and not gitworkdone) or empty: |
1112 raise NoHunks | 1123 raise NoHunks |
1113 | 1124 |
1114 def applydiff(ui, fp, changed, strip=1, sourcefile=None, eolmode='strict'): | 1125 def applydiff(ui, fp, changed, strip=1, sourcefile=None, eolmode='strict'): |
1115 """ | 1126 """ |
1116 Reads a patch from fp and tries to apply it. | 1127 Reads a patch from fp and tries to apply it. |