9 import cStringIO, email.Parser, os, re |
9 import cStringIO, email.Parser, os, re |
10 import tempfile, zlib |
10 import tempfile, zlib |
11 |
11 |
12 from i18n import _ |
12 from i18n import _ |
13 from node import hex, nullid, short |
13 from node import hex, nullid, short |
14 import base85, cmdutil, mdiff, util, diffhelpers, copies, encoding |
14 import base85, mdiff, util, diffhelpers, copies, encoding |
15 |
15 |
16 gitre = re.compile('diff --git a/(.*) b/(.*)') |
16 gitre = re.compile('diff --git a/(.*) b/(.*)') |
17 |
17 |
18 class PatchError(Exception): |
18 class PatchError(Exception): |
19 pass |
19 pass |
442 finally: |
442 finally: |
443 fp.close() |
443 fp.close() |
444 |
444 |
445 def writelines(self, fname, lines): |
445 def writelines(self, fname, lines): |
446 # Ensure supplied data ends in fname, being a regular file or |
446 # Ensure supplied data ends in fname, being a regular file or |
447 # a symlink. updatedir() will -too magically- take care of |
447 # a symlink. cmdutil.updatedir will -too magically- take care |
448 # setting it to the proper type afterwards. |
448 # of setting it to the proper type afterwards. |
449 islink = os.path.islink(fname) |
449 islink = os.path.islink(fname) |
450 if islink: |
450 if islink: |
451 fp = cStringIO.StringIO() |
451 fp = cStringIO.StringIO() |
452 else: |
452 else: |
453 fp = self.opener(fname, 'w') |
453 fp = self.opener(fname, 'w') |
1127 |
1127 |
1128 If 'eolmode' is 'strict', the patch content and patched file are |
1128 If 'eolmode' is 'strict', the patch content and patched file are |
1129 read in binary mode. Otherwise, line endings are ignored when |
1129 read in binary mode. Otherwise, line endings are ignored when |
1130 patching then normalized according to 'eolmode'. |
1130 patching then normalized according to 'eolmode'. |
1131 |
1131 |
1132 Callers probably want to call 'updatedir' after this to apply |
1132 Callers probably want to call 'cmdutil.updatedir' after this to |
1133 certain categories of changes not done by this function. |
1133 apply certain categories of changes not done by this function. |
1134 """ |
1134 """ |
1135 return _applydiff( |
1135 return _applydiff( |
1136 ui, fp, patchfile, copyfile, |
1136 ui, fp, patchfile, copyfile, |
1137 changed, strip=strip, sourcefile=sourcefile, eolmode=eolmode) |
1137 changed, strip=strip, sourcefile=sourcefile, eolmode=eolmode) |
1138 |
1138 |
1193 rejects += closefile() |
1193 rejects += closefile() |
1194 |
1194 |
1195 if rejects: |
1195 if rejects: |
1196 return -1 |
1196 return -1 |
1197 return err |
1197 return err |
1198 |
|
1199 def updatedir(ui, repo, patches, similarity=0): |
|
1200 '''Update dirstate after patch application according to metadata''' |
|
1201 if not patches: |
|
1202 return |
|
1203 copies = [] |
|
1204 removes = set() |
|
1205 cfiles = patches.keys() |
|
1206 cwd = repo.getcwd() |
|
1207 if cwd: |
|
1208 cfiles = [util.pathto(repo.root, cwd, f) for f in patches.keys()] |
|
1209 for f in patches: |
|
1210 gp = patches[f] |
|
1211 if not gp: |
|
1212 continue |
|
1213 if gp.op == 'RENAME': |
|
1214 copies.append((gp.oldpath, gp.path)) |
|
1215 removes.add(gp.oldpath) |
|
1216 elif gp.op == 'COPY': |
|
1217 copies.append((gp.oldpath, gp.path)) |
|
1218 elif gp.op == 'DELETE': |
|
1219 removes.add(gp.path) |
|
1220 |
|
1221 wctx = repo[None] |
|
1222 for src, dst in copies: |
|
1223 wctx.copy(src, dst) |
|
1224 if (not similarity) and removes: |
|
1225 wctx.remove(sorted(removes), True) |
|
1226 |
|
1227 for f in patches: |
|
1228 gp = patches[f] |
|
1229 if gp and gp.mode: |
|
1230 islink, isexec = gp.mode |
|
1231 dst = repo.wjoin(gp.path) |
|
1232 # patch won't create empty files |
|
1233 if gp.op == 'ADD' and not os.path.exists(dst): |
|
1234 flags = (isexec and 'x' or '') + (islink and 'l' or '') |
|
1235 repo.wwrite(gp.path, '', flags) |
|
1236 util.set_flags(dst, islink, isexec) |
|
1237 cmdutil.addremove(repo, cfiles, similarity=similarity) |
|
1238 files = patches.keys() |
|
1239 files.extend([r for r in removes if r not in files]) |
|
1240 return sorted(files) |
|
1241 |
1198 |
1242 def externalpatch(patcher, args, patchname, ui, strip, cwd, files): |
1199 def externalpatch(patcher, args, patchname, ui, strip, cwd, files): |
1243 """use <patcher> to apply <patchname> to the working directory. |
1200 """use <patcher> to apply <patchname> to the working directory. |
1244 returns whether patch was applied with fuzz factor.""" |
1201 returns whether patch was applied with fuzz factor.""" |
1245 |
1202 |