##// END OF EJS Templates
New mq command qfold: Merge patches into the current patch....
Brendan Cully -
r2748:752b9475 default
parent child Browse files
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