Package buildbot :: Package changes :: Module pb
[frames] | no frames]

Source Code for Module buildbot.changes.pb

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