def Update(self,
               update_seed=None,
               allow_no_backup=False,
               throw_if_unattended=False):
        """Performs an update of the given components.

    If no components are provided, it will attempt to update everything you have
    installed.

    Args:
      update_seed: list of str, A list of component ids to update.
      allow_no_backup: bool, True if we want to allow the updater to run
        without creating a backup.  This lets us be in the root directory of the
        SDK and still do an update.  It is more fragile if there is a failure,
        so we only do it if necessary.
      throw_if_unattended: bool, True to throw an exception on prompts when
        not running in interactive mode.

    Returns:
      bool, True if the update succeeded (or there was nothing to do, False if
      if was cancelled by the user.

    Raises:
      InvalidComponentError: If any of the given component ids do not exist.
    """
        self._EnsureNotDisabled()
        try:
            install_state, diff = self._GetStateAndDiff()
        except snapshots.IncompatibleSchemaVersionError as e:
            return self._ReinstallOnError(e)

        if update_seed:
            invalid_seeds = diff.InvalidUpdateSeeds(update_seed)
            if invalid_seeds:
                if os.environ.get('CLOUDSDK_REINSTALL_COMPONENTS'):
                    # We are doing a reinstall.  Ignore any components that no longer
                    # exist.
                    update_seed = set(update_seed) - invalid_seeds
                else:
                    raise InvalidComponentError(
                        'The following components are unknown [{invalid_seeds}]'
                        .format(invalid_seeds=', '.join(invalid_seeds)))
        else:
            update_seed = diff.current.components.keys()

        to_remove = diff.ToRemove(update_seed)
        to_install = diff.ToInstall(update_seed)

        self.__Write(log.status)
        if not to_remove and not to_install:
            self.__Write(log.status, 'All components are up to date.')
            with install_state.LastUpdateCheck() as update_check:
                update_check.SetFromSnapshot(diff.latest, force=True)
            return True

        disable_backup = self._ShouldDoFastUpdate(
            allow_no_backup=allow_no_backup)
        self._PrintPendingAction(
            diff.DetailsForCurrent(to_remove - to_install), 'removed')
        self._PrintPendingAction(diff.DetailsForLatest(to_remove & to_install),
                                 'updated')
        self._PrintPendingAction(diff.DetailsForLatest(to_install - to_remove),
                                 'installed')
        self.__Write(log.status)

        message = self._GetDontCancelMessage(disable_backup)
        if not console_io.PromptContinue(
                message=message, throw_if_unattended=throw_if_unattended):
            return False

        components_to_install = diff.DetailsForLatest(to_install)
        components_to_remove = diff.DetailsForCurrent(to_remove)

        for c in components_to_install:
            metrics.Installs(c.id, c.version.version_string)

        if disable_backup:
            with execution_utils.UninterruptibleSection():
                self.__Write(log.status, 'Performing in place update...\n')
                self._UpdateWithProgressBar(components_to_remove,
                                            'Uninstalling',
                                            install_state.Uninstall)
                self._UpdateWithProgressBar(
                    components_to_install, 'Installing',
                    self._InstallFunction(install_state, diff))
        else:
            with console_io.ProgressBar(label='Creating update staging area',
                                        stream=log.status) as pb:
                staging_state = install_state.CloneToStaging(pb.SetProgress)
            self.__Write(log.status)
            self._UpdateWithProgressBar(components_to_remove, 'Uninstalling',
                                        staging_state.Uninstall)
            self._UpdateWithProgressBar(
                components_to_install, 'Installing',
                self._InstallFunction(staging_state, diff))
            self.__Write(log.status)
            self.__Write(log.status,
                         'Creating backup and activating new installation...')
            install_state.ReplaceWith(staging_state)

        with install_state.LastUpdateCheck() as update_check:
            update_check.SetFromSnapshot(diff.latest, force=True)
        self.__Write(log.status, '\nUpdate done!\n')

        if self.__warn:
            bad_commands = self.FindAllOldToolsOnPath()
            if bad_commands and not os.environ.get(
                    'CLOUDSDK_REINSTALL_COMPONENTS'):
                log.warning("""\
There are older versions of Google Cloud Platform tools on your system PATH.
Please remove the following to avoid accidentally invoking these old tools:

{0}

""".format('\n'.join(bad_commands)))
        return True
