Example #1
0
    def remoteInstall(self, forcedUpdate=False, showMessages=False):
        """
        Install the extension from the remote. This will call `extensionNeedsUpdate()`

        Optional set `forcedUpdate` to `True` if its needed to install the extension anyhow
        """
        if self.isExtensionInstalled(
        ) and not self.extensionNeedsUpdate() and not forcedUpdate:
            # dont download and install if the current intall is newer (only when it forced)
            return
        # get the zip path
        zipPath = self.remoteZipPath()

        try:
            # try to download the zip file
            # and fail silently with a custom error message
            contents = getDataFromURL(zipPath)
        except Exception as e:
            message = "Could not download the extension zip file for: '%s'" % self.extensionName(
            )
            logger.error(message)
            logger.error(e)
            raise ExtensionRepoError(message)
        # create a temp folder
        tempFolder = tempfile.mkdtemp()
        try:
            # try to extract the zip
            # and fail silently with a custom message
            with zipfile.ZipFile(BytesIO(contents)) as z:
                z.extractall(tempFolder)
        except Exception as e:
            message = "Could not extract the extension zip file for: '%s'" % self.extensionName(
            )
            logger.error(message)
            logger.error(e)
            raise ExtensionRepoError(message)
        # find the extension path
        extensionPath = findExtensionInRoot(
            os.path.basename(self.extensionPath), tempFolder)
        if extensionPath:
            # if found get the bundle and install it
            bundle = ExtensionBundle(path=extensionPath)
            bundle.install(showMessages=showMessages)
            self.resetRemembered()
        else:
            # raise an custom error when the extension is not found in the zip
            message = "Could not find the extension: '%s'" % self.extensionPath
            logger.error(message)
            raise ExtensionRepoError(message)
        # remove the temp folder with the extracted zip
        shutil.rmtree(tempFolder)
Example #2
0
    def _remoteInstallCallback(self, url, data, error):
        if error:
            message = "Could not download the extension zip file for: '%s' at url: '%s'" % (
                self.extensionName(), url)
            logger.error(message)
            logger.error(error)
            raise ExtensionRepoError(message)

        # create a temp folder
        tempFolder = tempfile.mkdtemp()
        try:
            # try to extract the zip
            # and fail silently with a custom message
            with zipfile.ZipFile(io.BytesIO(data.bytes())) as z:
                z.extractall(tempFolder)
        except Exception as e:
            message = "Could not extract the extension zip file for: '%s' at url: '%s'" % (
                self.extensionName(), url)
            logger.error(message)
            logger.error(e)
            raise ExtensionRepoError(message)

        # find the extension path
        extensionPath = findExtensionInRoot(
            os.path.basename(self.extensionPath), tempFolder)
        if extensionPath:
            # if found get the bundle and install it
            bundle = ExtensionBundle(path=extensionPath)
            bundle.install(showMessages=self._showMessages)
            self.resetRemembered()
        else:
            # raise an custom error when the extension is not found in the zip
            message = "Could not find the extension: '%s'" % self.extensionPath
            logger.error(message)
            raise ExtensionRepoError(message)

        # remove the temp folder with the extracted zip
        shutil.rmtree(tempFolder)

        # clear the cache for this extension icon so it may be reloaded
        if self.extensionIconURL():
            CachingURLReader.invalidate_cache_for_url(self.extensionIconURL())
            self._extensionIcon = None

        self._needsUpdate = False
        postEvent(EXTENSION_DID_REMOTE_INSTALL_EVENT_KEY, item=self)
Example #3
0
class Extension(object):
    """Facilitates loading the configuration from and updating extensions."""

    @classmethod
    def all(cls):
        return [cls(name=n) for n in ExtensionBundle.allExtensions()]

    @classmethod
    def install_remote(cls, repository, filename):
        remote = GithubRepository(repository, filename)
        path = remote.download()
        extension = cls(path=path).install()
        shutil.rmtree(path) # TODO: removing the tree should happen after download somehow
        return extension

    def __init__(self, name=None, path=None):
        self.name = name
        self.bundle = ExtensionBundle(name=self.name, path=path)

    @evented()
    def update(self, path=None):
        """Download and install the latest version of the extension."""

        if path is None:
            path = self.remote.download()

        Extension(path=path).install()

    @evented()
    def install(self):
        self.bundle.install()

    @evented()
    def uninstall(self):
        self.bundle.deinstall()

    @lazy_property
    def configuration(self):
        return Configuration(self.configuration_path)

    @lazy_property
    def remote(self):
        return GithubRepository(self.repository, self.filename)

    @property
    def is_current_version(self):
        """Return if extension is at curent version"""
        return self.remote.version <= self.version

    @property
    def is_ignored(self):
        return self.bundle.name in Storage.get('ignore')

    @property
    def is_configured(self):
        return self.repository is not None

    @property
    def is_installed(self):
        return self.bundle.bundleExists()

    @property
    def may_update(self):
        return not self.is_ignored and self.is_configured

    @property
    def should_update(self):
        return self.may_update and not self.is_current_version

    @property
    def configuration_path(self):
        return os.path.join(self.path, 'info.plist')

    @property
    def path(self):
        return self.bundle.bundlePath()

    @property
    def repository(self):
        return self.configuration.namespaced('repository') or \
            self.configuration.deprecated('repository')

    @property
    def version(self):
        return Version(self.configuration['version'])

    @property
    def filename(self):
        return os.path.basename(self.bundle.bundlePath())