##// END OF EJS Templates
zeroconf: Don't break serve if no internet connection is present.
Augie Fackler -
r7295:66d0fc10 default
parent child Browse files
Show More
@@ -1,132 +1,136
1 1 # zeroconf.py - zeroconf support for Mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of
6 6 # the GNU General Public License (version 2), incorporated herein by
7 7 # reference.
8 8
9 9 import Zeroconf, socket, time, os
10 10 from mercurial import ui
11 11 from mercurial import extensions
12 12 from mercurial.hgweb import hgweb_mod
13 13 from mercurial.hgweb import hgwebdir_mod
14 14
15 15 # publish
16 16
17 17 server = None
18 18 localip = None
19 19
20 20 def getip():
21 21 # finds external-facing interface without sending any packets (Linux)
22 22 try:
23 23 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
24 24 s.connect(('1.0.0.1', 0))
25 25 ip = s.getsockname()[0]
26 26 return ip
27 27 except:
28 28 pass
29 29
30 30 # Generic method, sometimes gives useless results
31 31 dumbip = socket.gethostbyaddr(socket.gethostname())[2][0]
32 32 if not dumbip.startswith('127.'):
33 33 return dumbip
34 34
35 35 # works elsewhere, but actually sends a packet
36 36 try:
37 37 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
38 38 s.connect(('1.0.0.1', 1))
39 39 ip = s.getsockname()[0]
40 40 return ip
41 41 except:
42 42 pass
43 43
44 44 return dumbip
45 45
46 46 def publish(name, desc, path, port):
47 47 global server, localip
48 48 if not server:
49 server = Zeroconf.Zeroconf()
49 try:
50 server = Zeroconf.Zeroconf()
51 except socket.gaierror:
52 # if we have no internet connection, this can happen.
53 return
50 54 ip = getip()
51 55 localip = socket.inet_aton(ip)
52 56
53 57 parts = socket.gethostname().split('.')
54 58 host = parts[0] + ".local"
55 59
56 60 # advertise to browsers
57 61 svc = Zeroconf.ServiceInfo('_http._tcp.local.',
58 62 name + '._http._tcp.local.',
59 63 server = host,
60 64 port = port,
61 65 properties = {'description': desc,
62 66 'path': "/" + path},
63 67 address = localip, weight = 0, priority = 0)
64 68 server.registerService(svc)
65 69
66 70 # advertise to Mercurial clients
67 71 svc = Zeroconf.ServiceInfo('_hg._tcp.local.',
68 72 name + '._hg._tcp.local.',
69 73 server = host,
70 74 port = port,
71 75 properties = {'description': desc,
72 76 'path': "/" + path},
73 77 address = localip, weight = 0, priority = 0)
74 78 server.registerService(svc)
75 79
76 80 class hgwebzc(hgweb_mod.hgweb):
77 81 def __init__(self, repo, name=None):
78 82 super(hgwebzc, self).__init__(repo, name)
79 83 name = self.reponame or os.path.basename(repo.root)
80 84 desc = self.repo.ui.config("web", "description", name)
81 85 publish(name, desc, name, int(repo.ui.config("web", "port", 8000)))
82 86
83 87 class hgwebdirzc(hgwebdir_mod.hgwebdir):
84 88 def run(self):
85 89 for r, p in self.repos:
86 90 u = ui.ui(parentui=self.parentui)
87 91 u.readconfig(os.path.join(p, '.hg', 'hgrc'))
88 92 n = os.path.basename(r)
89 93 publish(n, "hgweb", p, int(u.config("web", "port", 8000)))
90 94 return super(hgwebdirzc, self).run()
91 95
92 96 # listen
93 97
94 98 class listener(object):
95 99 def __init__(self):
96 100 self.found = {}
97 101 def removeService(self, server, type, name):
98 102 if repr(name) in self.found:
99 103 del self.found[repr(name)]
100 104 def addService(self, server, type, name):
101 105 self.found[repr(name)] = server.getServiceInfo(type, name)
102 106
103 107 def getzcpaths():
104 108 server = Zeroconf.Zeroconf()
105 109 l = listener()
106 110 browser = Zeroconf.ServiceBrowser(server, "_hg._tcp.local.", l)
107 111 time.sleep(1)
108 112 server.close()
109 113 for v in l.found.values():
110 114 n = v.name[:v.name.index('.')]
111 115 n.replace(" ", "-")
112 116 u = "http://%s:%s%s" % (socket.inet_ntoa(v.address), v.port,
113 117 v.properties.get("path", "/"))
114 118 yield "zc-" + n, u
115 119
116 120 def config(orig, self, section, key, default=None, untrusted=False):
117 121 if section == "paths" and key.startswith("zc-"):
118 122 for n, p in getzcpaths():
119 123 if n == key:
120 124 return p
121 125 return orig(self, section, key, default, untrusted)
122 126
123 127 def configitems(orig, self, section, untrusted=False):
124 128 r = orig(self, section, untrusted)
125 129 if section == "paths":
126 130 r += getzcpaths()
127 131 return r
128 132
129 133 extensions.wrapfunction(ui.ui, 'config', config)
130 134 extensions.wrapfunction(ui.ui, 'configitems', configitems)
131 135 hgweb_mod.hgweb = hgwebzc
132 136 hgwebdir_mod.hgwebdir = hgwebdirzc
General Comments 0
You need to be logged in to leave comments. Login now