A zeroconf proof of concept

Matt Mackall mpm at selenic.com
Mon Jun 30 10:52:29 CDT 2008


With the below extension enabled and a copy of Zeroconf.py in your
Python path from:

http://bazaar.launchpad.net/~statik/pyzeroconf/pyzeroconf.dev/download/elliot.murphy%40canonical.com-20070202033203-d08dp7o17mi1ehfl/zeroconf.py-20070202025230-yw3akeev1qdfsmis-4/Zeroconf.py

On one machine, run hg serve. On another on the same local network, run
hg paths:

$ hg paths
default = ssh://xxxxxxxxxx/
zc-hg = http://192.168.1.132:8000/hg

The latter, of course, is an hg repo detected via zeroconf. If you've
got hg shell completion enabled, you'll be able to do:

$ hg clone z<tab>

If you've got Safari, you can click on the bookmarks icon, click on
Bonjour, and then click on your repo. I'm sure there are other
zeroconf-enabled browsers out there too.

Theoretically, this extension should work on Linux, Mac, and Windows,
but I've only tried it on Linux. Enjoy.

diff -r e81d2bd66908 hgext/zeroconf.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hgext/zeroconf.py	Mon Jun 30 10:43:36 2008 -0500
@@ -0,0 +1,89 @@
+# zeroconf.py - zeroconf support for Mercurial
+
+import Zeroconf, socket, time, os
+from mercurial import ui
+from mercurial.hgweb import hgweb_mod
+from mercurial.hgweb import hgwebdir_mod
+
+# publish
+
+server = None
+localip = None
+
+def publish(name, desc, path):
+    global server, localip
+    if not server:
+        server = Zeroconf.Zeroconf()
+        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+        s.connect(('1.0.0.1', 0))
+        ip = s.getsockname()[0]
+        localip = socket.inet_aton(ip)
+
+    svc = Zeroconf.ServiceInfo('_http._tcp.local.',
+                               name + '._http._tcp.local.',
+                               port = 8000,
+                               properties = {'description': desc,
+                                             'path': "/" + path},
+                               address = localip, weight = 0, priority = 0)
+    server.registerService(svc)
+
+class hgwebzc(hgweb_mod.hgweb):
+    def __init__(self, repo, name=None):
+        super(hgwebzc, self).__init__(repo, name)
+        name = self.reponame or os.path.basename(repo.root)
+        desc = self.repo.ui.config("web", "description", name)
+        publish(name, desc, name)
+
+class hgwebdirzc(hgwebdir_mod.hgwebdir):
+    def run(self):
+        for r, p in self.repos:
+            u = ui.ui(parentui=self.parentui)
+            u.readconfig(os.path.join(path, '.hg', 'hgrc'))
+            n = os.path.basename(r)
+            desc = u.config("web", "description", n)
+            publish(n, "hgweb", p)
+        return super(hgwebdirzc, self).run()
+
+# listen
+
+class listener(object):
+    def __init__(self):
+        self.found = {}
+    def removeService(self, server, type, name):
+        if repr(name) in self.found:
+            del self.found[repr(name)]
+    def addService(self, server, type, name):
+        self.found[repr(name)] = server.getServiceInfo(type, name)
+
+def getzcpaths():
+    server = Zeroconf.Zeroconf()
+    l = listener()
+    browser = Zeroconf.ServiceBrowser(server, "_http._tcp.local.", l)
+    time.sleep(1)
+    server.close()
+    for v in l.found.values():
+        n = v.name[:v.name.index('.')]
+        n.replace(" ", "-")
+        u = "http://%s:%s%s" % (socket.inet_ntoa(v.address), v.port,
+                                 v.properties.get("path", "/"))
+        yield "zc-" + n, u
+
+def config(self, section, key, default=None, untrusted=False):
+    if section == "paths" and key.startswith("zc-"):
+        for n, p in getzcpaths():
+            if n == key:
+                return p
+    return oldconfig(self, section, key, default, untrusted)
+
+def configitems(self, section):
+    r = oldconfigitems(self, section, untrusted=False)
+    if section == "paths":
+        r += getzcpaths()
+    return r
+
+oldconfig = ui.ui.config
+oldconfigitems = ui.ui.configitems
+ui.ui.config = config
+ui.ui.configitems = configitems
+hgweb_mod.hgweb = hgwebzc
+hgwebdir_mod.hgwebdir = hgwebdirzc


-- 
Mathematics is the supreme nostalgia of our time.



More information about the Mercurial-devel mailing list