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 / avahiserve.py

commit
a4eaadad9216
parent
2de4c35d30c8
branch
default

Verbosity aligned with mercurial state, more verbose on TXT data

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