comparison hgext/mq.py @ 4712:f49fcbb325bc

Merge with mpm
author Brendan Cully <brendan@kublai.com>
date Mon, 25 Jun 2007 10:34:53 -0700
parents c71bf1d251ad 18e91c9def0c
children c29ee52e0b68
comparison
equal deleted inserted replaced
4711:c71bf1d251ad 4712:f49fcbb325bc
28 remove patch from applied stack qpop 28 remove patch from applied stack qpop
29 refresh contents of top applied patch qrefresh 29 refresh contents of top applied patch qrefresh
30 ''' 30 '''
31 31
32 from mercurial.i18n import _ 32 from mercurial.i18n import _
33 from mercurial import commands, cmdutil, hg, patch, revlog, util, changegroup 33 from mercurial import commands, cmdutil, hg, patch, revlog, util
34 from mercurial import repair
34 import os, sys, re, errno 35 import os, sys, re, errno
35 36
36 commands.norepo += " qclone qversion" 37 commands.norepo += " qclone qversion"
37 38
38 # Patch names looks like unix-file names. 39 # Patch names looks like unix-file names.
627 if commitfiles: 628 if commitfiles:
628 self.refresh(repo, short=True) 629 self.refresh(repo, short=True)
629 self.removeundo(repo) 630 self.removeundo(repo)
630 631
631 def strip(self, repo, rev, update=True, backup="all", wlock=None): 632 def strip(self, repo, rev, update=True, backup="all", wlock=None):
632 def limitheads(chlog, stop):
633 """return the list of all nodes that have no children"""
634 p = {}
635 h = []
636 stoprev = 0
637 if stop in chlog.nodemap:
638 stoprev = chlog.rev(stop)
639
640 for r in xrange(chlog.count() - 1, -1, -1):
641 n = chlog.node(r)
642 if n not in p:
643 h.append(n)
644 if n == stop:
645 break
646 if r < stoprev:
647 break
648 for pn in chlog.parents(n):
649 p[pn] = 1
650 return h
651
652 def bundle(cg):
653 backupdir = repo.join("strip-backup")
654 if not os.path.isdir(backupdir):
655 os.mkdir(backupdir)
656 name = os.path.join(backupdir, "%s" % revlog.short(rev))
657 name = savename(name)
658 self.ui.warn("saving bundle to %s\n" % name)
659 return changegroup.writebundle(cg, name, "HG10BZ")
660
661 def stripall(revnum):
662 mm = repo.changectx(rev).manifest()
663 seen = {}
664
665 for x in xrange(revnum, repo.changelog.count()):
666 for f in repo.changectx(x).files():
667 if f in seen:
668 continue
669 seen[f] = 1
670 if f in mm:
671 filerev = mm[f]
672 else:
673 filerev = 0
674 seen[f] = filerev
675 # we go in two steps here so the strip loop happens in a
676 # sensible order. When stripping many files, this helps keep
677 # our disk access patterns under control.
678 seen_list = seen.keys()
679 seen_list.sort()
680 for f in seen_list:
681 ff = repo.file(f)
682 filerev = seen[f]
683 if filerev != 0:
684 if filerev in ff.nodemap:
685 filerev = ff.rev(filerev)
686 else:
687 filerev = 0
688 ff.strip(filerev, revnum)
689
690 if not wlock: 633 if not wlock:
691 wlock = repo.wlock() 634 wlock = repo.wlock()
692 lock = repo.lock() 635 lock = repo.lock()
693 chlog = repo.changelog
694 # TODO delete the undo files, and handle undo of merge sets
695 pp = chlog.parents(rev)
696 revnum = chlog.rev(rev)
697 636
698 if update: 637 if update:
699 self.check_localchanges(repo, refresh=False) 638 self.check_localchanges(repo, refresh=False)
700 urev = self.qparents(repo, rev) 639 urev = self.qparents(repo, rev)
701 hg.clean(repo, urev, wlock=wlock) 640 hg.clean(repo, urev, wlock=wlock)
702 repo.dirstate.write() 641 repo.dirstate.write()
703 642
704 # save is a list of all the branches we are truncating away
705 # that we actually want to keep. changegroup will be used
706 # to preserve them and add them back after the truncate
707 saveheads = []
708 savebases = {}
709
710 heads = limitheads(chlog, rev)
711 seen = {}
712
713 # search through all the heads, finding those where the revision
714 # we want to strip away is an ancestor. Also look for merges
715 # that might be turned into new heads by the strip.
716 while heads:
717 h = heads.pop()
718 n = h
719 while True:
720 seen[n] = 1
721 pp = chlog.parents(n)
722 if pp[1] != revlog.nullid:
723 for p in pp:
724 if chlog.rev(p) > revnum and p not in seen:
725 heads.append(p)
726 if pp[0] == revlog.nullid:
727 break
728 if chlog.rev(pp[0]) < revnum:
729 break
730 n = pp[0]
731 if n == rev:
732 break
733 r = chlog.reachable(h, rev)
734 if rev not in r:
735 saveheads.append(h)
736 for x in r:
737 if chlog.rev(x) > revnum:
738 savebases[x] = 1
739
740 # create a changegroup for all the branches we need to keep
741 if backup == "all":
742 backupch = repo.changegroupsubset([rev], chlog.heads(), 'strip')
743 bundle(backupch)
744 if saveheads:
745 backupch = repo.changegroupsubset(savebases.keys(), saveheads, 'strip')
746 chgrpfile = bundle(backupch)
747
748 stripall(revnum)
749
750 change = chlog.read(rev)
751 chlog.strip(revnum, revnum)
752 repo.manifest.strip(repo.manifest.rev(change[0]), revnum)
753 self.removeundo(repo) 643 self.removeundo(repo)
754 if saveheads: 644 repair.strip(self.ui, repo, rev, backup)
755 self.ui.status("adding branch\n")
756 commands.unbundle(self.ui, repo, "file:%s" % chgrpfile,
757 update=False)
758 if backup != "strip":
759 os.unlink(chgrpfile)
760 645
761 def isapplied(self, patch): 646 def isapplied(self, patch):
762 """returns (index, rev, patch)""" 647 """returns (index, rev, patch)"""
763 for i in xrange(len(self.applied)): 648 for i in xrange(len(self.applied)):
764 a = self.applied[i] 649 a = self.applied[i]