Esempio n. 1
0
def check_for_mmpm_enhancements(assume_yes=False, gui=False) -> bool:
    '''
    Scrapes the main file of MMPM off the github repo, and compares the current
    version, versus the one available in the master branch. If there is a newer
    version, the user is prompted for an upgrade.

    Parameters:
        None

    Returns:
        bool: True on success, False on failure
    '''

    try:
        log.logger.info(
            f'Checking for MMPM enhancements. Current version: {mmpm.__version__}'
        )

        MMPM_FILE = urlopen(utils.MMPM_FILE_URL)
        contents: str = str(MMPM_FILE.read())

        version_line: List[str] = re.findall(r"__version__ = \d+\.\d+",
                                             contents)
        version_list: List[str] = re.findall(r"\d+\.\d+", version_line[0])
        version_number: float = float(version_list[0])

        if version_number and mmpm.__version__ < version_number:
            log.logger.info(f'Found newer version of MMPM: {version_number}')
            valid_response = False

            if gui:
                print(f'Currently installed version: {mmpm.__version__}')
                print(f'Available version: {version_number}\n')
                message = f"A newer version of MMPM is available ({version_number}). Please upgrade via terminal using 'mmpm -e'"
                utils.separator(message)
                print(message)
                utils.separator(message)
                return True

            print(utils.done())

            while not valid_response:
                print(f'\nCurrently installed version: {mmpm.__version__}')
                print(f'Available version: {version_number}\n')

                response = "yes" if assume_yes else input(
                    colors.B_GREEN +
                    "A newer version of MMPM is available\n\n" + colors.RESET +
                    "Would you like to upgrade now?" + colors.B_WHITE +
                    " [yes/y | no/n]: " + colors.RESET)

                if response in ("yes", "y"):
                    valid_response = True
                    original_dir = os.getcwd()

                    message = "Upgrading MMPM"

                    utils.separator(message)
                    print(colors.B_CYAN + message + colors.RESET)
                    utils.separator(message)

                    log.logger.info(
                        f'User chose to update MMPM with {original_dir} as the starting directory'
                    )

                    os.chdir(os.path.join('/', 'tmp'))
                    os.system('rm -rf /tmp/mmpm')

                    try:
                        return_code, _, stderr = utils.clone(
                            'mmpm', utils.MMPM_REPO_URL)
                    except OSError:
                        utils.error_msg('Failed to clone MMPM repo')
                        sys.exit(1)

                    if return_code:
                        utils.error_msg(stderr)
                        sys.exit(1)

                    os.chdir('/tmp/mmpm')

                    # if the user needs to be prompted for their password, this can't be a subprocess
                    os.system('make reinstall')

                    os.chdir(original_dir)
                    log.logger.info(
                        f'Changing back to original working directory: {original_dir}'
                    )

                elif response in ("no", "n"):
                    valid_response = True
                else:
                    utils.warning_msg("Respond with yes/no or y/n.")
        else:
            print(utils.done())
            print(
                "\nNo enhancements available for MMPM. You have the latest version."
            )
            log.logger.info('No newer version of MMPM available')
            return False
        return True
    except HTTPError:
        return False
Esempio n. 2
0
def install_modules(modules: dict, modules_to_install: List[str]) -> bool:
    '''
    Compares list of 'modules_to_install' to modules found within the
    'modules', clones the repository within the ~/MagicMirror/modules
    directory, and runs 'npm install' for each newly installed module.

    Parameters:
        modules (dict): Dictionary of MagicMirror modules
        modules_to_install (List[str]): List of modules to install

    Returns:
        bool: True upon success, False upon failure
    '''

    modules_dir: str = os.path.join(utils.MAGICMIRROR_ROOT, 'modules')

    if not os.path.exists(modules_dir):
        msg = "Failed to find MagicMirror root. Have you installed MagicMirror properly? "
        msg += "You may also set the env variable 'MMPM_MAGICMIRROR_ROOT' to the MagicMirror root directory."
        utils.error_msg(msg)
        return False

    log.logger.info(f'User selected modules to install: {modules_to_install}')
    log.logger.info(
        f'Changing into MagicMirror modules directory {modules_dir}')

    os.chdir(modules_dir)

    successful_installs: List[str] = []
    existing_modules: List[str] = []
    failed_installs: List[str] = []

    for module_to_install in modules_to_install:
        install_next: bool = False

        for _, category in modules.items():
            for module in category:
                if module[utils.TITLE] == module_to_install:
                    log.logger.info(
                        f'Matched {module[utils.TITLE]} to installation candidate'
                    )
                    title = module[utils.TITLE]
                    target = os.path.join(os.getcwd(), title)
                    repo = module[utils.REPOSITORY]

                    try:
                        os.mkdir(target)
                    except OSError:
                        log.logger.info(
                            f'Found {title} already in {os.getcwd()}. Skipping.'
                        )
                        utils.warning_msg(
                            f"The module {title} is already installed. To remove the module, run 'mmpm -r {title}'"
                        )
                        existing_modules.append(title)
                        install_next = True
                        continue

                    os.chdir(target)

                    message = f"Installing {title} @ {target}"
                    utils.separator(message)

                    print(colors.RESET + "Installing " + colors.B_CYAN +
                          f"{title}" + colors.B_YELLOW + " @ " + colors.RESET +
                          f"{target}")

                    utils.separator(message)
                    error_code, _, stderr = utils.clone(title, repo, target)

                    if error_code:
                        utils.warning_msg("\n" + stderr)
                        failed_installs.append(title)
                        install_next = True
                        continue

                    print(utils.done())
                    error: str = utils.handle_installation_process()

                    if error:
                        utils.error_msg(error)
                        failed_installs.append(title)

                    else:
                        successful_installs.append(title)

                    os.chdir(modules_dir)
                    install_next = True
                    break

            if install_next:
                break

    for module in failed_installs:
        failed_install_path = os.path.join(modules_dir, module)
        message = f"Failed to install {title}, removing the directory: '{failed_install_path}'"
        log.logger.info(message)
        utils.error_msg(message)
        utils.run_cmd(['rm', '-rf', failed_install_path], progress=False)

    for module in modules_to_install:
        if module not in successful_installs and module not in existing_modules and module not in failed_installs:
            utils.warning_msg(
                f"Unable to match '{module}' with installation candidate. Is the casing correct?"
            )

    if successful_installs:
        print(
            f"The installed modules may need additional configuring within '{utils.MAGICMIRROR_CONFIG_FILE}'"
        )
        return True

    return False