321 fns, matchfn, anypats = cmdutil.matchpats(repo, files, opts) |
321 fns, matchfn, anypats = cmdutil.matchpats(repo, files, opts) |
322 |
322 |
323 patch.diff(repo, node1, node2, fns, match=matchfn, |
323 patch.diff(repo, node1, node2, fns, match=matchfn, |
324 fp=fp, changes=changes, opts=self.diffopts()) |
324 fp=fp, changes=changes, opts=self.diffopts()) |
325 |
325 |
326 def mergeone(self, repo, mergeq, head, patch, rev, wlock): |
326 def mergeone(self, repo, mergeq, head, patch, rev): |
327 # first try just applying the patch |
327 # first try just applying the patch |
328 (err, n) = self.apply(repo, [ patch ], update_status=False, |
328 (err, n) = self.apply(repo, [ patch ], update_status=False, |
329 strict=True, merge=rev, wlock=wlock) |
329 strict=True, merge=rev) |
330 |
330 |
331 if err == 0: |
331 if err == 0: |
332 return (err, n) |
332 return (err, n) |
333 |
333 |
334 if n is None: |
334 if n is None: |
335 raise util.Abort(_("apply failed for patch %s") % patch) |
335 raise util.Abort(_("apply failed for patch %s") % patch) |
336 |
336 |
337 self.ui.warn("patch didn't work out, merging %s\n" % patch) |
337 self.ui.warn("patch didn't work out, merging %s\n" % patch) |
338 |
338 |
339 # apply failed, strip away that rev and merge. |
339 # apply failed, strip away that rev and merge. |
340 hg.clean(repo, head, wlock=wlock) |
340 hg.clean(repo, head) |
341 self.strip(repo, n, update=False, backup='strip', wlock=wlock) |
341 self.strip(repo, n, update=False, backup='strip') |
342 |
342 |
343 ctx = repo.changectx(rev) |
343 ctx = repo.changectx(rev) |
344 ret = hg.merge(repo, rev, wlock=wlock) |
344 ret = hg.merge(repo, rev) |
345 if ret: |
345 if ret: |
346 raise util.Abort(_("update returned %d") % ret) |
346 raise util.Abort(_("update returned %d") % ret) |
347 n = repo.commit(None, ctx.description(), ctx.user(), |
347 n = repo.commit(None, ctx.description(), ctx.user(), force=1) |
348 force=1, wlock=wlock) |
|
349 if n == None: |
348 if n == None: |
350 raise util.Abort(_("repo commit failed")) |
349 raise util.Abort(_("repo commit failed")) |
351 try: |
350 try: |
352 message, comments, user, date, patchfound = mergeq.readheaders(patch) |
351 message, comments, user, date, patchfound = mergeq.readheaders(patch) |
353 except: |
352 except: |
379 return pp[0] |
378 return pp[0] |
380 if p1 in arevs: |
379 if p1 in arevs: |
381 return pp[1] |
380 return pp[1] |
382 return pp[0] |
381 return pp[0] |
383 |
382 |
384 def mergepatch(self, repo, mergeq, series, wlock): |
383 def mergepatch(self, repo, mergeq, series): |
385 if len(self.applied) == 0: |
384 if len(self.applied) == 0: |
386 # each of the patches merged in will have two parents. This |
385 # each of the patches merged in will have two parents. This |
387 # can confuse the qrefresh, qdiff, and strip code because it |
386 # can confuse the qrefresh, qdiff, and strip code because it |
388 # needs to know which parent is actually in the patch queue. |
387 # needs to know which parent is actually in the patch queue. |
389 # so, we insert a merge marker with only one parent. This way |
388 # so, we insert a merge marker with only one parent. This way |
390 # the first patch in the queue is never a merge patch |
389 # the first patch in the queue is never a merge patch |
391 # |
390 # |
392 pname = ".hg.patches.merge.marker" |
391 pname = ".hg.patches.merge.marker" |
393 n = repo.commit(None, '[mq]: merge marker', user=None, force=1, |
392 n = repo.commit(None, '[mq]: merge marker', user=None, force=1) |
394 wlock=wlock) |
|
395 self.removeundo(repo) |
393 self.removeundo(repo) |
396 self.applied.append(statusentry(revlog.hex(n), pname)) |
394 self.applied.append(statusentry(revlog.hex(n), pname)) |
397 self.applied_dirty = 1 |
395 self.applied_dirty = 1 |
398 |
396 |
399 head = self.qparents(repo) |
397 head = self.qparents(repo) |
410 info = mergeq.isapplied(patch) |
408 info = mergeq.isapplied(patch) |
411 if not info: |
409 if not info: |
412 self.ui.warn("patch %s is not applied\n" % patch) |
410 self.ui.warn("patch %s is not applied\n" % patch) |
413 return (1, None) |
411 return (1, None) |
414 rev = revlog.bin(info[1]) |
412 rev = revlog.bin(info[1]) |
415 (err, head) = self.mergeone(repo, mergeq, head, patch, rev, wlock) |
413 (err, head) = self.mergeone(repo, mergeq, head, patch, rev) |
416 if head: |
414 if head: |
417 self.applied.append(statusentry(revlog.hex(head), patch)) |
415 self.applied.append(statusentry(revlog.hex(head), patch)) |
418 self.applied_dirty = 1 |
416 self.applied_dirty = 1 |
419 if err: |
417 if err: |
420 return (err, head) |
418 return (err, head) |
435 return (False, files, False) |
433 return (False, files, False) |
436 |
434 |
437 return (True, files, fuzz) |
435 return (True, files, fuzz) |
438 |
436 |
439 def apply(self, repo, series, list=False, update_status=True, |
437 def apply(self, repo, series, list=False, update_status=True, |
440 strict=False, patchdir=None, merge=None, wlock=None, |
438 strict=False, patchdir=None, merge=None, all_files={}): |
441 all_files={}): |
439 wlock = lock = tr = None |
442 lock = tr = None |
|
443 try: |
440 try: |
444 if not wlock: |
441 wlock = repo.wlock() |
445 wlock = repo.wlock() |
|
446 lock = repo.lock() |
442 lock = repo.lock() |
447 tr = repo.transaction() |
443 tr = repo.transaction() |
448 try: |
444 try: |
449 ret = self._apply(tr, repo, series, list, update_status, |
445 ret = self._apply(tr, repo, series, list, update_status, |
450 strict, patchdir, merge, wlock, |
446 strict, patchdir, merge, all_files=all_files) |
451 lock=lock, all_files=all_files) |
|
452 tr.close() |
447 tr.close() |
453 self.save_dirty() |
448 self.save_dirty() |
454 return ret |
449 return ret |
455 except: |
450 except: |
456 try: |
451 try: |
461 raise |
456 raise |
462 finally: |
457 finally: |
463 del lock, wlock, tr |
458 del lock, wlock, tr |
464 |
459 |
465 def _apply(self, tr, repo, series, list=False, update_status=True, |
460 def _apply(self, tr, repo, series, list=False, update_status=True, |
466 strict=False, patchdir=None, merge=None, wlock=None, |
461 strict=False, patchdir=None, merge=None, all_files={}): |
467 lock=None, all_files={}): |
|
468 # TODO unify with commands.py |
462 # TODO unify with commands.py |
469 if not patchdir: |
463 if not patchdir: |
470 patchdir = self.path |
464 patchdir = self.path |
471 err = 0 |
465 err = 0 |
472 n = None |
466 n = None |
509 repo.dirstate.remove(f) |
503 repo.dirstate.remove(f) |
510 for f in merged: |
504 for f in merged: |
511 repo.dirstate.merge(f) |
505 repo.dirstate.merge(f) |
512 p1, p2 = repo.dirstate.parents() |
506 p1, p2 = repo.dirstate.parents() |
513 repo.dirstate.setparents(p1, merge) |
507 repo.dirstate.setparents(p1, merge) |
514 files = patch.updatedir(self.ui, repo, files, wlock=wlock) |
508 files = patch.updatedir(self.ui, repo, files) |
515 n = repo.commit(files, message, user, date, force=1, lock=lock, |
509 n = repo.commit(files, message, user, date, force=1) |
516 wlock=wlock) |
|
517 |
510 |
518 if n == None: |
511 if n == None: |
519 raise util.Abort(_("repo commit failed")) |
512 raise util.Abort(_("repo commit failed")) |
520 |
513 |
521 if update_status: |
514 if update_status: |
621 self.check_toppatch(repo) |
614 self.check_toppatch(repo) |
622 wlock = repo.wlock() |
615 wlock = repo.wlock() |
623 try: |
616 try: |
624 insert = self.full_series_end() |
617 insert = self.full_series_end() |
625 if msg: |
618 if msg: |
626 n = repo.commit(commitfiles, msg, force=True, wlock=wlock) |
619 n = repo.commit(commitfiles, msg, force=True) |
627 else: |
620 else: |
628 n = repo.commit(commitfiles, |
621 n = repo.commit(commitfiles, "[mq]: %s" % patch, force=True) |
629 "[mq]: %s" % patch, force=True, wlock=wlock) |
|
630 if n == None: |
622 if n == None: |
631 raise util.Abort(_("repo commit failed")) |
623 raise util.Abort(_("repo commit failed")) |
632 self.full_series[insert:insert] = [patch] |
624 self.full_series[insert:insert] = [patch] |
633 self.applied.append(statusentry(revlog.hex(n), patch)) |
625 self.applied.append(statusentry(revlog.hex(n), patch)) |
634 self.parse_series() |
626 self.parse_series() |
646 self.refresh(repo, short=True) |
638 self.refresh(repo, short=True) |
647 self.removeundo(repo) |
639 self.removeundo(repo) |
648 finally: |
640 finally: |
649 del wlock |
641 del wlock |
650 |
642 |
651 def strip(self, repo, rev, update=True, backup="all", wlock=None): |
643 def strip(self, repo, rev, update=True, backup="all"): |
652 lock = None |
644 wlock = lock = None |
653 try: |
645 try: |
654 if not wlock: |
646 wlock = repo.wlock() |
655 wlock = repo.wlock() |
|
656 lock = repo.lock() |
647 lock = repo.lock() |
657 |
648 |
658 if update: |
649 if update: |
659 self.check_localchanges(repo, refresh=False) |
650 self.check_localchanges(repo, refresh=False) |
660 urev = self.qparents(repo, rev) |
651 urev = self.qparents(repo, rev) |
661 hg.clean(repo, urev, wlock=wlock) |
652 hg.clean(repo, urev) |
662 repo.dirstate.write() |
653 repo.dirstate.write() |
663 |
654 |
664 self.removeundo(repo) |
655 self.removeundo(repo) |
665 repair.strip(self.ui, repo, rev, backup) |
656 repair.strip(self.ui, repo, rev, backup) |
666 finally: |
657 finally: |
746 if i + off < len(self.series): |
737 if i + off < len(self.series): |
747 return self.series[i + off] |
738 return self.series[i + off] |
748 raise util.Abort(_("patch %s not in series") % patch) |
739 raise util.Abort(_("patch %s not in series") % patch) |
749 |
740 |
750 def push(self, repo, patch=None, force=False, list=False, |
741 def push(self, repo, patch=None, force=False, list=False, |
751 mergeq=None, wlock=None): |
742 mergeq=None): |
752 if not wlock: |
743 wlock = repo.wlock() |
753 wlock = repo.wlock() |
|
754 try: |
744 try: |
755 patch = self.lookup(patch) |
745 patch = self.lookup(patch) |
756 # Suppose our series file is: A B C and the current 'top' |
746 # Suppose our series file is: A B C and the current 'top' |
757 # patch is B. qpush C should be performed (moving forward) |
747 # patch is B. qpush C should be performed (moving forward) |
758 # qpush B is a NOP (no change) qpush A is an error (can't |
748 # qpush B is a NOP (no change) qpush A is an error (can't |
792 end = self.series.index(patch, start) + 1 |
782 end = self.series.index(patch, start) + 1 |
793 s = self.series[start:end] |
783 s = self.series[start:end] |
794 all_files = {} |
784 all_files = {} |
795 try: |
785 try: |
796 if mergeq: |
786 if mergeq: |
797 ret = self.mergepatch(repo, mergeq, s, wlock) |
787 ret = self.mergepatch(repo, mergeq, s) |
798 else: |
788 else: |
799 ret = self.apply(repo, s, list, wlock=wlock, |
789 ret = self.apply(repo, s, list, all_files=all_files) |
800 all_files=all_files) |
|
801 except: |
790 except: |
802 self.ui.warn(_('cleaning up working directory...')) |
791 self.ui.warn(_('cleaning up working directory...')) |
803 node = repo.dirstate.parents()[0] |
792 node = repo.dirstate.parents()[0] |
804 hg.revert(repo, node, None, wlock) |
793 hg.revert(repo, node, None) |
805 unknown = repo.status(wlock=wlock)[4] |
794 unknown = repo.status()[4] |
806 # only remove unknown files that we know we touched or |
795 # only remove unknown files that we know we touched or |
807 # created while patching |
796 # created while patching |
808 for f in unknown: |
797 for f in unknown: |
809 if f in all_files: |
798 if f in all_files: |
810 util.unlink(repo.wjoin(f)) |
799 util.unlink(repo.wjoin(f)) |
818 self.ui.write("Now at: %s\n" % top) |
807 self.ui.write("Now at: %s\n" % top) |
819 return ret[0] |
808 return ret[0] |
820 finally: |
809 finally: |
821 del wlock |
810 del wlock |
822 |
811 |
823 def pop(self, repo, patch=None, force=False, update=True, all=False, |
812 def pop(self, repo, patch=None, force=False, update=True, all=False): |
824 wlock=None): |
|
825 def getfile(f, rev): |
813 def getfile(f, rev): |
826 t = repo.file(f).read(rev) |
814 t = repo.file(f).read(rev) |
827 repo.wfile(f, "w").write(t) |
815 repo.wfile(f, "w").write(t) |
828 |
816 |
829 if not wlock: |
817 wlock = repo.wlock() |
830 wlock = repo.wlock() |
|
831 try: |
818 try: |
832 if patch: |
819 if patch: |
833 # index, rev, patch |
820 # index, rev, patch |
834 info = self.isapplied(patch) |
821 info = self.isapplied(patch) |
835 if not info: |
822 if not info: |
897 raise |
884 raise |
898 try: os.removedirs(os.path.dirname(repo.wjoin(f))) |
885 try: os.removedirs(os.path.dirname(repo.wjoin(f))) |
899 except: pass |
886 except: pass |
900 repo.dirstate.forget(f) |
887 repo.dirstate.forget(f) |
901 repo.dirstate.setparents(qp, revlog.nullid) |
888 repo.dirstate.setparents(qp, revlog.nullid) |
902 self.strip(repo, rev, update=False, backup='strip', wlock=wlock) |
889 self.strip(repo, rev, update=False, backup='strip') |
903 del self.applied[start:end] |
890 del self.applied[start:end] |
904 if len(self.applied): |
891 if len(self.applied): |
905 self.ui.write("Now at: %s\n" % self.applied[-1].name) |
892 self.ui.write("Now at: %s\n" % self.applied[-1].name) |
906 else: |
893 else: |
907 self.ui.write("Patch queue now empty\n") |
894 self.ui.write("Patch queue now empty\n") |
1073 message = "\n".join(message) |
1060 message = "\n".join(message) |
1074 else: |
1061 else: |
1075 message = msg |
1062 message = msg |
1076 |
1063 |
1077 self.strip(repo, top, update=False, |
1064 self.strip(repo, top, update=False, |
1078 backup='strip', wlock=wlock) |
1065 backup='strip') |
1079 n = repo.commit(filelist, message, changes[1], match=matchfn, |
1066 n = repo.commit(filelist, message, changes[1], match=matchfn, |
1080 force=1, wlock=wlock) |
1067 force=1) |
1081 self.applied[-1] = statusentry(revlog.hex(n), patchfn) |
1068 self.applied[-1] = statusentry(revlog.hex(n), patchfn) |
1082 self.applied_dirty = 1 |
1069 self.applied_dirty = 1 |
1083 self.removeundo(repo) |
1070 self.removeundo(repo) |
1084 else: |
1071 else: |
1085 self.printdiff(repo, patchparent, fp=patchf) |
1072 self.printdiff(repo, patchparent, fp=patchf) |
1095 try: os.removedirs(os.path.dirname(f)) |
1082 try: os.removedirs(os.path.dirname(f)) |
1096 except: pass |
1083 except: pass |
1097 # forget the file copies in the dirstate |
1084 # forget the file copies in the dirstate |
1098 # push should readd the files later on |
1085 # push should readd the files later on |
1099 repo.dirstate.forget(a) |
1086 repo.dirstate.forget(a) |
1100 self.pop(repo, force=True, wlock=wlock) |
1087 self.pop(repo, force=True) |
1101 self.push(repo, force=True, wlock=wlock) |
1088 self.push(repo, force=True) |
1102 finally: |
1089 finally: |
1103 del wlock |
1090 del wlock |
1104 |
1091 |
1105 def init(self, repo, create=False): |
1092 def init(self, repo, create=False): |
1106 if not create and os.path.isdir(self.path): |
1093 if not create and os.path.isdir(self.path): |