##// END OF EJS Templates
patch.py: re-add the ability to use an external patch program...
Bryan O'Sullivan -
r4900:e56c7e05 default
parent child Browse files
Show More
@@ -15,6 +15,9 b' import sys, tempfile, zlib'
15 class PatchError(Exception):
15 class PatchError(Exception):
16 pass
16 pass
17
17
18 class NoHunks(PatchError):
19 pass
20
18 # helper functions
21 # helper functions
19
22
20 def copyfile(src, dst, basedir=None):
23 def copyfile(src, dst, basedir=None):
@@ -73,7 +76,7 b' def extract(ui, fileobj):'
73 ui.debug('From: %s\n' % user)
76 ui.debug('From: %s\n' % user)
74 diffs_seen = 0
77 diffs_seen = 0
75 ok_types = ('text/plain', 'text/x-diff', 'text/x-patch')
78 ok_types = ('text/plain', 'text/x-diff', 'text/x-patch')
76
79 message = ''
77 for part in msg.walk():
80 for part in msg.walk():
78 content_type = part.get_content_type()
81 content_type = part.get_content_type()
79 ui.debug('Content-Type: %s\n' % content_type)
82 ui.debug('Content-Type: %s\n' % content_type)
@@ -213,25 +216,83 b' def readgitpatch(fp, firstline):'
213 return (dopatch, gitpatches)
216 return (dopatch, gitpatches)
214
217
215 def patch(patchname, ui, strip=1, cwd=None, files={}):
218 def patch(patchname, ui, strip=1, cwd=None, files={}):
216 """apply the patch <patchname> to the working directory.
219 """apply <patchname> to the working directory.
217 a list of patched files is returned"""
220 returns whether patch was applied with fuzz factor."""
221 patcher = ui.config('ui', 'patch')
222 args = []
223 try:
224 if patcher:
225 return externalpatch(patcher, args, patchname, ui, strip, cwd,
226 files)
227 else:
228 try:
229 return internalpatch(patchname, ui, strip, cwd, files)
230 except NoHunks:
231 patcher = util.find_exe('gpatch') or util.find_exe('patch')
232 ui.debug('no valid hunks found; trying with %r instead\n' %
233 patcher)
234 if util.needbinarypatch():
235 args.append('--binary')
236 return externalpatch(patcher, args, patchname, ui, strip, cwd,
237 files)
238 except PatchError, err:
239 s = str(err)
240 if s:
241 raise util.Abort(s)
242 else:
243 raise util.Abort(_('patch failed to apply'))
244
245 def externalpatch(patcher, args, patchname, ui, strip, cwd, files):
246 """use <patcher> to apply <patchname> to the working directory.
247 returns whether patch was applied with fuzz factor."""
248
249 fuzz = False
250 if cwd:
251 args.append('-d %s' % util.shellquote(cwd))
252 fp = os.popen('%s %s -p%d < %s' % (patcher, ' '.join(args), strip,
253 util.shellquote(patchname)))
254
255 for line in fp:
256 line = line.rstrip()
257 ui.note(line + '\n')
258 if line.startswith('patching file '):
259 pf = util.parse_patch_output(line)
260 printed_file = False
261 files.setdefault(pf, (None, None))
262 elif line.find('with fuzz') >= 0:
263 fuzz = True
264 if not printed_file:
265 ui.warn(pf + '\n')
266 printed_file = True
267 ui.warn(line + '\n')
268 elif line.find('saving rejects to file') >= 0:
269 ui.warn(line + '\n')
270 elif line.find('FAILED') >= 0:
271 if not printed_file:
272 ui.warn(pf + '\n')
273 printed_file = True
274 ui.warn(line + '\n')
275 code = fp.close()
276 if code:
277 raise PatchError(_("patch command failed: %s") %
278 util.explain_exit(code)[0])
279 return fuzz
280
281 def internalpatch(patchname, ui, strip, cwd, files):
282 """use builtin patch to apply <patchname> to the working directory.
283 returns whether patch was applied with fuzz factor."""
218 fp = file(patchname)
284 fp = file(patchname)
219 fuzz = False
220 if cwd:
285 if cwd:
221 curdir = os.getcwd()
286 curdir = os.getcwd()
222 os.chdir(cwd)
287 os.chdir(cwd)
223 try:
288 try:
224 ret = applydiff(ui, fp, files, strip=strip)
289 ret = applydiff(ui, fp, files, strip=strip)
225 except PatchError, err:
290 finally:
226 ui.debug(err)
291 if cwd:
227 raise util.Abort(_("patch failed to apply"))
292 os.chdir(curdir)
228 if cwd:
229 os.chdir(curdir)
230 if ret < 0:
293 if ret < 0:
231 raise util.Abort(_("patch failed to apply"))
294 raise PatchError
232 if ret > 0:
295 return ret > 0
233 fuzz = True
234 return fuzz
235
296
236 # @@ -start,len +start,len @@ or @@ -start +start @@ if len is 1
297 # @@ -start,len +start,len @@ or @@ -start +start @@ if len is 1
237 unidesc = re.compile('@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@')
298 unidesc = re.compile('@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@')
@@ -936,7 +997,7 b' def applydiff(ui, fp, changed, strip=1, '
936 if rejects:
997 if rejects:
937 return -1
998 return -1
938 if hunknum == 0 and dopatch and not gitworkdone:
999 if hunknum == 0 and dopatch and not gitworkdone:
939 raise PatchError(_("no valid hunks found"))
1000 raise NoHunks
940 return err
1001 return err
941
1002
942 def diffopts(ui, opts={}, untrusted=False):
1003 def diffopts(ui, opts={}, untrusted=False):
General Comments 0
You need to be logged in to leave comments. Login now