__init__.py
135 lines
| 4.3 KiB
| text/x-python
|
PythonLexer
Matt Mackall
|
r7071 | # 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. | ||||
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 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 | ||||
dumbip = socket.gethostbyaddr(socket.gethostname())[2][0] | ||||
if not dumbip.startswith('127.'): | ||||
return dumbip | ||||
# 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: | ||||
server = Zeroconf.Zeroconf() | ||||
ip = getip() | ||||
localip = socket.inet_aton(ip) | ||||
Matt Mackall
|
r7087 | parts = socket.gethostname().split('.') | ||
host = parts[0] + ".local" | ||||
Matt Mackall
|
r7071 | |||
# 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.', | ||||
Matt Mackall
|
r7088 | server = host, | ||
Matt Mackall
|
r7071 | 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): | ||||
print os.environ | ||||
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, int(repo.ui.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(): | ||||
server = Zeroconf.Zeroconf() | ||||
l = listener() | ||||
browser = 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(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 | ||||