Index: third_party/buildbot_7_12/buildbot/steps/transfer.py |
diff --git a/third_party/buildbot_7_12/buildbot/steps/transfer.py b/third_party/buildbot_7_12/buildbot/steps/transfer.py |
deleted file mode 100644 |
index bf8f2a8ff6dd07a16dcdd9b2652246d88659cadc..0000000000000000000000000000000000000000 |
--- a/third_party/buildbot_7_12/buildbot/steps/transfer.py |
+++ /dev/null |
@@ -1,469 +0,0 @@ |
-# -*- test-case-name: buildbot.test.test_transfer -*- |
- |
-import os.path, tarfile, tempfile |
-from twisted.internet import reactor |
-from twisted.spread import pb |
-from twisted.python import log |
-from buildbot.process.buildstep import RemoteCommand, BuildStep |
-from buildbot.process.buildstep import SUCCESS, FAILURE, SKIPPED |
-from buildbot.interfaces import BuildSlaveTooOldError |
- |
- |
-class _FileWriter(pb.Referenceable): |
- """ |
- Helper class that acts as a file-object with write access |
- """ |
- |
- def __init__(self, destfile, maxsize, mode): |
- # Create missing directories. |
- destfile = os.path.abspath(destfile) |
- dirname = os.path.dirname(destfile) |
- if not os.path.exists(dirname): |
- os.makedirs(dirname) |
- |
- self.destfile = destfile |
- self.fp = open(destfile, "wb") |
- if mode is not None: |
- os.chmod(destfile, mode) |
- self.remaining = maxsize |
- |
- def remote_write(self, data): |
- """ |
- Called from remote slave to write L{data} to L{fp} within boundaries |
- of L{maxsize} |
- |
- @type data: C{string} |
- @param data: String of data to write |
- """ |
- if self.remaining is not None: |
- if len(data) > self.remaining: |
- data = data[:self.remaining] |
- self.fp.write(data) |
- self.remaining = self.remaining - len(data) |
- else: |
- self.fp.write(data) |
- |
- def remote_close(self): |
- """ |
- Called by remote slave to state that no more data will be transfered |
- """ |
- self.fp.close() |
- self.fp = None |
- |
- def __del__(self): |
- # unclean shutdown, the file is probably truncated, so delete it |
- # altogether rather than deliver a corrupted file |
- fp = getattr(self, "fp", None) |
- if fp: |
- fp.close() |
- os.unlink(self.destfile) |
- |
- |
-def _extractall(self, path=".", members=None): |
- """Fallback extractall method for TarFile, in case it doesn't have its own.""" |
- |
- import copy |
- import operator |
- |
- directories = [] |
- |
- if members is None: |
- members = self |
- |
- for tarinfo in members: |
- if tarinfo.isdir(): |
- # Extract directories with a safe mode. |
- directories.append(tarinfo) |
- tarinfo = copy.copy(tarinfo) |
- tarinfo.mode = 0700 |
- self.extract(tarinfo, path) |
- |
- # Reverse sort directories. |
- directories.sort(lambda a, b: cmp(a.name, b.name)) |
- directories.reverse() |
- |
- # Set correct owner, mtime and filemode on directories. |
- for tarinfo in directories: |
- dirpath = os.path.join(path, tarinfo.name) |
- try: |
- self.chown(tarinfo, dirpath) |
- self.utime(tarinfo, dirpath) |
- self.chmod(tarinfo, dirpath) |
- except tarfile.ExtractError, e: |
- if self.errorlevel > 1: |
- raise |
- else: |
- self._dbg(1, "tarfile: %s" % e) |
- |
-class _DirectoryWriter(_FileWriter): |
- """ |
- A DirectoryWriter is implemented as a FileWriter, with an added post-processing |
- step to unpack the archive, once the transfer has completed. |
- """ |
- |
- def __init__(self, destroot, maxsize, compress, mode): |
- self.destroot = destroot |
- |
- self.fd, self.tarname = tempfile.mkstemp() |
- self.compress = compress |
- _FileWriter.__init__(self, self.tarname, maxsize, mode) |
- |
- def remote_unpack(self): |
- """ |
- Called by remote slave to state that no more data will be transfered |
- """ |
- if self.fp: |
- self.fp.close() |
- self.fp = None |
- fileobj = os.fdopen(self.fd, 'r') |
- if self.compress == 'bz2': |
- mode='r|bz2' |
- elif self.compress == 'gz': |
- mode='r|gz' |
- else: |
- mode = 'r' |
- if not hasattr(tarfile.TarFile, 'extractall'): |
- tarfile.TarFile.extractall = _extractall |
- archive = tarfile.open(name=self.tarname, mode=mode, fileobj=fileobj) |
- archive.extractall(path=self.destroot) |
- os.remove(self.tarname) |
- |
- |
-class StatusRemoteCommand(RemoteCommand): |
- def __init__(self, remote_command, args): |
- RemoteCommand.__init__(self, remote_command, args) |
- |
- self.rc = None |
- self.stderr = '' |
- |
- def remoteUpdate(self, update): |
- #log.msg('StatusRemoteCommand: update=%r' % update) |
- if 'rc' in update: |
- self.rc = update['rc'] |
- if 'stderr' in update: |
- self.stderr = self.stderr + update['stderr'] + '\n' |
- |
-class _TransferBuildStep(BuildStep): |
- """ |
- Base class for FileUpload and FileDownload to factor out common |
- functionality. |
- """ |
- DEFAULT_WORKDIR = "build" # is this redundant? |
- |
- def setDefaultWorkdir(self, workdir): |
- if self.workdir is None: |
- self.workdir = workdir |
- |
- def _getWorkdir(self): |
- properties = self.build.getProperties() |
- if self.workdir is None: |
- workdir = self.DEFAULT_WORKDIR |
- else: |
- workdir = self.workdir |
- return properties.render(workdir) |
- |
- def finished(self, result): |
- # Subclasses may choose to skip a transfer. In those cases, self.cmd |
- # will be None, and we should just let BuildStep.finished() handle |
- # the rest |
- if result == SKIPPED: |
- return BuildStep.finished(self, SKIPPED) |
- if self.cmd.stderr != '': |
- self.addCompleteLog('stderr', self.cmd.stderr) |
- |
- if self.cmd.rc is None or self.cmd.rc == 0: |
- return BuildStep.finished(self, SUCCESS) |
- return BuildStep.finished(self, FAILURE) |
- |
- |
-class FileUpload(_TransferBuildStep): |
- """ |
- Build step to transfer a file from the slave to the master. |
- |
- arguments: |
- |
- - ['slavesrc'] filename of source file at slave, relative to workdir |
- - ['masterdest'] filename of destination file at master |
- - ['workdir'] string with slave working directory relative to builder |
- base dir, default 'build' |
- - ['maxsize'] maximum size of the file, default None (=unlimited) |
- - ['blocksize'] maximum size of each block being transfered |
- - ['mode'] file access mode for the resulting master-side file. |
- The default (=None) is to leave it up to the umask of |
- the buildmaster process. |
- |
- """ |
- |
- name = 'upload' |
- |
- def __init__(self, slavesrc, masterdest, |
- workdir=None, maxsize=None, blocksize=16*1024, mode=None, |
- **buildstep_kwargs): |
- BuildStep.__init__(self, **buildstep_kwargs) |
- self.addFactoryArguments(slavesrc=slavesrc, |
- masterdest=masterdest, |
- workdir=workdir, |
- maxsize=maxsize, |
- blocksize=blocksize, |
- mode=mode, |
- ) |
- |
- self.slavesrc = slavesrc |
- self.masterdest = masterdest |
- self.workdir = workdir |
- self.maxsize = maxsize |
- self.blocksize = blocksize |
- assert isinstance(mode, (int, type(None))) |
- self.mode = mode |
- |
- def start(self): |
- version = self.slaveVersion("uploadFile") |
- properties = self.build.getProperties() |
- |
- if not version: |
- m = "slave is too old, does not know about uploadFile" |
- raise BuildSlaveTooOldError(m) |
- |
- source = properties.render(self.slavesrc) |
- masterdest = properties.render(self.masterdest) |
- # we rely upon the fact that the buildmaster runs chdir'ed into its |
- # basedir to make sure that relative paths in masterdest are expanded |
- # properly. TODO: maybe pass the master's basedir all the way down |
- # into the BuildStep so we can do this better. |
- masterdest = os.path.expanduser(masterdest) |
- log.msg("FileUpload started, from slave %r to master %r" |
- % (source, masterdest)) |
- |
- self.step_status.setText(['uploading', os.path.basename(source)]) |
- |
- # we use maxsize to limit the amount of data on both sides |
- fileWriter = _FileWriter(masterdest, self.maxsize, self.mode) |
- |
- # default arguments |
- args = { |
- 'slavesrc': source, |
- 'workdir': self._getWorkdir(), |
- 'writer': fileWriter, |
- 'maxsize': self.maxsize, |
- 'blocksize': self.blocksize, |
- } |
- |
- self.cmd = StatusRemoteCommand('uploadFile', args) |
- d = self.runCommand(self.cmd) |
- d.addCallback(self.finished).addErrback(self.failed) |
- |
- |
-class DirectoryUpload(BuildStep): |
- """ |
- Build step to transfer a directory from the slave to the master. |
- |
- arguments: |
- |
- - ['slavesrc'] name of source directory at slave, relative to workdir |
- - ['masterdest'] name of destination directory at master |
- - ['workdir'] string with slave working directory relative to builder |
- base dir, default 'build' |
- - ['maxsize'] maximum size of the compressed tarfile containing the |
- whole directory |
- - ['blocksize'] maximum size of each block being transfered |
- - ['compress'] compression type to use: one of [None, 'gz', 'bz2'] |
- |
- """ |
- |
- name = 'upload' |
- |
- def __init__(self, slavesrc, masterdest, |
- workdir="build", maxsize=None, blocksize=16*1024, |
- compress=None, **buildstep_kwargs): |
- BuildStep.__init__(self, **buildstep_kwargs) |
- self.addFactoryArguments(slavesrc=slavesrc, |
- masterdest=masterdest, |
- workdir=workdir, |
- maxsize=maxsize, |
- blocksize=blocksize, |
- compress=compress, |
- ) |
- |
- self.slavesrc = slavesrc |
- self.masterdest = masterdest |
- self.workdir = workdir |
- self.maxsize = maxsize |
- self.blocksize = blocksize |
- assert compress in (None, 'gz', 'bz2') |
- self.compress = compress |
- |
- def start(self): |
- version = self.slaveVersion("uploadDirectory") |
- properties = self.build.getProperties() |
- |
- if not version: |
- m = "slave is too old, does not know about uploadDirectory" |
- raise BuildSlaveTooOldError(m) |
- |
- source = properties.render(self.slavesrc) |
- masterdest = properties.render(self.masterdest) |
- # we rely upon the fact that the buildmaster runs chdir'ed into its |
- # basedir to make sure that relative paths in masterdest are expanded |
- # properly. TODO: maybe pass the master's basedir all the way down |
- # into the BuildStep so we can do this better. |
- masterdest = os.path.expanduser(masterdest) |
- log.msg("DirectoryUpload started, from slave %r to master %r" |
- % (source, masterdest)) |
- |
- self.step_status.setText(['uploading', os.path.basename(source)]) |
- |
- # we use maxsize to limit the amount of data on both sides |
- dirWriter = _DirectoryWriter(masterdest, self.maxsize, self.compress, 0600) |
- |
- # default arguments |
- args = { |
- 'slavesrc': source, |
- 'workdir': self.workdir, |
- 'writer': dirWriter, |
- 'maxsize': self.maxsize, |
- 'blocksize': self.blocksize, |
- 'compress': self.compress |
- } |
- |
- self.cmd = StatusRemoteCommand('uploadDirectory', args) |
- d = self.runCommand(self.cmd) |
- d.addCallback(self.finished).addErrback(self.failed) |
- |
- def finished(self, result): |
- # Subclasses may choose to skip a transfer. In those cases, self.cmd |
- # will be None, and we should just let BuildStep.finished() handle |
- # the rest |
- if result == SKIPPED: |
- return BuildStep.finished(self, SKIPPED) |
- if self.cmd.stderr != '': |
- self.addCompleteLog('stderr', self.cmd.stderr) |
- |
- if self.cmd.rc is None or self.cmd.rc == 0: |
- return BuildStep.finished(self, SUCCESS) |
- return BuildStep.finished(self, FAILURE) |
- |
- |
- |
- |
-class _FileReader(pb.Referenceable): |
- """ |
- Helper class that acts as a file-object with read access |
- """ |
- |
- def __init__(self, fp): |
- self.fp = fp |
- |
- def remote_read(self, maxlength): |
- """ |
- Called from remote slave to read at most L{maxlength} bytes of data |
- |
- @type maxlength: C{integer} |
- @param maxlength: Maximum number of data bytes that can be returned |
- |
- @return: Data read from L{fp} |
- @rtype: C{string} of bytes read from file |
- """ |
- if self.fp is None: |
- return '' |
- |
- data = self.fp.read(maxlength) |
- return data |
- |
- def remote_close(self): |
- """ |
- Called by remote slave to state that no more data will be transfered |
- """ |
- if self.fp is not None: |
- self.fp.close() |
- self.fp = None |
- |
- |
-class FileDownload(_TransferBuildStep): |
- """ |
- Download the first 'maxsize' bytes of a file, from the buildmaster to the |
- buildslave. Set the mode of the file |
- |
- Arguments:: |
- |
- ['mastersrc'] filename of source file at master |
- ['slavedest'] filename of destination file at slave |
- ['workdir'] string with slave working directory relative to builder |
- base dir, default 'build' |
- ['maxsize'] maximum size of the file, default None (=unlimited) |
- ['blocksize'] maximum size of each block being transfered |
- ['mode'] use this to set the access permissions of the resulting |
- buildslave-side file. This is traditionally an octal |
- integer, like 0644 to be world-readable (but not |
- world-writable), or 0600 to only be readable by |
- the buildslave account, or 0755 to be world-executable. |
- The default (=None) is to leave it up to the umask of |
- the buildslave process. |
- |
- """ |
- name = 'download' |
- |
- def __init__(self, mastersrc, slavedest, |
- workdir=None, maxsize=None, blocksize=16*1024, mode=None, |
- **buildstep_kwargs): |
- BuildStep.__init__(self, **buildstep_kwargs) |
- self.addFactoryArguments(mastersrc=mastersrc, |
- slavedest=slavedest, |
- workdir=workdir, |
- maxsize=maxsize, |
- blocksize=blocksize, |
- mode=mode, |
- ) |
- |
- self.mastersrc = mastersrc |
- self.slavedest = slavedest |
- self.workdir = workdir |
- self.maxsize = maxsize |
- self.blocksize = blocksize |
- assert isinstance(mode, (int, type(None))) |
- self.mode = mode |
- |
- def start(self): |
- properties = self.build.getProperties() |
- |
- version = self.slaveVersion("downloadFile") |
- if not version: |
- m = "slave is too old, does not know about downloadFile" |
- raise BuildSlaveTooOldError(m) |
- |
- # we are currently in the buildmaster's basedir, so any non-absolute |
- # paths will be interpreted relative to that |
- source = os.path.expanduser(properties.render(self.mastersrc)) |
- slavedest = properties.render(self.slavedest) |
- log.msg("FileDownload started, from master %r to slave %r" % |
- (source, slavedest)) |
- |
- self.step_status.setText(['downloading', "to", |
- os.path.basename(slavedest)]) |
- |
- # setup structures for reading the file |
- try: |
- fp = open(source, 'rb') |
- except IOError: |
- # if file does not exist, bail out with an error |
- self.addCompleteLog('stderr', |
- 'File %r not available at master' % source) |
- # TODO: once BuildStep.start() gets rewritten to use |
- # maybeDeferred, just re-raise the exception here. |
- reactor.callLater(0, BuildStep.finished, self, FAILURE) |
- return |
- fileReader = _FileReader(fp) |
- |
- # default arguments |
- args = { |
- 'slavedest': slavedest, |
- 'maxsize': self.maxsize, |
- 'reader': fileReader, |
- 'blocksize': self.blocksize, |
- 'workdir': self._getWorkdir(), |
- 'mode': self.mode, |
- } |
- |
- self.cmd = StatusRemoteCommand('downloadFile', args) |
- d = self.runCommand(self.cmd) |
- d.addCallback(self.finished).addErrback(self.failed) |
- |