mercurial/hg.py
changeset 222 87484f627422
parent 220 3113a94c1bff
child 223 1aaa49039a6b
--- a/mercurial/hg.py	Thu Jun 02 18:07:01 2005 -0800
+++ b/mercurial/hg.py	Thu Jun 02 18:46:49 2005 -0800
@@ -594,6 +594,9 @@
             else:
                 self.dirstate.update([f], "r")
 
+    def heads(self):
+        return self.changelog.heads()
+
     def branches(self, nodes):
         if not nodes: nodes = [self.changelog.tip()]
         b = []
@@ -659,22 +662,24 @@
         seen = {}
         seenbranch = {}
 
-        self.ui.status("searching for changes\n")
-        tip = remote.branches([])[0]
-        self.ui.debug("remote tip branch is %s:%s\n" %
-                      (short(tip[0]), short(tip[1])))
-
         # if we have an empty repo, fetch everything
         if self.changelog.tip() == nullid:
+            self.ui.status("requesting all changes\n")
             return remote.changegroup([nullid])
 
         # otherwise, assume we're closer to the tip than the root
-        unknown = [tip]
+        self.ui.status("searching for changes\n")
+        heads = remote.heads()
+        unknown = []
+        for h in heads:
+            if h not in m:
+                unknown.append(h)
 
-        if tip[0] in m:
+        if not unknown:
             self.ui.status("nothing to do!\n")
             return None
-
+            
+        unknown = remote.branches(unknown)
         while unknown:
             n = unknown.pop(0)
             seen[n[0]] = 1
@@ -766,6 +771,77 @@
                 yield y
 
     def addchangegroup(self, generator):
+
+        class genread:
+            def __init__(self, generator):
+                self.g = generator
+                self.buf = ""
+            def read(self, l):
+                while l > len(self.buf):
+                    try:
+                        self.buf += self.g.next()
+                    except StopIteration:
+                        break
+                d, self.buf = self.buf[:l], self.buf[l:]
+                return d
+                
+        def getchunk():
+            d = source.read(4)
+            if not d: return ""
+            l = struct.unpack(">l", d)[0]
+            if l <= 4: return ""
+            return source.read(l - 4)
+
+        def getgroup():
+            while 1:
+                c = getchunk()
+                if not c: break
+                yield c
+
+        def csmap(x):
+            self.ui.debug("add changeset %s\n" % short(x))
+            return self.changelog.count()
+
+        def revmap(x):
+            return self.changelog.rev(x)
+
+        if not generator: return
+        changesets = files = revisions = 0
+        self.lock()
+        source = genread(generator)
+        tr = self.transaction()
+
+        # pull off the changeset group
+        self.ui.status("adding changesets\n")
+        co = self.changelog.tip()
+        cn = self.changelog.addgroup(getgroup(), csmap, tr)
+        changesets = self.changelog.rev(cn) - self.changelog.rev(co)
+
+        # pull off the manifest group
+        self.ui.status("adding manifests\n")
+        mm = self.manifest.tip()
+        mo = self.manifest.addgroup(getgroup(), revmap, tr)
+
+        # process the files
+        self.ui.status("adding file revisions\n")
+        while 1:
+            f = getchunk()
+            if not f: break
+            self.ui.debug("adding %s revisions\n" % f)
+            fl = self.file(f)
+            o = fl.tip()
+            n = fl.addgroup(getgroup(), revmap, tr)
+            revisions += fl.rev(n) - fl.rev(o)
+            files += 1
+
+        self.ui.status(("modified %d files, added %d changesets" +
+                        " and %d new revisions\n")
+                       % (files, changesets, revisions))
+
+        tr.close()
+        return
+
+    def merge(self, generator):
         changesets = files = revisions = 0
 
         self.lock()
@@ -980,6 +1056,14 @@
         cu = "%s?%s" % (self.url, qs)
         return urllib.urlopen(cu)
 
+    def heads(self):
+        d = self.do_cmd("heads").read()
+        try:
+            return map(bin, d[:-1].split(" "))
+        except:
+            self.ui.warn("unexpected response:\n" + d[:400] + "\n...\n")
+            raise
+
     def branches(self, nodes):
         n = " ".join(map(hex, nodes))
         d = self.do_cmd("branches", nodes=n).read()