Mercurial > hg
comparison hgext/mq.py @ 10187:fcc15ba18c03
Merge with stable
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Fri, 01 Jan 2010 15:33:51 -0600 |
parents | 926c436964b4 296a0b14a686 |
children | 8161127a638f |
comparison
equal
deleted
inserted
replaced
10183:572dd10fa308 | 10187:fcc15ba18c03 |
---|---|
223 self.series_path = "series" | 223 self.series_path = "series" |
224 self.status_path = "status" | 224 self.status_path = "status" |
225 self.guards_path = "guards" | 225 self.guards_path = "guards" |
226 self.active_guards = None | 226 self.active_guards = None |
227 self.guards_dirty = False | 227 self.guards_dirty = False |
228 self._diffopts = None | |
229 | 228 |
230 @util.propertycache | 229 @util.propertycache |
231 def applied(self): | 230 def applied(self): |
232 if os.path.exists(self.join(self.status_path)): | 231 if os.path.exists(self.join(self.status_path)): |
233 lines = self.opener(self.status_path).read().splitlines() | 232 lines = self.opener(self.status_path).read().splitlines() |
257 self.applied_dirty = 0 | 256 self.applied_dirty = 0 |
258 self.series_dirty = 0 | 257 self.series_dirty = 0 |
259 self.guards_dirty = False | 258 self.guards_dirty = False |
260 self.active_guards = None | 259 self.active_guards = None |
261 | 260 |
262 def diffopts(self): | 261 def diffopts(self, opts={}, patchfn=None): |
263 if self._diffopts is None: | 262 diffopts = patch.diffopts(self.ui, opts) |
264 self._diffopts = patch.diffopts(self.ui) | 263 if patchfn: |
265 return self._diffopts | 264 diffopts = self.patchopts(diffopts, patchfn) |
265 return diffopts | |
266 | |
267 def patchopts(self, diffopts, *patches): | |
268 """Return a copy of input diff options with git set to true if | |
269 referenced patch is a git patch. | |
270 """ | |
271 diffopts = diffopts.copy() | |
272 for patchfn in patches: | |
273 patchf = self.opener(patchfn, 'r') | |
274 # if the patch was a git patch, refresh it as a git patch | |
275 for line in patchf: | |
276 if line.startswith('diff --git'): | |
277 diffopts.git = True | |
278 break | |
279 patchf.close() | |
280 return diffopts | |
266 | 281 |
267 def join(self, *p): | 282 def join(self, *p): |
268 return os.path.join(self.path, *p) | 283 return os.path.join(self.path, *p) |
269 | 284 |
270 def find_series(self, patch): | 285 def find_series(self, patch): |
416 try: | 431 try: |
417 os.unlink(undo) | 432 os.unlink(undo) |
418 except OSError, inst: | 433 except OSError, inst: |
419 self.ui.warn(_('error removing undo: %s\n') % str(inst)) | 434 self.ui.warn(_('error removing undo: %s\n') % str(inst)) |
420 | 435 |
421 def printdiff(self, repo, node1, node2=None, files=None, | 436 def printdiff(self, repo, diffopts, node1, node2=None, files=None, |
422 fp=None, changes=None, opts={}): | 437 fp=None, changes=None, opts={}): |
423 stat = opts.get('stat') | 438 stat = opts.get('stat') |
424 if stat: | 439 if stat: |
425 opts['unified'] = '0' | 440 opts['unified'] = '0' |
426 | 441 |
427 m = cmdutil.match(repo, files, opts) | 442 m = cmdutil.match(repo, files, opts) |
428 chunks = patch.diff(repo, node1, node2, m, changes, self.diffopts()) | 443 chunks = patch.diff(repo, node1, node2, m, changes, diffopts) |
429 write = fp is None and repo.ui.write or fp.write | 444 write = fp is None and repo.ui.write or fp.write |
430 if stat: | 445 if stat: |
431 width = self.ui.interactive() and util.termwidth() or 80 | 446 width = self.ui.interactive() and util.termwidth() or 80 |
432 write(patch.diffstat(util.iterlines(chunks), width=width, | 447 write(patch.diffstat(util.iterlines(chunks), width=width, |
433 git=self.diffopts().git)) | 448 git=diffopts.git)) |
434 else: | 449 else: |
435 for chunk in chunks: | 450 for chunk in chunks: |
436 write(chunk) | 451 write(chunk) |
437 | 452 |
438 def mergeone(self, repo, mergeq, head, patch, rev): | 453 def mergeone(self, repo, mergeq, head, patch, rev, diffopts): |
439 # first try just applying the patch | 454 # first try just applying the patch |
440 (err, n) = self.apply(repo, [ patch ], update_status=False, | 455 (err, n) = self.apply(repo, [ patch ], update_status=False, |
441 strict=True, merge=rev) | 456 strict=True, merge=rev) |
442 | 457 |
443 if err == 0: | 458 if err == 0: |
462 try: | 477 try: |
463 ph = patchheader(mergeq.join(patch)) | 478 ph = patchheader(mergeq.join(patch)) |
464 except: | 479 except: |
465 raise util.Abort(_("unable to read %s") % patch) | 480 raise util.Abort(_("unable to read %s") % patch) |
466 | 481 |
482 diffopts = self.patchopts(diffopts, patch) | |
467 patchf = self.opener(patch, "w") | 483 patchf = self.opener(patch, "w") |
468 comments = str(ph) | 484 comments = str(ph) |
469 if comments: | 485 if comments: |
470 patchf.write(comments) | 486 patchf.write(comments) |
471 self.printdiff(repo, head, n, fp=patchf) | 487 self.printdiff(repo, diffopts, head, n, fp=patchf) |
472 patchf.close() | 488 patchf.close() |
473 self.removeundo(repo) | 489 self.removeundo(repo) |
474 return (0, n) | 490 return (0, n) |
475 | 491 |
476 def qparents(self, repo, rev=None): | 492 def qparents(self, repo, rev=None): |
490 return pp[0] | 506 return pp[0] |
491 if p1 in arevs: | 507 if p1 in arevs: |
492 return pp[1] | 508 return pp[1] |
493 return pp[0] | 509 return pp[0] |
494 | 510 |
495 def mergepatch(self, repo, mergeq, series): | 511 def mergepatch(self, repo, mergeq, series, diffopts): |
496 if len(self.applied) == 0: | 512 if len(self.applied) == 0: |
497 # each of the patches merged in will have two parents. This | 513 # each of the patches merged in will have two parents. This |
498 # can confuse the qrefresh, qdiff, and strip code because it | 514 # can confuse the qrefresh, qdiff, and strip code because it |
499 # needs to know which parent is actually in the patch queue. | 515 # needs to know which parent is actually in the patch queue. |
500 # so, we insert a merge marker with only one parent. This way | 516 # so, we insert a merge marker with only one parent. This way |
520 info = mergeq.isapplied(patch) | 536 info = mergeq.isapplied(patch) |
521 if not info: | 537 if not info: |
522 self.ui.warn(_("patch %s is not applied\n") % patch) | 538 self.ui.warn(_("patch %s is not applied\n") % patch) |
523 return (1, None) | 539 return (1, None) |
524 rev = bin(info[1]) | 540 rev = bin(info[1]) |
525 (err, head) = self.mergeone(repo, mergeq, head, patch, rev) | 541 err, head = self.mergeone(repo, mergeq, head, patch, rev, diffopts) |
526 if head: | 542 if head: |
527 self.applied.append(statusentry(hex(head), patch)) | 543 self.applied.append(statusentry(hex(head), patch)) |
528 self.applied_dirty = 1 | 544 self.applied_dirty = 1 |
529 if err: | 545 if err: |
530 return (err, head) | 546 return (err, head) |
755 force = opts.get('force') | 771 force = opts.get('force') |
756 user = opts.get('user') | 772 user = opts.get('user') |
757 date = opts.get('date') | 773 date = opts.get('date') |
758 if date: | 774 if date: |
759 date = util.parsedate(date) | 775 date = util.parsedate(date) |
776 diffopts = self.diffopts({'git': opts.get('git')}) | |
760 self.check_reserved_name(patchfn) | 777 self.check_reserved_name(patchfn) |
761 if os.path.exists(self.join(patchfn)): | 778 if os.path.exists(self.join(patchfn)): |
762 raise util.Abort(_('patch "%s" already exists') % patchfn) | 779 raise util.Abort(_('patch "%s" already exists') % patchfn) |
763 if opts.get('include') or opts.get('exclude') or pats: | 780 if opts.get('include') or opts.get('exclude') or pats: |
764 match = cmdutil.match(repo, pats, opts) | 781 match = cmdutil.match(repo, pats, opts) |
804 self.applied_dirty = 1 | 821 self.applied_dirty = 1 |
805 if msg: | 822 if msg: |
806 msg = msg + "\n\n" | 823 msg = msg + "\n\n" |
807 p.write(msg) | 824 p.write(msg) |
808 if commitfiles: | 825 if commitfiles: |
809 diffopts = self.diffopts() | |
810 if opts.get('git'): diffopts.git = True | |
811 parent = self.qparents(repo, n) | 826 parent = self.qparents(repo, n) |
812 chunks = patch.diff(repo, node1=parent, node2=n, | 827 chunks = patch.diff(repo, node1=parent, node2=n, |
813 match=match, opts=diffopts) | 828 match=match, opts=diffopts) |
814 for chunk in chunks: | 829 for chunk in chunks: |
815 p.write(chunk) | 830 p.write(chunk) |
930 return self.series[i + off] | 945 return self.series[i + off] |
931 raise util.Abort(_("patch %s not in series") % patch) | 946 raise util.Abort(_("patch %s not in series") % patch) |
932 | 947 |
933 def push(self, repo, patch=None, force=False, list=False, | 948 def push(self, repo, patch=None, force=False, list=False, |
934 mergeq=None, all=False): | 949 mergeq=None, all=False): |
950 diffopts = self.diffopts() | |
935 wlock = repo.wlock() | 951 wlock = repo.wlock() |
936 try: | 952 try: |
937 if repo.dirstate.parents()[0] not in repo.heads(): | 953 if repo.dirstate.parents()[0] not in repo.heads(): |
938 self.ui.status(_("(working directory not at a head)\n")) | 954 self.ui.status(_("(working directory not at a head)\n")) |
939 | 955 |
992 | 1008 |
993 s = self.series[start:end] | 1009 s = self.series[start:end] |
994 all_files = {} | 1010 all_files = {} |
995 try: | 1011 try: |
996 if mergeq: | 1012 if mergeq: |
997 ret = self.mergepatch(repo, mergeq, s) | 1013 ret = self.mergepatch(repo, mergeq, s, diffopts) |
998 else: | 1014 else: |
999 ret = self.apply(repo, s, list, all_files=all_files) | 1015 ret = self.apply(repo, s, list, all_files=all_files) |
1000 except: | 1016 except: |
1001 self.ui.warn(_('cleaning up working directory...')) | 1017 self.ui.warn(_('cleaning up working directory...')) |
1002 node = repo.dirstate.parents()[0] | 1018 node = repo.dirstate.parents()[0] |
1135 qp = self.qparents(repo, top) | 1151 qp = self.qparents(repo, top) |
1136 if opts.get('reverse'): | 1152 if opts.get('reverse'): |
1137 node1, node2 = None, qp | 1153 node1, node2 = None, qp |
1138 else: | 1154 else: |
1139 node1, node2 = qp, None | 1155 node1, node2 = qp, None |
1140 self._diffopts = patch.diffopts(self.ui, opts) | 1156 diffopts = self.diffopts(opts) |
1141 self.printdiff(repo, node1, node2, files=pats, opts=opts) | 1157 self.printdiff(repo, diffopts, node1, node2, files=pats, opts=opts) |
1142 | 1158 |
1143 def refresh(self, repo, pats=None, **opts): | 1159 def refresh(self, repo, pats=None, **opts): |
1144 if len(self.applied) == 0: | 1160 if len(self.applied) == 0: |
1145 self.ui.write(_("no patches applied\n")) | 1161 self.ui.write(_("no patches applied\n")) |
1146 return 1 | 1162 return 1 |
1157 if repo.changelog.heads(top) != [top]: | 1173 if repo.changelog.heads(top) != [top]: |
1158 raise util.Abort(_("cannot refresh a revision with children")) | 1174 raise util.Abort(_("cannot refresh a revision with children")) |
1159 cparents = repo.changelog.parents(top) | 1175 cparents = repo.changelog.parents(top) |
1160 patchparent = self.qparents(repo, top) | 1176 patchparent = self.qparents(repo, top) |
1161 ph = patchheader(self.join(patchfn)) | 1177 ph = patchheader(self.join(patchfn)) |
1178 diffopts = self.diffopts({'git': opts.get('git')}, patchfn) | |
1162 if msg: | 1179 if msg: |
1163 ph.setmessage(msg) | 1180 ph.setmessage(msg) |
1164 if newuser: | 1181 if newuser: |
1165 ph.setuser(newuser) | 1182 ph.setuser(newuser) |
1166 if newdate: | 1183 if newdate: |
1179 | 1196 |
1180 comments = str(ph) | 1197 comments = str(ph) |
1181 if comments: | 1198 if comments: |
1182 patchf.write(comments) | 1199 patchf.write(comments) |
1183 | 1200 |
1184 if opts.get('git'): | |
1185 self.diffopts().git = True | |
1186 tip = repo.changelog.tip() | 1201 tip = repo.changelog.tip() |
1187 if top == tip: | 1202 if top == tip: |
1188 # if the top of our patch queue is also the tip, there is an | 1203 # if the top of our patch queue is also the tip, there is an |
1189 # optimization here. We update the dirstate in place and strip | 1204 # optimization here. We update the dirstate in place and strip |
1190 # off the tip commit. Then just commit the current directory | 1205 # off the tip commit. Then just commit the current directory |
1246 r = list(set(dd)) | 1261 r = list(set(dd)) |
1247 a = list(set(aa)) | 1262 a = list(set(aa)) |
1248 c = [filter(matchfn, l) for l in (m, a, r)] | 1263 c = [filter(matchfn, l) for l in (m, a, r)] |
1249 match = cmdutil.matchfiles(repo, set(c[0] + c[1] + c[2])) | 1264 match = cmdutil.matchfiles(repo, set(c[0] + c[1] + c[2])) |
1250 chunks = patch.diff(repo, patchparent, match=match, | 1265 chunks = patch.diff(repo, patchparent, match=match, |
1251 changes=c, opts=self.diffopts()) | 1266 changes=c, opts=diffopts) |
1252 for chunk in chunks: | 1267 for chunk in chunks: |
1253 patchf.write(chunk) | 1268 patchf.write(chunk) |
1254 | 1269 |
1255 try: | 1270 try: |
1256 if self.diffopts().git: | 1271 if diffopts.git: |
1257 copies = {} | 1272 copies = {} |
1258 for dst in a: | 1273 for dst in a: |
1259 src = repo.dirstate.copied(dst) | 1274 src = repo.dirstate.copied(dst) |
1260 # during qfold, the source file for copies may | 1275 # during qfold, the source file for copies may |
1261 # be removed. Treat this as a simple add. | 1276 # be removed. Treat this as a simple add. |
1330 self.save_dirty() | 1345 self.save_dirty() |
1331 self.ui.warn(_('refresh interrupted while patch was popped! ' | 1346 self.ui.warn(_('refresh interrupted while patch was popped! ' |
1332 '(revert --all, qpush to recover)\n')) | 1347 '(revert --all, qpush to recover)\n')) |
1333 raise | 1348 raise |
1334 else: | 1349 else: |
1335 self.printdiff(repo, patchparent, fp=patchf) | 1350 self.printdiff(repo, diffopts, patchparent, fp=patchf) |
1336 patchf.rename() | 1351 patchf.rename() |
1337 added = repo.status()[1] | 1352 added = repo.status()[1] |
1338 for a in added: | 1353 for a in added: |
1339 f = repo.wjoin(a) | 1354 f = repo.wjoin(a) |
1340 try: | 1355 try: |
1610 if heads != [repo.changelog.node(rev[0])]: | 1625 if heads != [repo.changelog.node(rev[0])]: |
1611 raise util.Abort(_('revision %d has unmanaged children') | 1626 raise util.Abort(_('revision %d has unmanaged children') |
1612 % rev[0]) | 1627 % rev[0]) |
1613 lastparent = None | 1628 lastparent = None |
1614 | 1629 |
1615 if git: | 1630 diffopts = self.diffopts({'git': git}) |
1616 self.diffopts().git = True | |
1617 | |
1618 for r in rev: | 1631 for r in rev: |
1619 p1, p2 = repo.changelog.parentrevs(r) | 1632 p1, p2 = repo.changelog.parentrevs(r) |
1620 n = repo.changelog.node(r) | 1633 n = repo.changelog.node(r) |
1621 if p2 != nullrev: | 1634 if p2 != nullrev: |
1622 raise util.Abort(_('cannot import merge revision %d') % r) | 1635 raise util.Abort(_('cannot import merge revision %d') % r) |
1631 checkseries(patchname) | 1644 checkseries(patchname) |
1632 checkfile(patchname) | 1645 checkfile(patchname) |
1633 self.full_series.insert(0, patchname) | 1646 self.full_series.insert(0, patchname) |
1634 | 1647 |
1635 patchf = self.opener(patchname, "w") | 1648 patchf = self.opener(patchname, "w") |
1636 patch.export(repo, [n], fp=patchf, opts=self.diffopts()) | 1649 patch.export(repo, [n], fp=patchf, opts=diffopts) |
1637 patchf.close() | 1650 patchf.close() |
1638 | 1651 |
1639 se = statusentry(hex(n), patchname) | 1652 se = statusentry(hex(n), patchname) |
1640 self.applied.insert(0, se) | 1653 self.applied.insert(0, se) |
1641 | 1654 |
2063 message = '\n'.join(message) | 2076 message = '\n'.join(message) |
2064 | 2077 |
2065 if opts['edit']: | 2078 if opts['edit']: |
2066 message = ui.edit(message, user or ui.username()) | 2079 message = ui.edit(message, user or ui.username()) |
2067 | 2080 |
2068 q.refresh(repo, msg=message) | 2081 diffopts = q.patchopts(q.diffopts(), *patches) |
2082 q.refresh(repo, msg=message, git=diffopts.git) | |
2069 q.delete(repo, patches, opts) | 2083 q.delete(repo, patches, opts) |
2070 q.save_dirty() | 2084 q.save_dirty() |
2071 | 2085 |
2072 def goto(ui, repo, patch, **opts): | 2086 def goto(ui, repo, patch, **opts): |
2073 '''push or pop patches until named patch is at top of stack''' | 2087 '''push or pop patches until named patch is at top of stack''' |