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: