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

Source Code for Module buildbot.steps.source.cvs

  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 email.Utils import formatdate 
 17  import time 
 18  import re 
 19   
 20  from twisted.python import log 
 21  from twisted.internet import defer 
 22   
 23  from buildbot.process import buildstep 
 24  from buildbot.steps.shell import StringFileWriter 
 25  from buildbot.steps.source.base import Source 
 26  from buildbot.interfaces import BuildSlaveTooOldError 
27 28 -class CVS(Source):
29 30 name = "cvs" 31 32 renderables = [ "cvsroot" ] 33
34 - def __init__(self, cvsroot=None, cvsmodule='', mode='incremental', 35 method=None, branch=None, global_options=[], extra_options=[], 36 login=None, **kwargs):
37 38 self.cvsroot = cvsroot 39 self.cvsmodule = cvsmodule 40 self.branch = branch 41 self.global_options = global_options 42 self.extra_options = extra_options 43 self.login = login 44 self.mode = mode 45 self.method = method 46 self.srcdir = 'source' 47 Source.__init__(self, **kwargs)
48
49 - def startVC(self, branch, revision, patch):
50 self.branch = branch 51 self.revision = revision 52 self.stdio_log = self.addLog("stdio") 53 self.method = self._getMethod() 54 d = self.checkCvs() 55 def checkInstall(cvsInstalled): 56 if not cvsInstalled: 57 raise BuildSlaveTooOldError("CVS is not installed on slave") 58 return 0
59 d.addCallback(checkInstall) 60 d.addCallback(self.checkLogin) 61 62 if self.mode == 'incremental': 63 d.addCallback(lambda _: self.incremental()) 64 elif self.mode == 'full': 65 d.addCallback(lambda _: self.full()) 66 67 d.addCallback(self.parseGotRevision) 68 d.addCallback(self.finish) 69 d.addErrback(self.failed) 70 return d
71 72 @defer.inlineCallbacks
73 - def incremental(self):
74 updatable = yield self._sourcedirIsUpdatable() 75 if updatable: 76 rv = yield self.doUpdate() 77 else: 78 rv = yield self.clobber() 79 defer.returnValue(rv)
80 81 @defer.inlineCallbacks
82 - def full(self):
83 if self.method == 'clobber': 84 rv = yield self.clobber() 85 defer.returnValue(rv) 86 return 87 88 elif self.method == 'copy': 89 rv = yield self.copy() 90 defer.returnValue(rv) 91 return 92 93 updatable = yield self._sourcedirIsUpdatable() 94 if not updatable: 95 log.msg("CVS repo not present, making full checkout") 96 rv = yield self.doCheckout(self.workdir) 97 elif self.method == 'clean': 98 rv = yield self.clean() 99 elif self.method == 'fresh': 100 rv = yield self.fresh() 101 else: 102 raise ValueError("Unknown method, check your configuration") 103 defer.returnValue(rv)
104
105 - def clobber(self):
106 cmd = buildstep.RemoteCommand('rmdir', {'dir': self.workdir, 107 'logEnviron': self.logEnviron}) 108 cmd.useLog(self.stdio_log, False) 109 d = self.runCommand(cmd) 110 def checkRemoval(res): 111 if res != 0: 112 raise RuntimeError("Failed to delete directory") 113 return res
114 d.addCallback(lambda _: checkRemoval(cmd.rc)) 115 d.addCallback(lambda _: self.doCheckout(self.workdir)) 116 return d 117
118 - def fresh(self, ):
119 d = self.purge(True) 120 d.addCallback(lambda _: self.doUpdate()) 121 return d
122
123 - def clean(self, ):
124 d = self.purge(False) 125 d.addCallback(lambda _: self.doUpdate()) 126 return d
127
128 - def copy(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 self.workdir = 'source' 134 d.addCallback(lambda _: self.incremental()) 135 def copy(_): 136 cmd = buildstep.RemoteCommand('cpdir', 137 {'fromdir': 'source', 138 'todir':'build', 139 'logEnviron': self.logEnviron,}) 140 cmd.useLog(self.stdio_log, False) 141 d = self.runCommand(cmd) 142 return d
143 d.addCallback(copy) 144 def resetWorkdir(_): 145 self.workdir = 'build' 146 return 0 147 d.addCallback(resetWorkdir) 148 return d 149
150 - def purge(self, ignore_ignores):
151 command = ['cvsdiscard'] 152 if ignore_ignores: 153 command += ['--ignore'] 154 cmd = buildstep.RemoteShellCommand(self.workdir, command, 155 env=self.env, 156 logEnviron=self.logEnviron, 157 timeout=self.timeout) 158 cmd.useLog(self.stdio_log, False) 159 d = self.runCommand(cmd) 160 def evaluate(cmd): 161 if cmd.didFail(): 162 raise buildstep.BuildStepFailed() 163 return cmd.rc
164 d.addCallback(evaluate) 165 return d 166
167 - def doCheckout(self, dir):
168 command = ['-d', self.cvsroot, '-z3', 'checkout', '-d', dir ] 169 command = self.global_options + command + self.extra_options 170 if self.branch: 171 command += ['-r', self.branch] 172 if self.revision: 173 command += ['-D', self.revision] 174 command += [ self.cvsmodule ] 175 d = self._dovccmd(command, '') 176 return d
177
178 - def doUpdate(self):
179 command = ['-z3', 'update', '-dP'] 180 branch = self.branch 181 # special case. 'cvs update -r HEAD -D today' gives no files; see #2351 182 if branch == 'HEAD' and self.revision: 183 branch = None 184 if branch: 185 command += ['-r', self.branch] 186 if self.revision: 187 command += ['-D', self.revision] 188 d = self._dovccmd(command) 189 return d
190
191 - def finish(self, res):
192 d = defer.succeed(res) 193 def _gotResults(results): 194 self.setStatus(self.cmd, results) 195 return results
196 d.addCallback(_gotResults) 197 d.addCallbacks(self.finished, self.checkDisconnect) 198 return d 199
200 - def checkLogin(self, _):
201 if self.login: 202 d = defer.succeed(0) 203 else: 204 d = self._dovccmd(['-d', self.cvsroot, 'login']) 205 def setLogin(res): 206 # this happens only if the login command succeeds. 207 self.login = True 208 return res
209 d.addCallback(setLogin) 210 211 return d 212
213 - def _dovccmd(self, command, workdir=None):
214 if workdir is None: 215 workdir = self.workdir 216 if not command: 217 raise ValueError("No command specified") 218 cmd = buildstep.RemoteShellCommand(workdir, ['cvs'] + 219 command, 220 env=self.env, 221 timeout=self.timeout, 222 logEnviron=self.logEnviron) 223 cmd.useLog(self.stdio_log, False) 224 d = self.runCommand(cmd) 225 def evaluateCommand(cmd): 226 if cmd.rc != 0: 227 log.msg("Source step failed while running command %s" % cmd) 228 raise buildstep.BuildStepFailed() 229 return cmd.rc
230 d.addCallback(lambda _: evaluateCommand(cmd)) 231 return d 232 233 @defer.inlineCallbacks
234 - def _sourcedirIsUpdatable(self):
235 myFileWriter = StringFileWriter() 236 args = { 237 'workdir': self.build.path_module.join(self.workdir, 'CVS'), 238 'writer': myFileWriter, 239 'maxsize': None, 240 'blocksize': 32*1024, 241 } 242 243 cmd = buildstep.RemoteCommand('uploadFile', 244 dict(slavesrc='Root', **args), 245 ignore_updates=True) 246 yield self.runCommand(cmd) 247 if cmd.rc is not None and cmd.rc != 0: 248 defer.returnValue(False) 249 return 250 251 # on Windows, the cvsroot may not contain the password, so compare to 252 # both 253 cvsroot_without_pw = re.sub("(:pserver:[^:]*):[^@]*(@.*)", 254 r"\1\2", self.cvsroot) 255 if myFileWriter.buffer.strip() not in (self.cvsroot, 256 cvsroot_without_pw): 257 defer.returnValue(False) 258 return 259 260 myFileWriter.buffer = "" 261 cmd = buildstep.RemoteCommand('uploadFile', 262 dict(slavesrc='Repository', **args), 263 ignore_updates=True) 264 yield self.runCommand(cmd) 265 if cmd.rc is not None and cmd.rc != 0: 266 defer.returnValue(False) 267 return 268 if myFileWriter.buffer.strip() != self.cvsmodule: 269 defer.returnValue(False) 270 return 271 272 defer.returnValue(True)
273
274 - def parseGotRevision(self, res):
275 revision = time.strftime("%Y-%m-%d %H:%M:%S +0000", time.gmtime()) 276 self.updateSourceProperty('got_revision', revision) 277 return res
278
279 - def checkCvs(self):
280 d = self._dovccmd(['--version']) 281 def check(res): 282 if res == 0: 283 return True 284 return False
285 d.addCallback(check) 286 return d 287
288 - def _getMethod(self):
289 if self.method is not None and self.mode != 'incremental': 290 return self.method 291 elif self.mode == 'incremental': 292 return None 293 elif self.method is None and self.mode == 'full': 294 return 'fresh'
295
296 - def computeSourceRevision(self, changes):
297 if not changes: 298 return None 299 lastChange = max([c.when for c in changes]) 300 lastSubmit = max([br.submittedAt for br in self.build.requests]) 301 when = (lastChange + lastSubmit) / 2 302 return formatdate(when)
303