def handleRelease(self, product_name, series_name, url, file_names): """If the given URL looks like a release tarball, download it and create a corresponding ProductRelease.""" filename = urlparse.urlsplit(url)[2] slash = filename.rfind("/") if slash != -1: filename = filename[slash + 1:] self.log.debug("Filename portion is %s", filename) version = extract_version(filename) if version is None: self.log.info("Unable to parse version from %s", url) return self.log.debug("Version is %s", version) if not sane_version(version): self.log.error("Version number '%s' for '%s' is not sane", version, url) return if filename in file_names: self.log.debug("Already have a tarball for release %s", version) return mimetype, encoding = mimetypes.guess_type(url) self.log.debug("Mime type is %s", mimetype) if mimetype is None: mimetype = 'application/octet-stream' self.log.info("Downloading %s", url) with tempfile.TemporaryFile(prefix="product-release-finder") as fp: try: response = urlfetch(url, use_proxy=True, output_file=fp) # XXX cjwatson 2018-06-26: This will all change with # requests 3.x. See: # https://blog.petrzemek.net/2018/04/22/ expected_length = response.headers.get("Content-Length") if expected_length is not None: actual_length = response.raw.tell() expected_length = int(expected_length) if actual_length < expected_length: raise IOError( "Incomplete read: got %d, expected %d" % (actual_length, expected_length)) except (IOError, requests.RequestException): self.log.exception("Download of %s failed", url) raise stat = os.fstat(fp.fileno()) fp.seek(0) self.addReleaseTarball(product_name, series_name, version, filename, stat.st_size, fp, mimetype) file_names.add(filename)
def _validate(self, version): """See `UniqueField`.""" super(DistroSeriesVersionField, self)._validate(version) if not sane_version(version): raise LaunchpadValidationError("%s is not a valid version" % version) # Avoid circular import hell. from lp.archivepublisher.debversion import Version, VersionError try: # XXX sinzui 2009-07-25 bug=404613: DistributionMirror and buildd # have stricter version rules than the schema. The version must # be a debversion. Version(version) except VersionError as error: raise LaunchpadValidationError("'%s': %s" % (version, error))
def _validate(self, version): """See `UniqueField`.""" super(DistroSeriesVersionField, self)._validate(version) if not sane_version(version): raise LaunchpadValidationError( "%s is not a valid version" % version) # Avoid circular import hell. from lp.archivepublisher.debversion import Version, VersionError try: # XXX sinzui 2009-07-25 bug=404613: DistributionMirror and buildd # have stricter version rules than the schema. The version must # be a debversion. Version(version) except VersionError as error: raise LaunchpadValidationError( "'%s': %s" % (version, error))
def handleRelease(self, product_name, series_name, url, file_names): """If the given URL looks like a release tarball, download it and create a corresponding ProductRelease.""" filename = urlparse.urlsplit(url)[2] slash = filename.rfind("/") if slash != -1: filename = filename[slash + 1:] self.log.debug("Filename portion is %s", filename) version = extract_version(filename) if version is None: self.log.info("Unable to parse version from %s", url) return self.log.debug("Version is %s", version) if not sane_version(version): self.log.error("Version number '%s' for '%s' is not sane", version, url) return if filename in file_names: self.log.debug("Already have a tarball for release %s", version) return mimetype, encoding = mimetypes.guess_type(url) self.log.debug("Mime type is %s", mimetype) if mimetype is None: mimetype = 'application/octet-stream' self.log.info("Downloading %s", url) try: local, headers = urllib.urlretrieve(url) stat = os.stat(local) except IOError: self.log.error("Download of %s failed", url) raise except OSError: self.log.error("Unable to stat downloaded file") raise try: fp = open(local, 'r') os.unlink(local) self.addReleaseTarball(product_name, series_name, version, filename, stat.st_size, fp, mimetype) file_names.add(filename) finally: fp.close()