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
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