Alessio Caiazza is sharing code with you

Bitbucket is a code hosting site. Unlimited public and private repositories. Free for small teams.

Don't show this again

nolith / avahiserve

Avahi mercurial extension. Works only on Linux.

Clone this repository (size: 23.4 KB): HTTPS / SSH
hg clone https://bitbucket.org/nolith/avahiserve
hg clone ssh://hg@bitbucket.org/nolith/avahiserve

avahiserve / aserve / avahiserve.py

commit
cf105dccad3d
parent
769e1d8004b0
branch
default

new folder structure.

1
cf105dccad3d
##   avahiserve - Mercurial serve command with avahi publishing
2
cf105dccad3d
##   Copyright (C) 2008  Alessio Caiazza
3
cf105dccad3d
##   
4
cf105dccad3d
##   This program is free software: you can redistribute it and/or modify
5
cf105dccad3d
##   it under the terms of the GNU General Public License as published by
6
cf105dccad3d
##   the Free Software Foundation, either version 3 of the License, or
7
cf105dccad3d
##   any later version.
8
cf105dccad3d
##   
9
cf105dccad3d
##   This program is distributed in the hope that it will be useful,
10
cf105dccad3d
##   but WITHOUT ANY WARRANTY; without even the implied warranty of
11
cf105dccad3d
##   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
cf105dccad3d
##   GNU General Public License for more details.
13
cf105dccad3d
##   
14
cf105dccad3d
##   You should have received a copy of the GNU General Public License
15
cf105dccad3d
##   along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
cf105dccad3d
17
cf105dccad3d
from mercurial import commands
18
cf105dccad3d
19
cf105dccad3d
import dbus
20
cf105dccad3d
import gobject
21
cf105dccad3d
import avahi
22
cf105dccad3d
from dbus.mainloop.glib import DBusGMainLoop
23
cf105dccad3d
24
cf105dccad3d
VERSION='0.1.0'
25
cf105dccad3d
26
cf105dccad3d
class AvahiReg:
27
cf105dccad3d
28
cf105dccad3d
	def __init__(self, name, port):
29
cf105dccad3d
		self.verbose = False
30
cf105dccad3d
		self.serviceName = "Mercurial"
31
cf105dccad3d
		if name != '':
32
cf105dccad3d
			self.serviceName += ": " + name
33
cf105dccad3d
		self.serviceType = "_http._tcp" # See http://www.dns-sd.org/ServiceTypes.html
34
cf105dccad3d
		self.servicePort = port
35
cf105dccad3d
		self.serviceTXT = ["extension's author=Alessio Caiazza"] #TXT record for the service
36
cf105dccad3d
37
cf105dccad3d
		self.domain = "" # Domain to publish on, default to .local
38
cf105dccad3d
		self.host = "" # Host to publish records for, default to localhost
39
cf105dccad3d
40
cf105dccad3d
		self.group = None #our entry group
41
cf105dccad3d
		self.rename_count = 12 # Counter so we only rename after collisions a sensible number of times
42
cf105dccad3d
43
cf105dccad3d
	def add_service(self):
44
cf105dccad3d
		if self.group is None:
45
cf105dccad3d
			self.group = dbus.Interface(
46
cf105dccad3d
				self.bus.get_object( avahi.DBUS_NAME, self.server.EntryGroupNew()),
47
cf105dccad3d
				avahi.DBUS_INTERFACE_ENTRY_GROUP)
48
cf105dccad3d
			self.group.connect_to_signal('StateChanged', self.entry_group_state_changed)
49
cf105dccad3d
		if self.verbose:
50
cf105dccad3d
			print "Adding service '%s' of type '%s' ..." % (self.serviceName, self.serviceType)
51
cf105dccad3d
		self.group.AddService(
52
cf105dccad3d
			avahi.IF_UNSPEC,    #interface
53
cf105dccad3d
			avahi.PROTO_UNSPEC, #protocol
54
cf105dccad3d
			0,                  #flags
55
cf105dccad3d
			self.serviceName, self.serviceType,
56
cf105dccad3d
			self.domain, self.host,
57
cf105dccad3d
			dbus.UInt16(self.servicePort),
58
cf105dccad3d
			avahi.string_array_to_txt_array(self.serviceTXT))
59
cf105dccad3d
		self.group.Commit()
60
cf105dccad3d
61
cf105dccad3d
	def remove_service(self):
62
cf105dccad3d
		if not group is None:
63
cf105dccad3d
			group.Reset()
64
cf105dccad3d
65
cf105dccad3d
	def server_state_changed(self, state):
66
cf105dccad3d
		if state == avahi.SERVER_COLLISION:
67
cf105dccad3d
			if self.verbose:
68
cf105dccad3d
				print "WARNING: Server name collision"
69
cf105dccad3d
			remove_service()
70
cf105dccad3d
		elif state == avahi.SERVER_RUNNING:
