Package buildbot :: Package steps :: Package source :: Module bzr
[frames] | no frames]

Source Code for Module buildbot.steps.source.bzr

  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  from twisted.python import log 
 17  from twisted.internet import defer 
 18   
 19  from buildbot.process import buildstep 
 20  from buildbot.steps.source import Source 
 21  from buildbot.interfaces import BuildSlaveTooOldError 
22 23 -class Bzr(Source):
24 25 name = 'bzr' 26 renderables = [ 'repourl', 'baseURL' ] 27
28 - def __init__(self, repourl=None, baseURL=None, mode='incremental', 29 method=None, defaultBranch=None, **kwargs):
30 31 self.repourl = repourl 32 self.baseURL = baseURL 33 self.branch = defaultBranch 34 self.mode = mode 35 self.method = method 36 Source.__init__(self, **kwargs) 37 self.addFactoryArguments(repourl=repourl, 38 mode=mode, 39 method=method, 40 baseURL=baseURL, 41 defaultBranch=defaultBranch, 42 ) 43 if repourl and baseURL: 44 raise ValueError("you must provide exactly one of repourl and" 45 " baseURL") 46 47 if repourl is None and baseURL is None: 48 raise ValueError("you must privide at least one of repourl and" 49 " baseURL") 50 51 if self.repourl is None: 52 self.repourl = self.baseURL + defaultBranch 53 54 assert self.mode in ['incremental', 'full'] 55 56 if self.mode == 'full': 57 assert self.method in ['clean', 'fresh', 'clobber', 'copy', None]
58
59 - def startVC(self, branch, revision, patch):
60 self.branch = branch or 'master' 61 self.revision = revision 62 self.method = self._getMethod() 63 self.stdio_log = self.addLog("stdio") 64 65 d = self.checkBzr() 66 def checkInstall(bzrInstalled): 67 if not bzrInstalled: 68 raise BuildSlaveTooOldError("bzr is not installed on slave") 69 return 0
70 71 d.addCallback(checkInstall) 72 if self.mode == 'full': 73 d.addCallback(lambda _: self.full()) 74 elif self.mode == 'incremental': 75 d.addCallback(lambda _: self.incremental()) 76 77 d.addCallback(self.parseGotRevision) 78 d.addCallback(self.finish) 79 d.addErrback(self.failed) 80 return d
81
82 - def incremental(self):
83 d = self._sourcedirIsUpdatable() 84 def _cmd(updatable): 85 if updatable: 86 command = ['update'] 87 else: 88 command = ['checkout', self.repourl, '.'] 89 90 if self.revision: 91 command.extend(['-r', self.revision]) 92 return command
93 94 d.addCallback(_cmd) 95 d.addCallback(self._dovccmd) 96 return d 97 98 @defer.deferredGenerator
99 - def full(self):
100 if self.method == 'clobber': 101 wfd = defer.waitForDeferred(self.clobber()) 102 yield wfd 103 wfd.getResult() 104 return 105 elif self.method == 'copy': 106 self.workdir = 'source' 107 wfd = defer.waitForDeferred(self.copy()) 108 yield wfd 109 wfd.getResult() 110 return 111 112 wfd = defer.waitForDeferred(self._sourcedirIsUpdatable()) 113 yield wfd 114 updatable = wfd.getResult() 115 if not updatable: 116 log.msg("No bzr repo present, making full checkout") 117 d = self._doFull() 118 elif self.method == 'clean': 119 d = self.clean() 120 elif self.method == 'fresh': 121 d = self.fresh() 122 else: 123 raise ValueError("Unknown method, check your configuration") 124 wfd = defer.waitForDeferred(d) 125 yield wfd 126 wfd.getResult()
127
128 - def clobber(self):
129 cmd = buildstep.RemoteCommand('rmdir', {'dir': self.workdir, 130 'logEnviron': self.logEnviron,}) 131 cmd.useLog(self.stdio_log, False) 132 d = self.runCommand(cmd) 133 def checkRemoval(res): 134 if res != 0: 135 raise RuntimeError("Failed to delete directory") 136 return res
137 d.addCallback(lambda _: checkRemoval(cmd.rc)) 138 d.addCallback(lambda _: self._doFull()) 139 return d 140
141 - def copy(self):
142 cmd = buildstep.RemoteCommand('rmdir', {'dir': 'build', 143 'logEnviron': self.logEnviron,}) 144 cmd.useLog(self.stdio_log, False) 145 d = self.runCommand(cmd) 146 d.addCallback(lambda _: self.incremental()) 147 def copy(_): 148 cmd = buildstep.RemoteCommand('cpdir', 149 {'fromdir': 'source', 150 'todir':'build', 151 'logEnviron': self.logEnviron,}) 152 cmd.useLog(self.stdio_log, False) 153 d = self.runCommand(cmd) 154 return d
155 d.addCallback(copy) 156 return d 157
158 - def clean(self):
159 d = self._dovccmd(['clean-tree', '--ignored', '--force']) 160 command = ['update'] 161 if self.revision: 162 command.extend(['-r', self.revision]) 163 d.addCallback(lambda _: self._dovccmd(command)) 164 return d
165
166 - def fresh(self):
167 d = self._dovccmd(['clean-tree', '--force']) 168 command = ['update'] 169 if self.revision: 170 command.extend(['-r', self.revision]) 171 d.addCallback(lambda _: self._dovccmd(command)) 172 return d
173
174 - def _doFull(self):
175 command = ['checkout', self.repourl, '.'] 176 if self.revision: 177 command.extend(['-r', self.revision]) 178 d = self._dovccmd(command) 179 return d
180
181 - def finish(self, res):
182 d = defer.succeed(res) 183 def _gotResults(results): 184 self.setStatus(self.cmd, results) 185 log.msg("Closing log, sending result of the command %s " % \ 186 (self.cmd)) 187 return results
188 d.addCallback(_gotResults) 189 d.addCallbacks(self.finished, self.checkDisconnect) 190 return d 191
192 - def _sourcedirIsUpdatable(self):
193 cmd = buildstep.RemoteCommand('stat', {'file': self.workdir + '/.bzr', 194 'logEnviron': self.logEnviron,}) 195 cmd.useLog(self.stdio_log, False) 196 d = self.runCommand(cmd) 197 def _fail(tmp): 198 if cmd.rc != 0: 199 return False 200 return True
201 d.addCallback(_fail) 202 return d 203
204 - def computeSourceRevision(self, changes):
205 if not changes: 206 return None 207 lastChange = max([int(c.revision) for c in changes]) 208 return lastChange
209
210 - def _dovccmd(self, command, abandonOnFailure=True, collectStdout=False):
211 cmd = buildstep.RemoteShellCommand(self.workdir, ['bzr'] + command, 212 env=self.env, 213 logEnviron=self.logEnviron, 214 collectStdout=collectStdout) 215 cmd.useLog(self.stdio_log, False) 216 d = self.runCommand(cmd) 217 def evaluateCommand(cmd): 218 if abandonOnFailure and cmd.rc != 0: 219 log.msg("Source step failed while running command %s" % cmd) 220 raise buildstep.BuildStepFailed() 221 if collectStdout: 222 return cmd.stdout 223 else: 224 return cmd.rc
225 d.addCallback(lambda _: evaluateCommand(cmd)) 226 return d 227
228 - def checkBzr(self):
229 d = self._dovccmd(['--version']) 230 def check(res): 231 if res == 0: 232 return True 233 return False
234 d.addCallback(check) 235 return d 236
237 - def _getMethod(self):
238 if self.method is not None and self.mode != 'incremental': 239 return self.method 240 elif self.mode == 'incremental': 241 return None 242 elif self.method is None and self.mode == 'full': 243 return 'fresh'
244
245 - def parseGotRevision(self, _):
246 d = self._dovccmd(["version-info", "--custom", "--template='{revno}"], 247 collectStdout=True) 248 def setrev(stdout): 249 revision = stdout.strip("'") 250 try: 251 revision = int(revision) 252 except ValueError: 253 log.msg("Invalid revision number") 254 raise buildstep.BuildStepFailed() 255 256 log.msg("Got Git revision %s" % (revision, )) 257 self.setProperty('got_revision', revision, 'Source') 258 return 0
259 d.addCallback(setrev) 260 return d 261