Exemplo n.º 2
0
    def Update(self,
               update_seed=None,
               allow_no_backup=False,
               throw_if_unattended=False):
        """Performs an update of the given components.

    If no components are provided, it will attempt to update everything you have
    installed.

    Args:
      update_seed: list of str, A list of component ids to update.
      allow_no_backup: bool, True if we want to allow the updater to run
        without creating a backup.  This lets us be in the root directory of the
        SDK and still do an update.  It is more fragile if there is a failure,
        so we only do it if necessary.
      throw_if_unattended: bool, True to throw an exception on prompts when
        not running in interactive mode.

    Returns:
      bool, True if the update succeeded (or there was nothing to do, False if
      if was cancelled by the user.

    Raises:
      InvalidComponentError: If any of the given component ids do not exist.
    """
        md5dict1 = self._HashRcfiles(_SHELL_RCFILES)
        self._EnsureNotDisabled()

        old_release_notes = release_notes.GetReleaseNotes(self.__sdk_root)

        try:
            install_state, diff = self._GetStateAndDiff(
                command_path='components.update')
        except snapshots.IncompatibleSchemaVersionError as e:
            return self._ReinstallOnError(e)

        if update_seed:
            invalid_seeds = diff.InvalidUpdateSeeds(update_seed)
            if invalid_seeds:
                if os.environ.get('CLOUDSDK_REINSTALL_COMPONENTS'):
                    # We are doing a reinstall.  Ignore any components that no longer
                    # exist.
                    update_seed = set(update_seed) - invalid_seeds
                else:
                    ignored = set(_IGNORED_MISSING_COMPONENTS)
                    deprecated = invalid_seeds & ignored
                    for item in deprecated:
                        log.warning('Component [%s] no longer exists.', item)
                        additional_msg = _IGNORED_MISSING_COMPONENTS.get(item)
                        if additional_msg:
                            log.warning(additional_msg)
                    invalid_seeds -= ignored
                    if invalid_seeds:
                        raise InvalidComponentError(
                            'The following components are unknown [{invalid_seeds}]'
                            .format(invalid_seeds=', '.join(invalid_seeds)))
                    update_seed = set(update_seed) - deprecated
        else:
            update_seed = diff.current.components.keys()

        to_remove = diff.ToRemove(update_seed)
        to_install = diff.ToInstall(update_seed)

        self.__Write(log.status)
        if not to_remove and not to_install:
            self.__Write(log.status, 'All components are up to date.')
            with install_state.LastUpdateCheck() as update_check:
                update_check.SetFromSnapshot(
                    diff.latest,
                    force=True,
                    platform_filter=self.__platform_filter)
            return True

        disable_backup = self._ShouldDoFastUpdate(
            allow_no_backup=allow_no_backup)
        self._PrintPendingAction(
            diff.DetailsForCurrent(to_remove - to_install), 'removed')
        self._PrintPendingAction(diff.DetailsForLatest(to_remove & to_install),
                                 'updated')
        self._PrintPendingAction(diff.DetailsForLatest(to_install - to_remove),
                                 'installed')
        self.__Write(log.status)

        if diff.latest.sdk_definition.release_notes_url:
            self.__Write(
                log.status,
                'For the latest full release notes, please visit:\n  {0}'.
                format(diff.latest.sdk_definition.release_notes_url))

        message = self._GetDontCancelMessage(disable_backup)
        if not console_io.PromptContinue(
                message=message, throw_if_unattended=throw_if_unattended):
            return False

        components_to_install = diff.DetailsForLatest(to_install)
        components_to_remove = diff.DetailsForCurrent(to_remove)

        for c in components_to_install:
            metrics.Installs(c.id, c.version.version_string)

        if disable_backup:
            with execution_utils.UninterruptibleSection(stream=log.status):
                self.__Write(log.status, 'Performing in place update...\n')
                self._UpdateWithProgressBar(components_to_remove,
                                            'Uninstalling',
                                            install_state.Uninstall)
                self._UpdateWithProgressBar(
                    components_to_install, 'Installing',
                    self._InstallFunction(install_state, diff))
        else:
            with console_io.ProgressBar(label='Creating update staging area',
                                        stream=log.status) as pb:
                staging_state = install_state.CloneToStaging(pb.SetProgress)
            self.__Write(log.status)
            self._UpdateWithProgressBar(components_to_remove, 'Uninstalling',
                                        staging_state.Uninstall)
            self._UpdateWithProgressBar(
                components_to_install, 'Installing',
                self._InstallFunction(staging_state, diff))
            self.__Write(log.status)
            self.__Write(log.status,
                         'Creating backup and activating new installation...')
            install_state.ReplaceWith(staging_state)

        with install_state.LastUpdateCheck() as update_check:
            update_check.SetFromSnapshot(
                diff.latest,
                force=True,
                platform_filter=self.__platform_filter)
        md5dict2 = self._HashRcfiles(_SHELL_RCFILES)
        if md5dict1 != md5dict2:
            self.__Write(
                log.status,
                '\nStart a new shell for the changes to take effect.\n')
        self.__Write(log.status, '\nUpdate done!\n')

        if self.__warn:
            bad_commands = self.FindAllOldToolsOnPath()
            if bad_commands and not os.environ.get(
                    'CLOUDSDK_REINSTALL_COMPONENTS'):
                log.warning("""\
There are older versions of Google Cloud Platform tools on your system PATH.
Please remove the following to avoid accidentally invoking these old tools:

{0}

""".format('\n'.join(bad_commands)))

        new_release_notes = release_notes.GetReleaseNotes(self.__sdk_root)
        changed_entries = release_notes.ChangesBetween(old_release_notes,
                                                       new_release_notes)
        if changed_entries:
            log.status.Print(
                'The following release notes are new in this upgrade. '
                'Please read carefully for information about new '
                'features, breaking changes, and bugs fixed:\n')
            log.status.Print('\n\n'.join(changed_entries))

        return True
