comparison mercurial/patch.py @ 3105:ef4e5d05bac4

Merge with mainline
author Matt Mackall <mpm@selenic.com>
date Sun, 17 Sep 2006 16:02:09 -0500
parents f422c8265ae5
children e43fd1623fe1
comparison
equal deleted inserted replaced
3104:e6818b0b8154 3105:ef4e5d05bac4
7 7
8 from demandload import demandload 8 from demandload import demandload
9 from i18n import gettext as _ 9 from i18n import gettext as _
10 from node import * 10 from node import *
11 demandload(globals(), "cmdutil mdiff util") 11 demandload(globals(), "cmdutil mdiff util")
12 demandload(globals(), "cStringIO email.Parser errno os re shutil sys tempfile") 12 demandload(globals(), '''cStringIO email.Parser errno os re shutil sys tempfile
13 popen2''')
13 14
14 # helper functions 15 # helper functions
15 16
16 def copyfile(src, dst, basedir=None): 17 def copyfile(src, dst, basedir=None):
17 if not basedir: 18 if not basedir:
180 if not gitpatches: 181 if not gitpatches:
181 dopatch = True 182 dopatch = True
182 183
183 return (dopatch, gitpatches) 184 return (dopatch, gitpatches)
184 185
185 def dogitpatch(patchname, gitpatches): 186 def dogitpatch(patchname, gitpatches, cwd=None):
186 """Preprocess git patch so that vanilla patch can handle it""" 187 """Preprocess git patch so that vanilla patch can handle it"""
187 pf = file(patchname) 188 pf = file(patchname)
188 pfline = 1 189 pfline = 1
189 190
190 fd, patchname = tempfile.mkstemp(prefix='hg-patch-') 191 fd, patchname = tempfile.mkstemp(prefix='hg-patch-')
194 for i in range(len(gitpatches)): 195 for i in range(len(gitpatches)):
195 p = gitpatches[i] 196 p = gitpatches[i]
196 if not p.copymod: 197 if not p.copymod:
197 continue 198 continue
198 199
199 copyfile(p.oldpath, p.path) 200 copyfile(p.oldpath, p.path, basedir=cwd)
200 201
201 # rewrite patch hunk 202 # rewrite patch hunk
202 while pfline < p.lineno: 203 while pfline < p.lineno:
203 tmpfp.write(pf.readline()) 204 tmpfp.write(pf.readline())
204 pfline += 1 205 pfline += 1
225 226
226 def patch(patchname, ui, strip=1, cwd=None): 227 def patch(patchname, ui, strip=1, cwd=None):
227 """apply the patch <patchname> to the working directory. 228 """apply the patch <patchname> to the working directory.
228 a list of patched files is returned""" 229 a list of patched files is returned"""
229 230
230 (dopatch, gitpatches) = readgitpatch(patchname) 231 # helper function
231 232 def __patch(patchname):
232 files = {} 233 """patch and updates the files and fuzz variables"""
233 fuzz = False 234 files = {}
234 if dopatch: 235 fuzz = False
235 if dopatch == 'filter': 236
236 patchname = dogitpatch(patchname, gitpatches) 237 patcher = util.find_in_path('gpatch', os.environ.get('PATH', ''),
237 patcher = util.find_in_path('gpatch', os.environ.get('PATH', ''), 'patch') 238 'patch')
238 args = [] 239 args = []
239 if cwd: 240 if cwd:
240 args.append('-d %s' % util.shellquote(cwd)) 241 args.append('-d %s' % util.shellquote(cwd))
241 fp = os.popen('%s %s -p%d < %s' % (patcher, ' '.join(args), strip, 242 fp = os.popen('%s %s -p%d < %s' % (patcher, ' '.join(args), strip,
242 util.shellquote(patchname))) 243 util.shellquote(patchname)))
243
244 if dopatch == 'filter':
245 False and os.unlink(patchname)
246 244
247 for line in fp: 245 for line in fp:
248 line = line.rstrip() 246 line = line.rstrip()
249 ui.note(line + '\n') 247 ui.note(line + '\n')
250 if line.startswith('patching file '): 248 if line.startswith('patching file '):
262 elif line.find('FAILED') >= 0: 260 elif line.find('FAILED') >= 0:
263 if not printed_file: 261 if not printed_file:
264 ui.warn(pf + '\n') 262 ui.warn(pf + '\n')
265 printed_file = True 263 printed_file = True
266 ui.warn(line + '\n') 264 ui.warn(line + '\n')
267
268 code = fp.close() 265 code = fp.close()
269 if code: 266 if code:
270 raise util.Abort(_("patch command failed: %s") % 267 raise util.Abort(_("patch command failed: %s") %
271 util.explain_exit(code)[0]) 268 util.explain_exit(code)[0])
269 return files, fuzz
270
271 (dopatch, gitpatches) = readgitpatch(patchname)
272
273 if dopatch:
274 if dopatch == 'filter':
275 patchname = dogitpatch(patchname, gitpatches, cwd=cwd)
276 try:
277 files, fuzz = __patch(patchname)
278 finally:
279 if dopatch == 'filter':
280 os.unlink(patchname)
281 else:
282 files, fuzz = {}, False
272 283
273 for gp in gitpatches: 284 for gp in gitpatches:
274 files[gp.path] = (gp.op, gp) 285 files[gp.path] = (gp.op, gp)
275 286
276 return (files, fuzz) 287 return (files, fuzz)
490 else: 501 else:
491 mode = gitmode(mmap.execf(f)) 502 mode = gitmode(mmap.execf(f))
492 header.append('deleted file mode %s\n' % mode) 503 header.append('deleted file mode %s\n' % mode)
493 else: 504 else:
494 omode = gitmode(mmap.execf(f)) 505 omode = gitmode(mmap.execf(f))
495 nmode = gitmode(util.is_exec(repo.wjoin(f), mmap.execf(f))) 506 if node2:
507 nmode = gitmode(mmap2.execf(f))
508 else:
509 nmode = gitmode(util.is_exec(repo.wjoin(f), mmap.execf(f)))
496 addmodehdr(header, omode, nmode) 510 addmodehdr(header, omode, nmode)
497 r = None 511 r = None
498 if dodiff: 512 if dodiff:
499 header.insert(0, 'diff --git a/%s b/%s\n' % (a, b)) 513 header.insert(0, 'diff --git a/%s b/%s\n' % (a, b))
500 fp.write(''.join(header)) 514 fp.write(''.join(header))
535 if fp not in (sys.stdout, repo.ui): 549 if fp not in (sys.stdout, repo.ui):
536 fp.close() 550 fp.close()
537 551
538 for seqno, cset in enumerate(revs): 552 for seqno, cset in enumerate(revs):
539 single(cset, seqno, fp) 553 single(cset, seqno, fp)
554
555 def diffstat(patchlines):
556 fd, name = tempfile.mkstemp(prefix="hg-patchbomb-", suffix=".txt")
557 try:
558 p = popen2.Popen3('diffstat -p1 -w79 2>/dev/null > ' + name)
559 try:
560 for line in patchlines: print >> p.tochild, line
561 p.tochild.close()
562 if p.wait(): return
563 fp = os.fdopen(fd, 'r')
564 stat = []
565 for line in fp: stat.append(line.lstrip())
566 last = stat.pop()
567 stat.insert(0, last)
568 stat = ''.join(stat)
569 if stat.startswith('0 files'): raise ValueError
570 return stat
571 except: raise
572 finally:
573 try: os.unlink(name)
574 except: pass