Show More
@@ -1,3 +1,4 b'' | |||||
|
1 | ||||
1 | # queue.py - patch queues for mercurial |
|
2 | # queue.py - patch queues for mercurial | |
2 | # |
|
3 | # | |
3 | # Copyright 2005 Chris Mason <mason@suse.com> |
|
4 | # Copyright 2005 Chris Mason <mason@suse.com> | |
@@ -270,6 +271,48 b' class queue:' | |||||
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 | |
@@ -299,44 +342,8 b' class queue:' | |||||
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 | |
@@ -1289,6 +1296,47 b' def diff(ui, repo, *files, **opts):' | |||||
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 | |
@@ -1462,6 +1510,7 b' cmdtable = {' | |||||
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": |
@@ -29,6 +29,7 b' list of commands (use "hg help -v mq" to' | |||||
29 | qcommit commit changes in the queue repository |
|
29 | qcommit commit changes in the queue repository | |
30 | qdelete remove a patch from the series file |
|
30 | qdelete remove a patch from the series file | |
31 | qdiff diff of the current patch |
|
31 | qdiff diff of the current patch | |
|
32 | qfold fold the named patches into the current patch | |||
32 | qheader Print the header of the topmost or specified patch |
|
33 | qheader Print the header of the topmost or specified patch | |
33 | qimport import a patch |
|
34 | qimport import a patch | |
34 | qinit init a new queue repository |
|
35 | qinit init a new queue repository |
General Comments 0
You need to be logged in to leave comments.
Login now