Exemplo n.º 3
0
    def Update(self,
               update_seed=None,
               allow_no_backup=False,
               throw_if_unattended=False):
        """Performs an update of the given components.

    If no components are provided, it will attempt to update everything you have
    installed.

    Args:
      update_seed: list of str, A list of component ids to update.
      allow_no_backup: bool, True if we want to allow the updater to run
        without creating a backup.  This lets us be in the root directory of the
        SDK and still do an update.  It is more fragile if there is a failure,
        so we only do it if necessary.
      throw_if_unattended: bool, True to throw an exception on prompts when
        not running in interactive mode.

    Returns:
      bool, True if the update succeeded (or there was nothing to do, False if
      if was cancelled by the user.

    Raises:
      InvalidComponentError: If any of the given component ids do not exist.
    """
        md5dict1 = self._HashRcfiles(_SHELL_RCFILES)
        self._EnsureNotDisabled()

        try:
            install_state, diff = self._GetStateAndDiff(
                command_path='components.update')
        except snapshots.IncompatibleSchemaVersionError as e:
            return self._ReinstallOnError(e)

        original_update_seed = update_seed
        if update_seed:
            invalid_seeds = diff.InvalidUpdateSeeds(update_seed)
            if invalid_seeds:
                if os.environ.get('CLOUDSDK_REINSTALL_COMPONENTS'):
                    # We are doing a reinstall.  Ignore any components that no longer
                    # exist.
                    update_seed = set(update_seed) - invalid_seeds
                else:
                    ignored = set(_IGNORED_MISSING_COMPONENTS)
                    deprecated = invalid_seeds & ignored
                    for item in deprecated:
                        log.warning('Component [%s] no longer exists.', item)
                        additional_msg = _IGNORED_MISSING_COMPONENTS.get(item)
                        if additional_msg:
                            log.warning(additional_msg)
                    invalid_seeds -= ignored
                    if invalid_seeds:
                        raise InvalidComponentError(
                            'The following components are unknown [{invalid_seeds}]'
                            .format(invalid_seeds=', '.join(invalid_seeds)))
                    update_seed = set(update_seed) - deprecated
        else:
            update_seed = diff.current.components.keys()

        to_remove = diff.ToRemove(update_seed)
        to_install = diff.ToInstall(update_seed)

        self.__Write(log.status)
        if not to_remove and not to_install:
            self.__Write(log.status, 'All components are up to date.')
            with install_state.LastUpdateCheck() as update_check:
                update_check.SetFromSnapshot(
                    diff.latest,
                    force=True,
                    platform_filter=self.__platform_filter)
            return True

        current_os = platforms.OperatingSystem.Current()
        if (current_os is platforms.OperatingSystem.WINDOWS and
                file_utils.IsDirAncestorOf(self.__sdk_root, sys.executable)):
            # On Windows, you can't use a Python installed within a directory to move
            # that directory, which means that with a bundled Python, updates will
            # fail. To get around this, we copy the Python interpreter to a temporary
            # directory and run it there.
            # There's no issue that the `.py` files themselves are inside the install
            # directory, because the Python interpreter loads them into memory and
            # closes them immediately.
            RestartCommand(python=_CopyPython(), block=False)
            sys.exit(0)

        # If explicitly listing components, you are probably installing and not
        # doing a full udpate, change the message to be more clear.
        if original_update_seed:
            latest_msg = 'Installing components from version: '
        else:
            latest_msg = 'You will be upgraded to version: '
        self._PrintVersions(diff, latest_msg=latest_msg)

        disable_backup = self._ShouldDoFastUpdate(
            allow_no_backup=allow_no_backup)
        self._PrintPendingAction(
            diff.DetailsForCurrent(to_remove - to_install), 'removed')
        self._PrintPendingAction(diff.DetailsForLatest(to_remove & to_install),
                                 'updated')
        self._PrintPendingAction(diff.DetailsForLatest(to_install - to_remove),
                                 'installed')
        self.__Write(log.status)

        release_notes.PrintReleaseNotesDiff(
            diff.latest.sdk_definition.release_notes_url,
            config.INSTALLATION_CONFIG.version, diff.latest.version)

        message = self._GetDontCancelMessage(disable_backup)
        if not console_io.PromptContinue(
                message=message, throw_if_unattended=throw_if_unattended):
            return False

        components_to_install = diff.DetailsForLatest(to_install)
        components_to_remove = diff.DetailsForCurrent(to_remove)

        for c in components_to_install:
            metrics.Installs(c.id, c.version.version_string)

        if disable_backup:
            with execution_utils.UninterruptibleSection(stream=log.status):
                self.__Write(log.status, 'Performing in place update...\n')
                self._UpdateWithProgressBar(components_to_remove,
                                            'Uninstalling',
                                            install_state.Uninstall,
                                            first=True,
                                            last=not components_to_install)
                self._UpdateWithProgressBar(components_to_install,
                                            'Installing',
                                            self._InstallFunction(
                                                install_state, diff),
                                            first=not components_to_remove,
                                            last=True)
        else:
            with console_io.ProgressBar(label='Creating update staging area',
                                        stream=log.status,
                                        last=False) as pb:
                staging_state = install_state.CloneToStaging(pb.SetProgress)
            self._UpdateWithProgressBar(components_to_remove,
                                        'Uninstalling',
                                        staging_state.Uninstall,
                                        first=False,
                                        last=False)
            self._UpdateWithProgressBar(components_to_install,
                                        'Installing',
                                        self._InstallFunction(
                                            staging_state, diff),
                                        first=False,
                                        last=False)
            with console_io.ProgressBar(
                    label='Creating backup and activating new installation',
                    stream=log.status,
                    first=False) as pb:
                install_state.ReplaceWith(staging_state, pb.SetProgress)

        with install_state.LastUpdateCheck() as update_check:
            update_check.SetFromSnapshot(
                diff.latest,
                force=True,
                platform_filter=self.__platform_filter)
        md5dict2 = self._HashRcfiles(_SHELL_RCFILES)
        if md5dict1 != md5dict2:
            self.__Write(
                log.status,
                '\nStart a new shell for the changes to take effect.\n')
        self.__Write(log.status, '\nUpdate done!\n')

        if self.__warn:
            bad_commands = self.FindAllOldToolsOnPath()
            if bad_commands and not os.environ.get(
                    'CLOUDSDK_REINSTALL_COMPONENTS'):
                log.warning("""\
There are older versions of Google Cloud Platform tools on your system PATH.
Please remove the following to avoid accidentally invoking these old tools:

{0}

""".format('\n'.join(bad_commands)))
        return True