##// END OF EJS Templates
zeroconf: use reST syntax for literal blocks
Martin Geisler -
r9218:d3db87d6 default
parent child Browse files
Show More
@@ -1,159 +1,159 b''
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 the
6 6 # GNU General Public License version 2, incorporated herein by reference.
7 7
8 8 '''discover and advertise repositories on the local network
9 9
10 10 Zeroconf enabled repositories will be announced in a network without the need
11 11 to configure a server or a service. They can be discovered without knowing
12 12 their actual IP address.
13 13
14 14 To allow other people to discover your repository using run "hg serve" in your
15 repository.
15 repository::
16 16
17 $ cd test
18 $ hg serve
17 $ cd test
18 $ hg serve
19 19
20 You can discover zeroconf enabled repositories by running "hg paths".
20 You can discover zeroconf enabled repositories by running "hg paths"::
21 21
22 $ hg paths
23 zc-test = http://example.com:8000/test
22 $ hg paths
23 zc-test = http://example.com:8000/test
24 24 '''
25 25
26 26 import Zeroconf, socket, time, os
27 27 from mercurial import ui
28 28 from mercurial import extensions
29 29 from mercurial.hgweb import hgweb_mod
30 30 from mercurial.hgweb import hgwebdir_mod
31 31
32 32 # publish
33 33
34 34 server = None
35 35 localip = None
36 36
37 37 def getip():
38 38 # finds external-facing interface without sending any packets (Linux)
39 39 try:
40 40 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
41 41 s.connect(('1.0.0.1', 0))
42 42 ip = s.getsockname()[0]
43 43 return ip
44 44 except:
45 45 pass
46 46
47 47 # Generic method, sometimes gives useless results
48 48 try:
49 49 dumbip = socket.gethostbyaddr(socket.gethostname())[2][0]
50 50 if not dumbip.startswith('127.') and ':' not in dumbip:
51 51 return dumbip
52 52 except socket.gaierror:
53 53 dumbip = '127.0.0.1'
54 54
55 55 # works elsewhere, but actually sends a packet
56 56 try:
57 57 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
58 58 s.connect(('1.0.0.1', 1))
59 59 ip = s.getsockname()[0]
60 60 return ip
61 61 except:
62 62 pass
63 63
64 64 return dumbip
65 65
66 66 def publish(name, desc, path, port):
67 67 global server, localip
68 68 if not server:
69 69 ip = getip()
70 70 if ip.startswith('127.'):
71 71 # if we have no internet connection, this can happen.
72 72 return
73 73 localip = socket.inet_aton(ip)
74 74 server = Zeroconf.Zeroconf(ip)
75 75
76 76 hostname = socket.gethostname().split('.')[0]
77 77 host = hostname + ".local"
78 78 name = "%s-%s" % (hostname, name)
79 79
80 80 # advertise to browsers
81 81 svc = Zeroconf.ServiceInfo('_http._tcp.local.',
82 82 name + '._http._tcp.local.',
83 83 server = host,
84 84 port = port,
85 85 properties = {'description': desc,
86 86 'path': "/" + path},
87 87 address = localip, weight = 0, priority = 0)
88 88 server.registerService(svc)
89 89
90 90 # advertise to Mercurial clients
91 91 svc = Zeroconf.ServiceInfo('_hg._tcp.local.',
92 92 name + '._hg._tcp.local.',
93 93 server = host,
94 94 port = port,
95 95 properties = {'description': desc,
96 96 'path': "/" + path},
97 97 address = localip, weight = 0, priority = 0)
98 98 server.registerService(svc)
99 99
100 100 class hgwebzc(hgweb_mod.hgweb):
101 101 def __init__(self, repo, name=None):
102 102 super(hgwebzc, self).__init__(repo, name)
103 103 name = self.reponame or os.path.basename(repo.root)
104 104 desc = self.repo.ui.config("web", "description", name)
105 105 publish(name, desc, name, int(repo.ui.config("web", "port", 8000)))
106 106
107 107 class hgwebdirzc(hgwebdir_mod.hgwebdir):
108 108 def run(self):
109 109 for r, p in self.repos:
110 110 u = self.ui.copy()
111 111 u.readconfig(os.path.join(p, '.hg', 'hgrc'))
112 112 n = os.path.basename(r)
113 113 publish(n, "hgweb", p, int(u.config("web", "port", 8000)))
114 114 return super(hgwebdirzc, self).run()
115 115
116 116 # listen
117 117
118 118 class listener(object):
119 119 def __init__(self):
120 120 self.found = {}
121 121 def removeService(self, server, type, name):
122 122 if repr(name) in self.found:
123 123 del self.found[repr(name)]
124 124 def addService(self, server, type, name):
125 125 self.found[repr(name)] = server.getServiceInfo(type, name)
126 126
127 127 def getzcpaths():
128 128 ip = getip()
129 129 if ip.startswith('127.'):
130 130 return
131 131 server = Zeroconf.Zeroconf(ip)
132 132 l = listener()
133 133 Zeroconf.ServiceBrowser(server, "_hg._tcp.local.", l)
134 134 time.sleep(1)
135 135 server.close()
136 136 for v in l.found.values():
137 137 n = v.name[:v.name.index('.')]
138 138 n.replace(" ", "-")
139 139 u = "http://%s:%s%s" % (socket.inet_ntoa(v.address), v.port,
140 140 v.properties.get("path", "/"))
141 141 yield "zc-" + n, u
142 142
143 143 def config(orig, self, section, key, default=None, untrusted=False):
144 144 if section == "paths" and key.startswith("zc-"):
145 145 for n, p in getzcpaths():
146 146 if n == key:
147 147 return p
148 148 return orig(self, section, key, default, untrusted)
149 149
150 150 def configitems(orig, self, section, untrusted=False):
151 151 r = orig(self, section, untrusted)
152 152 if section == "paths":
153 153 r += getzcpaths()
154 154 return r
155 155
156 156 extensions.wrapfunction(ui.ui, 'config', config)
157 157 extensions.wrapfunction(ui.ui, 'configitems', configitems)
158 158 hgweb_mod.hgweb = hgwebzc
159 159 hgwebdir_mod.hgwebdir = hgwebdirzc
General Comments 0
You need to be logged in to leave comments. Login now