##// END OF EJS Templates
verify: fix "missing revlog!" errors for revlog format v0 and add test...
verify: fix "missing revlog!" errors for revlog format v0 and add test With revlog format v0 the .d files are empty if the only revision stored is an empty file. Since Mercurial can no longer create format v0 repositories, but still use it, add a script which creates a repository with a single empty file. This can be used in other tests if wanted.

File last commit:

r12076:49463314 default
r12170:581066a3 stable
Show More
__init__.py
173 lines | 5.7 KiB | text/x-python | PythonLexer
Matt Mackall
zeroconf: initial implementation...
r7071 # zeroconf.py - zeroconf support for Mercurial
#
# Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
#
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Matt Mackall
zeroconf: initial implementation...
r7071
Cédric Duval
extensions: improve the consistency of synopses...
r8894 '''discover and advertise repositories on the local network
David Soria Parra
zeroconf: add extension documentation
r7606
Martin Geisler
zeroconf: small fixes in docstring...
r11504 Zeroconf-enabled repositories will be announced in a network without
Martin Geisler
zeroconf: word-wrap help texts at 70 characters
r8003 the need to configure a server or a service. They can be discovered
without knowing their actual IP address.
David Soria Parra
zeroconf: add extension documentation
r7606
Martin Geisler
zeroconf: small fixes in docstring...
r11504 To allow other people to discover your repository using run
:hg:`serve` in your repository::
David Soria Parra
zeroconf: add extension documentation
r7606
Martin Geisler
zeroconf: use reST syntax for literal blocks
r9218 $ cd test
$ hg serve
David Soria Parra
zeroconf: add extension documentation
r7606
Martin Geisler
zeroconf: small fixes in docstring...
r11504 You can discover Zeroconf-enabled repositories by running
:hg:`paths`::
David Soria Parra
zeroconf: add extension documentation
r7606
Martin Geisler
zeroconf: use reST syntax for literal blocks
r9218 $ hg paths
zc-test = http://example.com:8000/test
David Soria Parra
zeroconf: add extension documentation
r7606 '''
Renato Cunha
hgext/zeroconf/__init__.py: Separate relative and absolute imports....
r11340 import socket, time, os
import Zeroconf
Henrik Stuart
zeroconf: override default destination folder on clone
r10342 from mercurial import ui, hg, encoding
Matt Mackall
extensions: use new wrapper functions
r7216 from mercurial import extensions
Matt Mackall
zeroconf: initial implementation...
r7071 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
Alexander Solovyov
zeroconf: guess ip for Zeroconf...
r8264 try:
dumbip = socket.gethostbyaddr(socket.gethostname())[2][0]
if not dumbip.startswith('127.') and ':' not in dumbip:
return dumbip
Augie Fackler
zeroconf: gethostbyaddr may also fail with socket.herror
r10317 except (socket.gaierror, socket.herror):
Alexander Solovyov
zeroconf: guess ip for Zeroconf...
r8264 dumbip = '127.0.0.1'
Matt Mackall
zeroconf: initial implementation...
r7071
# 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:
Alexander Solovyov
zeroconf: guess ip for Zeroconf...
r8264 ip = getip()
if ip.startswith('127.'):
Augie Fackler
zeroconf: Don't break serve if no internet connection is present.
r7295 # if we have no internet connection, this can happen.
return
Matt Mackall
zeroconf: initial implementation...
r7071 localip = socket.inet_aton(ip)
Alexander Solovyov
zeroconf: guess ip for Zeroconf...
r8264 server = Zeroconf.Zeroconf(ip)
Matt Mackall
zeroconf: initial implementation...
r7071
Alexander Solovyov
zeroconf: advertise repositories with hostname
r7845 hostname = socket.gethostname().split('.')[0]
host = hostname + ".local"
name = "%s-%s" % (hostname, name)
Matt Mackall
zeroconf: initial implementation...
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
zeroconf: advertise a proper hostname for _hg services
r7088 server = host,
Matt Mackall
zeroconf: initial implementation...
r7071 port = port,
properties = {'description': desc,
'path': "/" + path},
address = localip, weight = 0, priority = 0)
server.registerService(svc)
class hgwebzc(hgweb_mod.hgweb):
Matt Mackall
zeroconf: handle string hgweb config args
r11005 def __init__(self, repo, name=None, baseui=None):
super(hgwebzc, self).__init__(repo, name=name, baseui=baseui)
name = self.reponame or os.path.basename(self.repo.root)
Patrick Mezard
zeroconf: fix hgweb published URLs (issue1819)
r9442 path = self.repo.ui.config("web", "prefix", "").strip('/')
Matt Mackall
zeroconf: initial implementation...
r7071 desc = self.repo.ui.config("web", "description", name)
Matt Mackall
zeroconf: handle string hgweb config args
r11005 publish(name, desc, path,
int(self.repo.ui.config("web", "port", 8000)))
Matt Mackall
zeroconf: initial implementation...
r7071
class hgwebdirzc(hgwebdir_mod.hgwebdir):
Patrick Mezard
zeroconf: fix hgweb published URLs (issue1819)
r9442 def __init__(self, conf, baseui=None):
Matt Mackall
hgweb: make baseui parameter non-positional
r10993 super(hgwebdirzc, self).__init__(conf, baseui=baseui)
Patrick Mezard
zeroconf: fix hgweb published URLs (issue1819)
r9442 prefix = self.ui.config("web", "prefix", "").strip('/') + '/'
Alexander Solovyov
zeroconf: code cleanup, fixing variable names to be meaningful
r9488 for repo, path in self.repos:
Matt Mackall
hgweb: kill parentui references
r8191 u = self.ui.copy()
Alexander Solovyov
zeroconf: code cleanup, fixing variable names to be meaningful
r9488 u.readconfig(os.path.join(path, '.hg', 'hgrc'))
name = os.path.basename(repo)
path = (prefix + repo).strip('/')
Alexander Solovyov
zeroconf: read actual description for repos in hgwebdir
r9489 desc = u.config('web', 'description', name)
publish(name, desc, path, int(u.config("web", "port", 8000)))
Matt Mackall
zeroconf: initial implementation...
r7071
# 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():
Alexander Solovyov
zeroconf: guess ip for Zeroconf...
r8264 ip = getip()
if ip.startswith('127.'):
return
server = Zeroconf.Zeroconf(ip)
Matt Mackall
zeroconf: initial implementation...
r7071 l = listener()
Peter Arrenbrecht
cleanup: drop variables for unused return values...
r7874 Zeroconf.ServiceBrowser(server, "_hg._tcp.local.", l)
Matt Mackall
zeroconf: initial implementation...
r7071 time.sleep(1)
server.close()
Alexander Solovyov
zeroconf: code cleanup, fixing variable names to be meaningful
r9488 for value in l.found.values():
name = value.name[:value.name.index('.')]
url = "http://%s:%s%s" % (socket.inet_ntoa(value.address), value.port,
value.properties.get("path", "/"))
yield "zc-" + name, url
Matt Mackall
zeroconf: initial implementation...
r7071
Matt Mackall
extensions: use new wrapper functions
r7216 def config(orig, self, section, key, default=None, untrusted=False):
Matt Mackall
zeroconf: initial implementation...
r7071 if section == "paths" and key.startswith("zc-"):
Alexander Solovyov
zeroconf: code cleanup, fixing variable names to be meaningful
r9488 for name, path in getzcpaths():
if name == key:
return path
Matt Mackall
extensions: use new wrapper functions
r7216 return orig(self, section, key, default, untrusted)
Matt Mackall
zeroconf: initial implementation...
r7071
Matt Mackall
zeroconf: don't break on hg showconfig
r7238 def configitems(orig, self, section, untrusted=False):
Alexander Solovyov
zeroconf: code cleanup, fixing variable names to be meaningful
r9488 repos = orig(self, section, untrusted)
Matt Mackall
zeroconf: initial implementation...
r7071 if section == "paths":
Alexander Solovyov
zeroconf: code cleanup, fixing variable names to be meaningful
r9488 repos += getzcpaths()
return repos
Matt Mackall
zeroconf: initial implementation...
r7071
Henrik Stuart
zeroconf: override default destination folder on clone
r10342 def defaultdest(orig, source):
for name, path in getzcpaths():
if path == source:
return name.encode(encoding.encoding)
return orig(source)
Matt Mackall
extensions: use new wrapper functions
r7216 extensions.wrapfunction(ui.ui, 'config', config)
extensions.wrapfunction(ui.ui, 'configitems', configitems)
Henrik Stuart
zeroconf: override default destination folder on clone
r10342 extensions.wrapfunction(hg, 'defaultdest', defaultdest)
Matt Mackall
zeroconf: initial implementation...
r7071 hgweb_mod.hgweb = hgwebzc
hgwebdir_mod.hgwebdir = hgwebdirzc