Mercurial > public > mercurial-scm > hg
comparison mercurial/hg.py @ 65:d40cc5aacc31 0.4f
Fix up a bunch of bugs in the new merge code
Move getchangegroup/addchangegroup to generators
author | mpm@selenic.com |
---|---|
date | Fri, 13 May 2005 11:47:16 -0800 |
parents | b3e2ddff0159 |
children | a182f2561c8e |
comparison
equal
deleted
inserted
replaced
64:b3e2ddff0159 | 65:d40cc5aacc31 |
---|---|
611 | 611 |
612 return nl | 612 return nl |
613 | 613 |
614 def getchangegroup(self, remote): | 614 def getchangegroup(self, remote): |
615 tip = remote.branches([])[0] | 615 tip = remote.branches([])[0] |
616 cl = self.changelog | 616 m = self.changelog.nodemap |
617 unknown = [tip] | 617 unknown = [tip] |
618 search = [] | 618 search = [] |
619 fetch = [] | 619 fetch = [] |
620 | 620 |
621 if tip[0] == self.changelog.tip(): | 621 if tip[0] in m: |
622 return None | 622 return None |
623 | 623 |
624 while unknown: | 624 while unknown: |
625 n = unknown.pop(0) | 625 n = unknown.pop(0) |
626 if n == nullid: break | 626 if n == nullid: break |
627 if n[1] and cl.nodemap.has_key(n[1]): # do we know the base? | 627 if n[1] and n[1] in m: # do we know the base? |
628 search.append(n) # schedule branch range for scanning | 628 search.append(n) # schedule branch range for scanning |
629 else: | 629 else: |
630 for b in remote.branches([n[2], n[3]]): | 630 for b in remote.branches([n[2], n[3]]): |
631 if cl.nodemap.has_key(b[0]): | 631 if b[0] in m: |
632 fetch.append(n[1]) # earliest unknown | 632 if n[1] not in fetch: |
633 fetch.append(n[1]) # earliest unknown | |
633 else: | 634 else: |
634 unknown.append(b) | 635 unknown.append(b) |
635 | 636 |
636 while search: | 637 while search: |
637 n = search.pop(0) | 638 n = search.pop(0) |
638 l = remote.between([(n[0], n[1])])[0] | 639 l = remote.between([(n[0], n[1])])[0] |
639 p = n[0] | 640 p = n[0] |
640 f = 1 | 641 f = 1 |
641 for i in l + [n[1]]: | 642 for i in l + [n[1]]: |
642 if self.changelog.nodemap.has_key(i): | 643 if i in m: |
643 if f <= 4: | 644 if f <= 4: |
644 fetch.append(p) | 645 fetch.append(p) |
645 else: | 646 else: |
646 search.append((p, i)) | 647 search.append((p, i)) |
648 break | |
647 p, f = i, f * 2 | 649 p, f = i, f * 2 |
650 | |
651 for f in fetch: | |
652 if f in m: | |
653 raise "already have", hex(f[:4]) | |
648 | 654 |
649 return remote.changegroup(fetch) | 655 return remote.changegroup(fetch) |
650 | 656 |
651 def changegroup(self, basenodes): | 657 def changegroup(self, basenodes): |
652 nodes = self.newer(basenodes) | 658 nodes = self.newer(basenodes) |
675 g = self.file(f).group(linkmap) | 681 g = self.file(f).group(linkmap) |
676 if not g: raise "couldn't find change to %s" % f | 682 if not g: raise "couldn't find change to %s" % f |
677 l = struct.pack(">l", len(f)) | 683 l = struct.pack(">l", len(f)) |
678 yield "".join([l, f, g]) | 684 yield "".join([l, f, g]) |
679 | 685 |
680 def addchangegroup(self, data): | 686 def addchangegroup(self, generator): |
681 def getlen(data, pos): | 687 class genread: |
682 return struct.unpack(">l", data[pos:pos + 4])[0] | 688 def __init__(self, generator): |
683 | 689 self.g = generator |
684 if not data: return | 690 self.buf = "" |
685 | 691 def read(self, l): |
692 while l > len(self.buf): | |
693 try: | |
694 self.buf += self.g.next() | |
695 except StopIteration: | |
696 break | |
697 d, self.buf = self.buf[:l], self.buf[l:] | |
698 return d | |
699 | |
700 if not generator: return | |
701 source = genread(generator) | |
702 | |
703 def getchunk(add = 0): | |
704 d = source.read(4) | |
705 if not d: return "" | |
706 l = struct.unpack(">l", d)[0] | |
707 return source.read(l - 4 + add) | |
708 | |
686 tr = self.transaction() | 709 tr = self.transaction() |
687 simple = True | 710 simple = True |
688 | 711 |
689 print "merging changesets" | 712 print "merging changesets" |
690 # pull off the changeset group | 713 # pull off the changeset group |
691 l = getlen(data, 0) | 714 csg = getchunk() |
692 csg = data[0:l] | |
693 pos = l | |
694 co = self.changelog.tip() | 715 co = self.changelog.tip() |
695 cn = self.changelog.addgroup(csg, lambda x: self.changelog.count(), tr) | 716 cn = self.changelog.addgroup(csg, lambda x: self.changelog.count(), tr) |
696 | 717 |
697 print "merging manifests" | 718 print "merging manifests" |
698 # pull off the manifest group | 719 # pull off the manifest group |
699 l = getlen(data, pos) | 720 mfg = getchunk() |
700 mfg = data[pos: pos + l] | |
701 pos += l | |
702 mo = self.manifest.tip() | 721 mo = self.manifest.tip() |
703 mn = self.manifest.addgroup(mfg, lambda x: self.changelog.rev(x), tr) | 722 mm = self.manifest.addgroup(mfg, lambda x: self.changelog.rev(x), tr) |
704 | 723 |
705 # do we need a resolve? | 724 # do we need a resolve? |
706 if self.changelog.ancestor(co, cn) != co: | 725 if self.changelog.ancestor(co, cn) != co: |
707 print "NEED RESOLVE" | |
708 simple = False | 726 simple = False |
709 resolverev = self.changelog.count() | 727 resolverev = self.changelog.count() |
710 | 728 |
711 # process the files | 729 # process the files |
712 print "merging files" | 730 print "merging files" |
713 new = {} | 731 new = {} |
714 while pos < len(data): | 732 while 1: |
715 l = getlen(data, pos) | 733 f = getchunk(4) |
716 pos += 4 | 734 if not f: break |
717 f = data[pos:pos + l] | 735 fg = getchunk() |
718 pos += l | |
719 | |
720 l = getlen(data, pos) | |
721 fg = data[pos: pos + l] | |
722 pos += l | |
723 | 736 |
724 fl = self.file(f) | 737 fl = self.file(f) |
725 o = fl.tip() | 738 o = fl.tip() |
726 n = fl.addgroup(fg, lambda x: self.changelog.rev(x), tr) | 739 n = fl.addgroup(fg, lambda x: self.changelog.rev(x), tr) |
727 if not simple: | 740 if not simple: |
728 new[fl] = fl.resolvedag(o, n, tr, resolverev) | 741 nn = fl.resolvedag(o, n, tr, resolverev) |
742 if nn: new[f] = nn | |
729 | 743 |
730 # For simple merges, we don't need to resolve manifests or changesets | 744 # For simple merges, we don't need to resolve manifests or changesets |
731 if simple: | 745 if simple: |
732 tr.close() | 746 tr.close() |
733 return | 747 return |
792 def do_cmd(self, cmd, **args): | 806 def do_cmd(self, cmd, **args): |
793 q = {"cmd": cmd} | 807 q = {"cmd": cmd} |
794 q.update(args) | 808 q.update(args) |
795 qs = urllib.urlencode(q) | 809 qs = urllib.urlencode(q) |
796 cu = "%s?%s" % (self.url, qs) | 810 cu = "%s?%s" % (self.url, qs) |
797 return urllib.urlopen(cu).read() | 811 return urllib.urlopen(cu) |
798 | 812 |
799 def branches(self, nodes): | 813 def branches(self, nodes): |
800 n = " ".join(map(hex, nodes)) | 814 n = " ".join(map(hex, nodes)) |
801 d = self.do_cmd("branches", nodes=n) | 815 d = self.do_cmd("branches", nodes=n).read() |
802 br = [ map(bin, b.split(" ")) for b in d.splitlines() ] | 816 br = [ map(bin, b.split(" ")) for b in d.splitlines() ] |
803 return br | 817 return br |
804 | 818 |
805 def between(self, pairs): | 819 def between(self, pairs): |
806 n = "\n".join(["-".join(map(hex, p)) for p in pairs]) | 820 n = "\n".join(["-".join(map(hex, p)) for p in pairs]) |
807 d = self.do_cmd("between", pairs=n) | 821 d = self.do_cmd("between", pairs=n).read() |
808 p = [ map(bin, l.split(" ")) for l in d.splitlines() ] | 822 p = [ map(bin, l.split(" ")) for l in d.splitlines() ] |
809 return p | 823 return p |
810 | 824 |
811 def changegroup(self, nodes): | 825 def changegroup(self, nodes): |
812 n = " ".join(map(hex, nodes)) | 826 n = " ".join(map(hex, nodes)) |
813 d = self.do_cmd("changegroup", roots=n) | 827 zd = zlib.decompressobj() |
814 return zlib.decompress(d) | 828 f = self.do_cmd("changegroup", roots=n) |
829 while 1: | |
830 d = f.read(4096) | |
831 if not d: | |
832 yield zd.flush() | |
833 break | |
834 yield zd.decompress(d) | |
815 | 835 |
816 def repository(ui, path=None, create=0): | 836 def repository(ui, path=None, create=0): |
817 if path and path[:5] == "hg://": | 837 if path and path[:5] == "hg://": |
818 return remoterepository(ui, path) | 838 return remoterepository(ui, path) |
819 else: | 839 else: |