Mercurial > public > mercurial-scm > hg
comparison mercurial/patch.py @ 14534:ecc79816d31e
patch: fix patchmeta/hunk synchronization in iterhunks()
Synchronizing on bfile does not work on file removal where bfile is /dev/null.
We match items on afile or bfile instead. The incorrect code makes iterhunks()
to emit patchmeta and hunks separately in some cases. This is currently hidden
by applydiff() being too tolerant when processing patchmeta, and will be fixed
later.
author | Patrick Mezard <pmezard@gmail.com> |
---|---|
date | Sun, 05 Jun 2011 22:24:19 +0200 |
parents | aa12e1bbde10 |
children | e597ef52a7c2 |
comparison
equal
deleted
inserted
replaced
14533:aa12e1bbde10 | 14534:ecc79816d31e |
---|---|
1120 if state == BFILE and ( | 1120 if state == BFILE and ( |
1121 (not context and x[0] == '@') | 1121 (not context and x[0] == '@') |
1122 or (context is not False and x.startswith('***************')) | 1122 or (context is not False and x.startswith('***************')) |
1123 or x.startswith('GIT binary patch')): | 1123 or x.startswith('GIT binary patch')): |
1124 gp = None | 1124 gp = None |
1125 if gitpatches and gitpatches[-1][0] == bfile: | 1125 if (gitpatches and |
1126 gp = gitpatches.pop()[1] | 1126 (gitpatches[-1][0] == afile or gitpatches[-1][1] == bfile)): |
1127 gp = gitpatches.pop()[2] | |
1127 if x.startswith('GIT binary patch'): | 1128 if x.startswith('GIT binary patch'): |
1128 h = binhunk(lr) | 1129 h = binhunk(lr) |
1129 else: | 1130 else: |
1130 if context is None and x.startswith('***************'): | 1131 if context is None and x.startswith('***************'): |
1131 context = True | 1132 context = True |
1139 m = gitre.match(x) | 1140 m = gitre.match(x) |
1140 if not m: | 1141 if not m: |
1141 continue | 1142 continue |
1142 if gitpatches is None: | 1143 if gitpatches is None: |
1143 # scan whole input for git metadata | 1144 # scan whole input for git metadata |
1144 gitpatches = [('b/' + gp.path, gp) for gp | 1145 gitpatches = [('a/' + gp.path, 'b/' + gp.path, gp) for gp |
1145 in scangitpatch(lr, x)] | 1146 in scangitpatch(lr, x)] |
1146 yield 'git', [g[1] for g in gitpatches | 1147 yield 'git', [g[2] for g in gitpatches |
1147 if g[1].op in ('COPY', 'RENAME')] | 1148 if g[2].op in ('COPY', 'RENAME')] |
1148 gitpatches.reverse() | 1149 gitpatches.reverse() |
1149 afile = 'a/' + m.group(1) | 1150 afile = 'a/' + m.group(1) |
1150 bfile = 'b/' + m.group(2) | 1151 bfile = 'b/' + m.group(2) |
1151 while bfile != gitpatches[-1][0]: | 1152 while afile != gitpatches[-1][0] and bfile != gitpatches[-1][1]: |
1152 gp = gitpatches.pop()[1] | 1153 gp = gitpatches.pop()[2] |
1153 yield 'file', ('a/' + gp.path, 'b/' + gp.path, None, gp) | 1154 yield 'file', ('a/' + gp.path, 'b/' + gp.path, None, gp) |
1154 gp = gitpatches[-1][1] | 1155 gp = gitpatches[-1][2] |
1155 # copy/rename + modify should modify target, not source | 1156 # copy/rename + modify should modify target, not source |
1156 if gp.op in ('COPY', 'DELETE', 'RENAME', 'ADD') or gp.mode: | 1157 if gp.op in ('COPY', 'DELETE', 'RENAME', 'ADD') or gp.mode: |
1157 afile = bfile | 1158 afile = bfile |
1158 newfile = True | 1159 newfile = True |
1159 elif x.startswith('---'): | 1160 elif x.startswith('---'): |
1187 emitfile = True | 1188 emitfile = True |
1188 state = BFILE | 1189 state = BFILE |
1189 hunknum = 0 | 1190 hunknum = 0 |
1190 | 1191 |
1191 while gitpatches: | 1192 while gitpatches: |
1192 gp = gitpatches.pop()[1] | 1193 gp = gitpatches.pop()[2] |
1193 yield 'file', ('a/' + gp.path, 'b/' + gp.path, None, gp) | 1194 yield 'file', ('a/' + gp.path, 'b/' + gp.path, None, gp) |
1194 | 1195 |
1195 def applydiff(ui, fp, changed, backend, store, strip=1, eolmode='strict'): | 1196 def applydiff(ui, fp, changed, backend, store, strip=1, eolmode='strict'): |
1196 """Reads a patch from fp and tries to apply it. | 1197 """Reads a patch from fp and tries to apply it. |
1197 | 1198 |