71
cf105dccad3d
			self.add_service()
72
cf105dccad3d
73
cf105dccad3d
	def entry_group_state_changed(self,state, error):
74
cf105dccad3d
75
cf105dccad3d
		if self.verbose:
76
cf105dccad3d
			print "state change: %i" % state
77
cf105dccad3d
78
cf105dccad3d
		if state == avahi.ENTRY_GROUP_ESTABLISHED:
79
cf105dccad3d
			print "Service established."
80
cf105dccad3d
		elif state == avahi.ENTRY_GROUP_COLLISION:
81
cf105dccad3d
82
cf105dccad3d
			rename_count = rename_count - 1
83
cf105dccad3d
			if rename_count > 0:
84
cf105dccad3d
				name = server.GetAlternativeServiceName(name)
85
cf105dccad3d
				if self.verbose:
86
cf105dccad3d
					print "WARNING: Service name collision, changing name to '%s' ..." % name
87
cf105dccad3d
				remove_service()
88
cf105dccad3d
				add_service()
89
cf105dccad3d
90
cf105dccad3d
			else:
91
cf105dccad3d
				if self.verbose:
92
cf105dccad3d
					print "ERROR: No suitable service name found after %i retries, exiting." % n_rename
93
cf105dccad3d
				main_loop.quit()
94
cf105dccad3d
		elif state == avahi.ENTRY_GROUP_FAILURE:
95
cf105dccad3d
			if self.verbose:
96
cf105dccad3d
				print "Error in group state changed", error
97
cf105dccad3d
			main_loop.quit()
98
cf105dccad3d
			return
99
cf105dccad3d
100
cf105dccad3d
	def start(self):
101
cf105dccad3d
		if self.verbose:
102
cf105dccad3d
			print "Starting avahiserve version " + VERSION
103
cf105dccad3d
		DBusGMainLoop( set_as_default=True )
104
cf105dccad3d
		self.bus = dbus.SystemBus()
105
cf105dccad3d
106
cf105dccad3d
		self.server = dbus.Interface(
107
cf105dccad3d
			self.bus.get_object( avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER ),
108
cf105dccad3d
			avahi.DBUS_INTERFACE_SERVER )
109
cf105dccad3d
110
cf105dccad3d
		self.server.connect_to_signal( "StateChanged", self.server_state_changed )
111
cf105dccad3d
		self.server_state_changed( self.server.GetState() )
112
cf105dccad3d
	
113
cf105dccad3d
	def stop(self):
114
cf105dccad3d
		if self.verbose:
115
cf105dccad3d
			print "Stopping avahi-publish-service"
116
cf105dccad3d
		if not self.group is None:
117
cf105dccad3d
			self.group.Free()
118
cf105dccad3d
119
cf105dccad3d
# every command must take a ui and and repo as arguments.
120
cf105dccad3d
# opts is a dict where you can find other command line flags
121
cf105dccad3d
#
122
cf105dccad3d
# Other parameters are taken in order from items on the command line that
123
cf105dccad3d
# don't start with a dash.  If no default value is given in the parameter list,
124
cf105dccad3d
# they are required.
125
cf105dccad3d
def avahi_serve(ui, repo, **opts):
126
cf105dccad3d
	# The doc string below will show up in hg help
127
cf105dccad3d
	"""Serve and publish on avahi zeroconf"""
128
cf105dccad3d
129
cf105dccad3d
	#print opts
130
cf105dccad3d
	if opts['port'] != 0:
131
cf105dccad3d
		port = int(opts['port'])
132
cf105dccad3d
	else:
133
cf105dccad3d
		port = 8000
134
cf105dccad3d
	a = AvahiReg(opts['name'], port)
135
cf105dccad3d
136
cf105dccad3d
	if ui.cdata.has_option('web', 'description'):
137
cf105dccad3d
		a.serviceTXT += ["description=" + ui.cdata.get('web','description')]
138
cf105dccad3d
	if ui.cdata.has_option('ui', 'username'):
139
cf105dccad3d
		#remove < and > cose make problems on Avahi Discovery
140
cf105dccad3d
		a.serviceTXT += ["owner=" + 
141
cf105dccad3d
				ui.cdata.get('ui','username')
142
cf105dccad3d
				.replace('<','')
143
cf105dccad3d
				.replace('>','')]
144
cf105dccad3d
145
cf105dccad3d
	a.verbose = ui.verbose
146
cf105dccad3d
	a.start()
147
cf105dccad3d
	try:
148
cf105dccad3d
		commands.serve(ui,repo, **opts)
149
cf105dccad3d
	except KeyboardInterrupt:
150
cf105dccad3d
		pass
151
cf105dccad3d
	
152
cf105dccad3d
	a.stop()
153
cf105dccad3d
154
cf105dccad3d
155
cf105dccad3d