##// END OF EJS Templates
fix: fix registration of config item defaults...
fix: fix registration of config item defaults Before this patch, because of the "(:<name>)?", all registered patterns would match and the default value would not be the one we thought we had registered (maybe it just took the default value for the first match?). This didn't matter because we didn't care about the default value; we used our own, intended default value in getfixers() anyway. We also have to look up each config item individually in order to not get developer warnings. Differential Revision: https://phab.mercurial-scm.org/D7082

File last commit:

r43347:687b865b default
r43488:5cb3e6f4 default
Show More
__init__.py
241 lines | 6.8 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.
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 '''
timeless
zeroconf: use absolute_import
r28296 from __future__ import absolute_import
David Soria Parra
zeroconf: add extension documentation
r7606
timeless
zeroconf: use absolute_import
r28296 import os
import socket
import time
Renato Cunha
hgext/zeroconf/__init__.py: Separate relative and absolute imports....
r11340
timeless
zeroconf: use absolute_import
r28296 from . import Zeroconf
from mercurial import (
dispatch,
encoding,
extensions,
hg,
Gregory Szorc
zeroconf: port to Python 3...
r42752 pycompat,
Augie Fackler
zeroconf: import ui as uimod per test-check-module-imports
r28308 ui as uimod,
timeless
zeroconf: use absolute_import
r28296 )
Augie Fackler
formatting: blacken the codebase...
r43346 from mercurial.hgweb import server as servermod
Matt Mackall
zeroconf: initial implementation...
r7071
Augie Fackler
extensions: change magic "shipped with hg" string...
r29841 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
Augie Fackler
extensions: document that `testedwith = 'internal'` is special...
r25186 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
# be specifying the version(s) of Mercurial they are tested with, or
# leave the attribute unspecified.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 testedwith = b'ships-with-hg-core'
Augie Fackler
hgext: mark all first-party extensions as such
r16743
Matt Mackall
zeroconf: initial implementation...
r7071 # publish
server = None
localip = None
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
zeroconf: initial implementation...
r7071 def getip():
# finds external-facing interface without sending any packets (Linux)
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
Gregory Szorc
zeroconf: port to Python 3...
r42752 s.connect((r'1.0.0.1', 0))
Matt Mackall
zeroconf: initial implementation...
r7071 ip = s.getsockname()[0]
return ip
Brodie Rao
cleanup: replace naked excepts with more specific ones
r16688 except socket.error:
Matt Mackall
zeroconf: initial implementation...
r7071 pass
# Generic method, sometimes gives useless results
Alexander Solovyov
zeroconf: guess ip for Zeroconf...
r8264 try:
dumbip = socket.gethostbyaddr(socket.gethostname())[2][0]
Gregory Szorc
zeroconf: port to Python 3...
r42752 if r':' in dumbip:
dumbip = r'127.0.0.1'
if not dumbip.startswith(r'127.'):
Alexander Solovyov
zeroconf: guess ip for Zeroconf...
r8264 return dumbip
Augie Fackler
zeroconf: gethostbyaddr may also fail with socket.herror
r10317 except (socket.gaierror, socket.herror):
Gregory Szorc
zeroconf: port to Python 3...
r42752 dumbip = r'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)
Gregory Szorc
zeroconf: port to Python 3...
r42752 s.connect((r'1.0.0.1', 1))
Matt Mackall
zeroconf: initial implementation...
r7071 ip = s.getsockname()[0]
return ip
Brodie Rao
cleanup: replace naked excepts with more specific ones
r16688 except socket.error:
Matt Mackall
zeroconf: initial implementation...
r7071 pass
return dumbip
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
zeroconf: initial implementation...
r7071 def publish(name, desc, path, port):
global server, localip
if not server:
Alexander Solovyov
zeroconf: guess ip for Zeroconf...
r8264 ip = getip()
Gregory Szorc
zeroconf: port to Python 3...
r42752 if ip.startswith(r'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
Gregory Szorc
zeroconf: port to Python 3...
r42752 hostname = socket.gethostname().split(r'.')[0]
host = hostname + r".local"
name = r"%s-%s" % (hostname, name)
Matt Mackall
zeroconf: initial implementation...
r7071
# advertise to browsers
Augie Fackler
formatting: blacken the codebase...
r43346 svc = Zeroconf.ServiceInfo(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'_http._tcp.local.',
Augie Fackler
formatting: blacken the codebase...
r43346 pycompat.bytestr(name + r'._http._tcp.local.'),
server=host,
port=port,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 properties={b'description': desc, b'path': b"/" + path},
Augie Fackler
formatting: blacken the codebase...
r43346 address=localip,
weight=0,
priority=0,
)
Matt Mackall
zeroconf: initial implementation...
r7071 server.registerService(svc)
# advertise to Mercurial clients
Augie Fackler
formatting: blacken the codebase...
r43346 svc = Zeroconf.ServiceInfo(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'_hg._tcp.local.',
Augie Fackler
formatting: blacken the codebase...
r43346 pycompat.bytestr(name + r'._hg._tcp.local.'),
server=host,
port=port,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 properties={b'description': desc, b'path': b"/" + path},
Augie Fackler
formatting: blacken the codebase...
r43346 address=localip,
weight=0,
priority=0,
)
Matt Mackall
zeroconf: initial implementation...
r7071 server.registerService(svc)
Augie Fackler
formatting: blacken the codebase...
r43346
Benoit Boissinot
zeroconf: use port from server instead of picking port from config (issue3746)...
r18190 def zc_create_server(create_server, ui, app):
httpd = create_server(ui, app)
port = httpd.port
Matt Mackall
zeroconf: initial implementation...
r7071
Benoit Boissinot
zeroconf: use port from server instead of picking port from config (issue3746)...
r18190 try:
repos = app.repos
except AttributeError:
# single repo
Gregory Szorc
zeroconf: access repo on hgweb_mod properly (issue5036)...
r27910 with app._obtainrepo() as repo:
name = app.reponame or os.path.basename(repo.root)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 path = repo.ui.config(b"web", b"prefix", b"").strip(b'/')
desc = repo.ui.config(b"web", b"description")
Boris Feld
configitems: register the 'web.description' config
r34235 if not desc:
desc = name
Benoit Boissinot
zeroconf: use port from server instead of picking port from config (issue3746)...
r18190 publish(name, desc, path, port)
else:
# webdir
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 prefix = app.ui.config(b"web", b"prefix", b"").strip(b'/') + b'/'
Benoit Boissinot
zeroconf: use port from server instead of picking port from config (issue3746)...
r18190 for repo, path in repos:
u = app.ui.copy()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 u.readconfig(os.path.join(path, b'.hg', b'hgrc'))
Alexander Solovyov
zeroconf: code cleanup, fixing variable names to be meaningful
r9488 name = os.path.basename(repo)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 path = (prefix + repo).strip(b'/')
desc = u.config(b'web', b'description')
Boris Feld
configitems: register the 'web.description' config
r34235 if not desc:
desc = name
Benoit Boissinot
zeroconf: use port from server instead of picking port from config (issue3746)...
r18190 publish(name, desc, path, port)
return httpd
Matt Mackall
zeroconf: initial implementation...
r7071
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
zeroconf: initial implementation...
r7071 # listen
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
zeroconf: initial implementation...
r7071 class listener(object):
def __init__(self):
self.found = {}
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
zeroconf: initial implementation...
r7071 def removeService(self, server, type, name):
if repr(name) in self.found:
del self.found[repr(name)]
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
zeroconf: initial implementation...
r7071 def addService(self, server, type, name):
self.found[repr(name)] = server.getServiceInfo(type, name)
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
zeroconf: initial implementation...
r7071 def getzcpaths():
Alexander Solovyov
zeroconf: guess ip for Zeroconf...
r8264 ip = getip()
Gregory Szorc
zeroconf: port to Python 3...
r42752 if ip.startswith(r'127.'):
Alexander Solovyov
zeroconf: guess ip for Zeroconf...
r8264 return
server = Zeroconf.Zeroconf(ip)
Matt Mackall
zeroconf: initial implementation...
r7071 l = listener()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 Zeroconf.ServiceBrowser(server, b"_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():
Augie Fackler
formatting: blacken the codebase...
r43346 name = value.name[: value.name.index(b'.')]
url = r"http://%s:%s%s" % (
socket.inet_ntoa(value.address),
value.port,
value.properties.get(r"path", r"/"),
)
Gregory Szorc
zeroconf: port to Python 3...
r42752 yield b"zc-" + name, pycompat.bytestr(url)
Matt Mackall
zeroconf: initial implementation...
r7071
Augie Fackler
formatting: blacken the codebase...
r43346
zeroconf: blindly forward extra argument to the core config method...
r33175 def config(orig, self, section, key, *args, **kwargs):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if section == b"paths" and key.startswith(b"zc-"):
Alexander Solovyov
zeroconf: code cleanup, fixing variable names to be meaningful
r9488 for name, path in getzcpaths():
if name == key:
return path
zeroconf: blindly forward extra argument to the core config method...
r33175 return orig(self, section, key, *args, **kwargs)
Matt Mackall
zeroconf: initial implementation...
r7071
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
zeroconf: forward all arguments passed to ui.configitems() wrapper...
r28038 def configitems(orig, self, section, *args, **kwargs):
repos = orig(self, section, *args, **kwargs)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if section == b"paths":
Alexander Solovyov
zeroconf: code cleanup, fixing variable names to be meaningful
r9488 repos += getzcpaths()
return repos
Matt Mackall
zeroconf: initial implementation...
r7071
Augie Fackler
formatting: blacken the codebase...
r43346
Danek Duvall
zeroconf: fix crash in "hg paths" when zeroconf server is up...
r28250 def configsuboptions(orig, self, section, name, *args, **kwargs):
opt, sub = orig(self, section, name, *args, **kwargs)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if section == b"paths" and name.startswith(b"zc-"):
Danek Duvall
zeroconf: fix crash in "hg paths" when zeroconf server is up...
r28250 # We have to find the URL in the zeroconf paths. We can't cons up any
# suboptions, so we use any that we found in the original config.
for zcname, zcurl in getzcpaths():
if zcname == name:
return zcurl, sub
return opt, sub
Augie Fackler
formatting: blacken the codebase...
r43346
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)
Augie Fackler
formatting: blacken the codebase...
r43346
Nicolas Dumazet
zeroconf: notify the Zeroconf threads when hg exits...
r14104 def cleanupafterdispatch(orig, ui, options, cmd, cmdfunc):
try:
return orig(ui, options, cmd, cmdfunc)
finally:
# we need to call close() on the server to notify() the various
# threading Conditions and allow the background threads to exit
global server
if server:
server.close()
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 extensions.wrapfunction(dispatch, b'_runcommand', cleanupafterdispatch)
Nicolas Dumazet
zeroconf: notify the Zeroconf threads when hg exits...
r14104
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 extensions.wrapfunction(uimod.ui, b'config', config)
extensions.wrapfunction(uimod.ui, b'configitems', configitems)
extensions.wrapfunction(uimod.ui, b'configsuboptions', configsuboptions)
extensions.wrapfunction(hg, b'defaultdest', defaultdest)
extensions.wrapfunction(servermod, b'create_server', zc_create_server)