Example #1
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
Example #2
0
def enhance_modules(modules: dict,
                    update: bool = False,
                    upgrade: bool = False,
                    modules_to_upgrade: List[str] = None) -> bool:
    '''
    Depending on flags passed in as arguments:

    Checks for available module updates, and alerts the user. Or, pulls latest
    version of module(s) from the associated repos.

    If upgrading, a user can upgrade all modules that have available upgrades
    by ommitting additional arguments. Or, upgrade specific modules by
    supplying their case-sensitive name(s) as an addtional argument.

    Parameters:
        modules (dict): Dictionary of MagicMirror modules
        update (bool): Flag to update modules
        upgrade (bool): Flag to upgrade modules
        modules_to_upgrade (List[str]): List of modules to update/upgrade

    Returns:
        None
    '''

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

    installed_modules: dict = get_installed_modules(modules)

    updates_list: List[str] = []

    dirs: List[str] = os.listdir(modules_dir)

    if upgrade and modules_to_upgrade:
        dirs = modules_to_upgrade

    for _, value in installed_modules.items():
        for index, _ in enumerate(value):
            if value[index][utils.TITLE] in dirs:
                title: str = value[index][utils.TITLE]
                curr_module_dir: str = os.path.join(modules_dir, title)
                os.chdir(curr_module_dir)

                if update:
                    utils.plain_print(f"Checking {title} for updates")
                    error_code, stdout, stderr = utils.run_cmd(
                        ["git", "fetch", "--dry-run"])

                    if error_code:
                        utils.error_msg(stderr)
                        return False

                    if stdout:
                        updates_list.append(title)

                    print(utils.done())

                elif upgrade:
                    utils.plain_print(f"Requesting upgrade for {title}")
                    error_code, stdout, stderr = utils.run_cmd(["git", "pull"])

                    if error_code:
                        utils.error_msg(stderr)
                        return False

                    print(utils.done())

                    if "Already up to date." in stdout:
                        print(stdout)
                        continue

                    error_msg: str = utils.handle_installation_process()

                    if error_msg:
                        utils.error_msg(error_msg)
                        return False

                os.chdir(modules_dir)

    os.chdir(original_dir)

    if update:
        if not updates_list:
            utils.plain_print(colors.RESET + "\nNo updates available.\n")
        else:
            utils.plain_print(
                colors.B_MAGENTA +
                "Updates are available for the following modules:\n" +
                colors.RESET)
            for module in updates_list:
                print(f"{module}")
    return True