comparison hgext/mq.py @ 4961:126f527b3ba3

Make repo locks recursive, eliminate all passing of lock/wlock
author Matt Mackall <mpm@selenic.com>
date Sat, 21 Jul 2007 16:02:10 -0500
parents 97b734fb9c6f
children 30d4d8985dd8
comparison
equal deleted inserted replaced
4960:5c5d23d93447 4961:126f527b3ba3
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):
1896 r = q.qrepo() 1883 r = q.qrepo()
1897 if r: 1884 if r:
1898 wlock = r.wlock() 1885 wlock = r.wlock()
1899 try: 1886 try:
1900 if r.dirstate[name] == 'r': 1887 if r.dirstate[name] == 'r':
1901 r.undelete([name], wlock) 1888 r.undelete([name])
1902 r.copy(patch, name, wlock) 1889 r.copy(patch, name)
1903 r.remove([patch], False, wlock) 1890 r.remove([patch], False)
1904 finally: 1891 finally:
1905 del wlock 1892 del wlock
1906 1893
1907 q.save_dirty() 1894 q.save_dirty()
1908 1895