summaryrefslogtreecommitdiff
path: root/sys/lib/python/hgext/zeroconf/__init__.py
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@localhost>2011-05-03 11:25:13 +0000
committercinap_lenrek <cinap_lenrek@localhost>2011-05-03 11:25:13 +0000
commit458120dd40db6b4df55a4e96b650e16798ef06a0 (patch)
tree8f82685be24fef97e715c6f5ca4c68d34d5074ee /sys/lib/python/hgext/zeroconf/__init__.py
parent3a742c699f6806c1145aea5149bf15de15a0afd7 (diff)
add hg and python
Diffstat (limited to 'sys/lib/python/hgext/zeroconf/__init__.py')
-rw-r--r--sys/lib/python/hgext/zeroconf/__init__.py159
1 files changed, 159 insertions, 0 deletions
diff --git a/sys/lib/python/hgext/zeroconf/__init__.py b/sys/lib/python/hgext/zeroconf/__init__.py
new file mode 100644
index 000000000..a57bbf593
--- /dev/null
+++ b/sys/lib/python/hgext/zeroconf/__init__.py
@@ -0,0 +1,159 @@
+# zeroconf.py - zeroconf support for Mercurial
+#
+# Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2, incorporated herein by reference.
+
+'''discover and advertise repositories on the local network
+
+Zeroconf enabled repositories will be announced in a network without
+the need to configure a server or a service. They can be discovered
+without knowing their actual IP address.
+
+To allow other people to discover your repository using run "hg serve"
+in your repository::
+
+ $ cd test
+ $ hg serve
+
+You can discover zeroconf enabled repositories by running "hg paths"::
+
+ $ hg paths
+ zc-test = http://example.com:8000/test
+'''
+
+import Zeroconf, socket, time, os
+from mercurial import ui
+from mercurial import extensions
+from mercurial.hgweb import hgweb_mod
+from mercurial.hgweb import hgwebdir_mod
+
+# publish
+
+server = None
+localip = None
+
+def getip():
+ # finds external-facing interface without sending any packets (Linux)
+ try:
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ s.connect(('1.0.0.1', 0))
+ ip = s.getsockname()[0]
+ return ip
+ except:
+ pass
+
+ # Generic method, sometimes gives useless results
+ try:
+ dumbip = socket.gethostbyaddr(socket.gethostname())[2][0]
+ if not dumbip.startswith('127.') and ':' not in dumbip:
+ return dumbip
+ except socket.gaierror:
+ dumbip = '127.0.0.1'
+
+ # works elsewhere, but actually sends a packet
+ try:
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ s.connect(('1.0.0.1', 1))
+ ip = s.getsockname()[0]
+ return ip
+ except:
+ pass
+
+ return dumbip
+
+def publish(name, desc, path, port):
+ global server, localip
+ if not server:
+ ip = getip()
+ if ip.startswith('127.'):
+ # if we have no internet connection, this can happen.
+ return
+ localip = socket.inet_aton(ip)
+ server = Zeroconf.Zeroconf(ip)
+
+ hostname = socket.gethostname().split('.')[0]
+ host = hostname + ".local"
+ name = "%s-%s" % (hostname, name)
+
+ # advertise to browsers
+ svc = Zeroconf.ServiceInfo('_http._tcp.local.',
+ name + '._http._tcp.local.',
+ server = host,
+ port = port,
+ properties = {'description': desc,
+ 'path': "/" + path},
+ address = localip, weight = 0, priority = 0)
+ server.registerService(svc)
+
+ # advertise to Mercurial clients
+ svc = Zeroconf.ServiceInfo('_hg._tcp.local.',
+ name + '._hg._tcp.local.',
+ server = host,
+ port = port,
+ 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, int(repo.ui.config("web", "port", 8000)))
+
+class hgwebdirzc(hgwebdir_mod.hgwebdir):
+ def run(self):
+ for r, p in self.repos:
+ u = self.ui.copy()
+ u.readconfig(os.path.join(p, '.hg', 'hgrc'))
+ n = os.path.basename(r)
+ publish(n, "hgweb", p, int(u.config("web", "port", 8000)))
+ 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():
+ ip = getip()
+ if ip.startswith('127.'):
+ return
+ server = Zeroconf.Zeroconf(ip)
+ l = listener()
+ Zeroconf.ServiceBrowser(server, "_hg._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(orig, 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 orig(self, section, key, default, untrusted)
+
+def configitems(orig, self, section, untrusted=False):
+ r = orig(self, section, untrusted)
+ if section == "paths":
+ r += getzcpaths()
+ return r
+
+extensions.wrapfunction(ui.ui, 'config', config)
+extensions.wrapfunction(ui.ui, 'configitems', configitems)
+hgweb_mod.hgweb = hgwebzc
+hgwebdir_mod.hgwebdir = hgwebdirzc