1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
|
# This file is part of Buildbot. Buildbot is free software: you can
# redistribute it and/or modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation, version 2.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Copyright Buildbot Team Members
from twisted.python import log
from twisted.internet import defer
from buildbot.pbutil import NewCredPerspective
from buildbot.changes import base
from buildbot.util import epoch2datetime
from buildbot import config
class ChangePerspective(NewCredPerspective):
def __init__(self, master, prefix):
self.master = master
self.prefix = prefix
def attached(self, mind):
return self
def detached(self, mind):
pass
def perspective_addChange(self, changedict):
log.msg("perspective_addChange called")
if 'revlink' in changedict and not changedict['revlink']:
changedict['revlink'] = ''
if 'repository' in changedict and not changedict['repository']:
changedict['repository'] = ''
if 'project' in changedict and not changedict['project']:
changedict['project'] = ''
if 'files' not in changedict or not changedict['files']:
changedict['files'] = []
# rename arguments to new names. Note that the client still uses the
# "old" names (who, when, and isdir), as they are not deprecated yet,
# although the master will accept the new names (author,
# when_timestamp, and is_dir). After a few revisions have passed, we
# can switch the client to use the new names.
if 'isdir' in changedict:
changedict['is_dir'] = changedict['isdir']
del changedict['isdir']
if 'who' in changedict:
changedict['author'] = changedict['who']
del changedict['who']
if 'when' in changedict:
when = None
if changedict['when'] is not None:
when = epoch2datetime(changedict['when'])
changedict['when_timestamp'] = when
del changedict['when']
# turn any bytestring keys into unicode, assuming utf8 but just
# replacing unknown characters. Ideally client would send us unicode
# in the first place, but older clients do not, so this fallback is
# useful.
for key in changedict:
if type(changedict[key]) == str:
changedict[key] = changedict[key].decode('utf8', 'replace')
changedict['files'] = list(changedict['files'])
for i, file in enumerate(changedict.get('files', [])):
if type(file) == str:
changedict['files'][i] = file.decode('utf8', 'replace')
files = []
for path in changedict['files']:
if self.prefix:
if not path.startswith(self.prefix):
# this file does not start with the prefix, so ignore it
continue
path = path[len(self.prefix):]
files.append(path)
changedict['files'] = files
if not files:
log.msg("No files listed in change... bit strange, but not fatal.")
if changedict.has_key('links'):
log.msg("Found links: "+repr(changedict['links']))
del changedict['links']
d = self.master.addChange(**changedict)
# since this is a remote method, we can't return a Change instance, so
# this just sets the return value to None:
d.addCallback(lambda _ : None)
return d
class PBChangeSource(config.ReconfigurableServiceMixin, base.ChangeSource):
compare_attrs = ["user", "passwd", "port", "prefix", "port"]
def __init__(self, user="change", passwd="changepw", port=None,
prefix=None):
self.user = user
self.passwd = passwd
self.port = port
self.prefix = prefix
self.registration = None
self.registered_port = None
def describe(self):
portname = self.registered_port
d = "PBChangeSource listener on " + str(portname)
if self.prefix is not None:
d += " (prefix '%s')" % self.prefix
return d
@defer.inlineCallbacks
def reconfigService(self, new_config):
# calculate the new port
port = self.port
if port is None:
port = new_config.slavePortnum
# and, if it's changed, re-register
if port != self.registered_port:
yield self._unregister()
self._register(port)
yield config.ReconfigurableServiceMixin.reconfigService(
self, new_config)
def stopService(self):
d = defer.maybeDeferred(base.ChangeSource.stopService, self)
d.addCallback(lambda _ : self._unregister())
return d
def _register(self, port):
if not port:
log.msg("PBChangeSource has no port to listen on")
return
self.registered_port = port
self.registration = self.master.pbmanager.register(
port, self.user, self.passwd,
self.getPerspective)
def _unregister(self):
self.registered_port = None
if self.registration:
reg = self.registration
self.registration = None
return reg.unregister()
else:
return defer.succeed(None)
def getPerspective(self, mind, username):
assert username == self.user
return ChangePerspective(self.master, self.prefix)
|