mercurial/hg.py
changeset 65 d40cc5aacc31
parent 64 b3e2ddff0159
child 67 a182f2561c8e
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: