268 self.applied_dirty = 1 |
269 self.applied_dirty = 1 |
269 if err: |
270 if err: |
270 return (err, head) |
271 return (err, head) |
271 return (0, head) |
272 return (0, head) |
272 |
273 |
|
274 def patch(self, repo, patchfile): |
|
275 '''Apply patchfile to the working directory. |
|
276 patchfile: file name of patch''' |
|
277 try: |
|
278 pp = util.find_in_path('gpatch', os.environ.get('PATH', ''), 'patch') |
|
279 f = os.popen("%s -d '%s' -p1 --no-backup-if-mismatch < '%s'" % |
|
280 (pp, repo.root, patchfile)) |
|
281 except: |
|
282 self.ui.warn("patch failed, unable to continue (try -v)\n") |
|
283 return (None, [], False) |
|
284 files = [] |
|
285 fuzz = False |
|
286 for l in f: |
|
287 l = l.rstrip('\r\n'); |
|
288 if self.ui.verbose: |
|
289 self.ui.warn(l + "\n") |
|
290 if l[:14] == 'patching file ': |
|
291 pf = os.path.normpath(l[14:]) |
|
292 # when patch finds a space in the file name, it puts |
|
293 # single quotes around the filename. strip them off |
|
294 if pf[0] == "'" and pf[-1] == "'": |
|
295 pf = pf[1:-1] |
|
296 if pf not in files: |
|
297 files.append(pf) |
|
298 printed_file = False |
|
299 file_str = l |
|
300 elif l.find('with fuzz') >= 0: |
|
301 if not printed_file: |
|
302 self.ui.warn(file_str + '\n') |
|
303 printed_file = True |
|
304 self.ui.warn(l + '\n') |
|
305 fuzz = True |
|
306 elif l.find('saving rejects to file') >= 0: |
|
307 self.ui.warn(l + '\n') |
|
308 elif l.find('FAILED') >= 0: |
|
309 if not printed_file: |
|
310 self.ui.warn(file_str + '\n') |
|
311 printed_file = True |
|
312 self.ui.warn(l + '\n') |
|
313 |
|
314 return (not f.close(), files, fuzz) |
|
315 |
273 def apply(self, repo, series, list=False, update_status=True, |
316 def apply(self, repo, series, list=False, update_status=True, |
274 strict=False, patchdir=None, merge=None, wlock=None): |
317 strict=False, patchdir=None, merge=None, wlock=None): |
275 # TODO unify with commands.py |
318 # TODO unify with commands.py |
276 if not patchdir: |
319 if not patchdir: |
277 patchdir = self.path |
320 patchdir = self.path |
297 else: |
340 else: |
298 if list: |
341 if list: |
299 message.append("\nimported patch %s" % patch) |
342 message.append("\nimported patch %s" % patch) |
300 message = '\n'.join(message) |
343 message = '\n'.join(message) |
301 |
344 |
302 try: |
345 (patcherr, files, fuzz) = self.patch(repo, pf) |
303 pp = util.find_in_path('gpatch', os.environ.get('PATH', ''), 'patch') |
346 patcherr = not patcherr |
304 f = os.popen("%s -d '%s' -p1 --no-backup-if-mismatch < '%s'" % |
|
305 (pp, repo.root, pf)) |
|
306 except: |
|
307 self.ui.warn("patch failed, unable to continue (try -v)\n") |
|
308 err = 1 |
|
309 break |
|
310 files = [] |
|
311 fuzz = False |
|
312 for l in f: |
|
313 l = l.rstrip('\r\n'); |
|
314 if self.ui.verbose: |
|
315 self.ui.warn(l + "\n") |
|
316 if l[:14] == 'patching file ': |
|
317 pf = os.path.normpath(l[14:]) |
|
318 # when patch finds a space in the file name, it puts |
|
319 # single quotes around the filename. strip them off |
|
320 if pf[0] == "'" and pf[-1] == "'": |
|
321 pf = pf[1:-1] |
|
322 if pf not in files: |
|
323 files.append(pf) |
|
324 printed_file = False |
|
325 file_str = l |
|
326 elif l.find('with fuzz') >= 0: |
|
327 if not printed_file: |
|
328 self.ui.warn(file_str + '\n') |
|
329 printed_file = True |
|
330 self.ui.warn(l + '\n') |
|
331 fuzz = True |
|
332 elif l.find('saving rejects to file') >= 0: |
|
333 self.ui.warn(l + '\n') |
|
334 elif l.find('FAILED') >= 0: |
|
335 if not printed_file: |
|
336 self.ui.warn(file_str + '\n') |
|
337 printed_file = True |
|
338 self.ui.warn(l + '\n') |
|
339 patcherr = f.close() |
|
340 |
347 |
341 if merge and len(files) > 0: |
348 if merge and len(files) > 0: |
342 # Mark as merged and update dirstate parent info |
349 # Mark as merged and update dirstate parent info |
343 repo.dirstate.update(repo.dirstate.filterfiles(files), 'm') |
350 repo.dirstate.update(repo.dirstate.filterfiles(files), 'm') |
344 p1, p2 = repo.dirstate.parents() |
351 p1, p2 = repo.dirstate.parents() |
1287 """diff of the current patch""" |
1294 """diff of the current patch""" |
1288 # deep in the dirstate code, the walkhelper method wants a list, not a tuple |
1295 # deep in the dirstate code, the walkhelper method wants a list, not a tuple |
1289 repo.mq.diff(repo, list(files)) |
1296 repo.mq.diff(repo, list(files)) |
1290 return 0 |
1297 return 0 |
1291 |
1298 |
|
1299 def fold(ui, repo, *files): |
|
1300 """fold the named patches into the current patch |
|
1301 Patches must not yet be applied.""" |
|
1302 q = repo.mq |
|
1303 |
|
1304 if not files: |
|
1305 raise util.Abort(_('qfold requires at least one patch name')) |
|
1306 if not q.check_toppatch(repo): |
|
1307 raise util.Abort(_('No patches applied\n')) |
|
1308 |
|
1309 parent = q.lookup('qtip') |
|
1310 patches = [] |
|
1311 messages = [] |
|
1312 for f in files: |
|
1313 patch = q.lookup(f) |
|
1314 if patch in patches or patch == parent: |
|
1315 self.ui.warn(_('Skipping already folded patch %s') % patch) |
|
1316 if q.isapplied(patch): |
|
1317 raise util.Abort(_('qfold cannot fold already applied patch %s') % patch) |
|
1318 patches.append(patch) |
|
1319 |
|
1320 for patch in patches: |
|
1321 messages.append(q.readheaders(patch)[0]) |
|
1322 pf = os.path.join(q.path, patch) |
|
1323 (patchsuccess, files, fuzz) = q.patch(repo, pf) |
|
1324 if not patchsuccess: |
|
1325 raise util.Abort(_('Error folding patch %s') % patch) |
|
1326 |
|
1327 message = q.readheaders(parent)[0] |
|
1328 for msg in messages: |
|
1329 message.append('* * *') |
|
1330 message.extend(msg) |
|
1331 message = '\n'.join(message) |
|
1332 |
|
1333 q.refresh(repo, msg=message) |
|
1334 |
|
1335 for patch in patches: |
|
1336 q.delete(repo, patch) |
|
1337 |
|
1338 q.save_dirty() |
|
1339 |
1292 def header(ui, repo, patch=None): |
1340 def header(ui, repo, patch=None): |
1293 """Print the header of the topmost or specified patch""" |
1341 """Print the header of the topmost or specified patch""" |
1294 q = repo.mq |
1342 q = repo.mq |
1295 |
1343 |
1296 if patch: |
1344 if patch: |
1460 (commit, |
1508 (commit, |
1461 commands.table["^commit|ci"][1], |
1509 commands.table["^commit|ci"][1], |
1462 'hg qcommit [OPTION]... [FILE]...'), |
1510 'hg qcommit [OPTION]... [FILE]...'), |
1463 "^qdiff": (diff, [], 'hg qdiff [FILE]...'), |
1511 "^qdiff": (diff, [], 'hg qdiff [FILE]...'), |
1464 "qdelete": (delete, [], 'hg qdelete PATCH'), |
1512 "qdelete": (delete, [], 'hg qdelete PATCH'), |
|
1513 'qfold': (fold, [], 'hg qfold PATCH...'), |
1465 'qheader': (header, [], |
1514 'qheader': (header, [], |
1466 _('hg qheader [PATCH]')), |
1515 _('hg qheader [PATCH]')), |
1467 "^qimport": |
1516 "^qimport": |
1468 (qimport, |
1517 (qimport, |
1469 [('e', 'existing', None, 'import file in patch dir'), |
1518 [('e', 'existing', None, 'import file in patch dir'), |