def handle_node_package(package_name: str, mode: str, metadata: Metadata): """ Installs a node/npm package handling metadata for the method #### Arguments package_name (str): The name of the node/npm package to be installed version (str): The version of the node/npm package to be installed mode (str): The method (installation/uninstallation) metadata (`Metadata`): Metadata for the method """ version_proc = Popen(mslex.split('npm --version'), stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True) version, err = version_proc.communicate() version = version.decode().strip() if err: click.echo(click.style('npm Or node Is Not Installed. Exit Code [0011]', fg='bright_yellow')) utils.disp_error_msg(utils.get_error_message('0011', 'install', package_name, None, metadata, packet.json_name), metadata) utils.handle_exit('ERROR', None, metadata) if mode == 'install': proc = Popen(mslex.split(f'npm i {package_name} -g'), stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True) write(f'npm v{version} :: Collecting {package_name}', 'bright_green', metadata) package_version = None for line in proc.stdout: line = line.decode() if 'node install.js' in line: write(f'npm v{version} :: Running `node install.js` for {package_name}', 'bright_green', metadata) if package_name in line and '@' in line and 'install' in line or ' postinstall' in line: package_version = line.split()[1] write(f'npm v{version} :: {package_version} Installing To <=> "{line.split()[3]}"', 'bright_green', metadata) if 'Success' in line and package_name in line or 'added' in line: write(f'npm v{version} :: Successfully Installed {package_version}', 'bright_green', metadata) if 'updated' in line: if package_version: write(f'npm v{version} :: Sucessfully Updated {package_version}', 'bright_green', metadata) else: write(f'npm v{version} :: Sucessfully Updated {package_name}', 'bright_green', metadata) else: proc = Popen(mslex.split(f'npm uninstall -g {package_name}'), stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True) for line in proc.stdout: line = line.decode() if 'up to date' in line: write(f'npm v{version} :: Could Not Find Any Existing Installations Of {package_name}', 'bright_yellow', metadata) if 'removed' in line: number = line.split(' ')[1].strip() time = line.split(' ')[4].strip() write(f'npm v{version} :: Sucessfully Uninstalled {package_name} And {number} Other Dependencies in {time}', 'bright_green', metadata)
def handle_atom_package(package_name: str, mode: str, requested_version: str, metadata: Metadata): """ Installs an atom package handling metadata #### Arguments package_name (str): The name of the atom package to be installed version (str): The version of the atom package to be installed mode (str): The method (installation/uninstallation) metadata (`Metadata`): Metadata for the method """ if mode == 'install': proc = Popen('apm'.split(), stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True) proc.communicate() if proc.returncode != 0: click.echo(click.style('Atom Is Not Installed. Exit Code [0113]', fg='bright_yellow')) utils.disp_error_msg(utils.get_error_message('0113', 'install', package_name, None, metadata, package_name), metadata) utils.handle_exit('error', '', metadata) with Halo(f'apm :: Installing {package_name}', text_color='cyan') as h: add_str = f"@{requested_version}" if requested_version else "" command = f'apm install {package_name}' + add_str proc = Popen( command, stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True) for line in proc.stdout: line = line.decode() if 'failed' in line: h.fail( f' Failed to Install {package_name} to <=> {line.split()[3]}') if 'done' in line: h.stop() click.echo(click.style( f' Successfully Installed {package_name} to <=> {line.split()[3]}', 'bright_green')) if mode == 'uninstall': proc = Popen('apm'.split(), stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True) proc.communicate() if proc.returncode != 0: click.echo(click.style('Atom Is Not Installed. Exit Code [0113]', fg='bright_yellow')) utils.disp_error_msg(utils.get_error_message('0113', 'install', package_name, None, metadata, package_name), metadata) utils.handle_exit('error', '', metadata) with Halo(f'apm :: Uninstalling {package_name}', text_color='cyan') as h: add_str = f"@{requested_version}" if requested_version else "" command = f'apm deinstall {package_name}' + add_str proc = Popen( command, stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True) for line in proc.stdout: line = line.decode() if 'failed' in line: h.fail(f' Failed to Uninstall {package_name}') if 'done' in line: h.stop() click.echo(click.style( f' Successfully Uninstalled {package_name}', 'bright_green'))
def handle_sublime_extension(package_name: str, mode: str, metadata: Metadata): """ Installs a sublime text package handling metadata for the method #### Arguments package_name (str): The name of the sublime text package to be installed version (str): The version of the sublime text package to be installed mode (str): The method (installation/uninstallation) metadata (`Metadata`): Metadata for the method """ if mode != 'install': return if utils.find_existing_installation('sublime-text-3', 'Sublime Text 3'): location = PathManager.get_appdata_directory().replace('\electric', '') + \ '\Sublime Text 3' if os.path.isdir(location) and os.path.isfile(fr'{location}\Packages\User\Package Control.sublime-settings'): with open(fr'{location}\Packages\User\Package Control.sublime-settings', 'r') as f: lines = f.readlines() idx = 0 for line in lines: if '"Package Control",' in line.strip(): idx = lines.index(line) if ']' in lines[idx + 1].strip(): lines[idx] = " \"Package Control\"" with open(fr'{location}\Packages\User\Package Control.sublime-settings', 'w') as f: f.writelines(lines) with open(fr'{location}\Packages\User\Package Control.sublime-settings', 'r') as f: json = js.load(f) current_packages = json['installed_packages'] if package_name in current_packages: write(f'{package_name} Is Already Installed!', 'white', metadata) sys.exit() current_packages.append(package_name) updated_packages = current_packages del json['installed_packages'] json['installed_packages'] = updated_packages with open(fr'{location}\Packages\User\Package Control.sublime-settings', 'w+') as f: f.write(js.dumps(json, indent=4)) write( f'Successfully Added {package_name} to Sublime Text 3', 'white', metadata) else: if not os.path.isdir(location): os.mkdir(location) if not os.path.isdir(fr'{location}\Installed Packages'): os.mkdir(fr'{location}\Installed Packages') # Package Control Not Installed with Halo('Installing Package Control', text_color='cyan'): urlretrieve('https://packagecontrol.io/Package%20Control.sublime-package', fr'{location}\Installed Packages\Package Control.sublime-package') if not os.path.isdir(fr'{location}\Packages'): os.mkdir(fr'{location}\Packages') if not os.path.isdir(fr'{location}\Packages\User'): os.mkdir(fr'{location}\Packages\User') with open(fr'{location}\Packages\User\Package Control.sublime-settings', 'w+') as f: f.write( js.dumps({ "bootstrapped": True, "installed_packages": [ "Package Control" ]}, indent=4 ) ) handle_sublime_extension(package_name, mode, metadata) else: click.echo(click.style( 'Sublime Text 3 Is Not Installed. Exit Code [0112]', fg='bright_yellow')) utils.disp_error_msg(utils.get_error_message( '0112', 'install', package_name, None, metadata, package_name), metadata) utils.handle_exit('error', '', metadata)
def handle_vscode_extension(package_name: str, requested_version: str, mode: str, metadata: Metadata): """ Installs a visual studio code package handling metadata for the method #### Arguments package_name (str): The name of the visual studio code package to be installed version (str): The version of the visual studio code package to be installed mode (str): The method (installation/uninstallation) metadata (`Metadata`): Metadata for the method """ base_c = 'code' output = Popen(mslex.split('code --version'), stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True) version, _ = output.communicate() version = version.decode() if output.returncode != 0: output = Popen(mslex.split('code-insiders --version'), stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True) version, _ = output.communicate() version = version.decode() base_c = 'code-insiders' if output.returncode != 0: click.echo(click.style( 'Visual Studio Code Or vscode Is Not Installed. Exit Code [0111]', fg='bright_yellow')) utils.disp_error_msg(utils.get_error_message( '0111', 'install', package_name, None, metadata, package_name), metadata) utils.handle_exit('error', '', metadata) version = version.strip().split('\n')[0] if mode == 'install': add_str = f"@{requested_version}" if requested_version else "" command = f'{base_c} --install-extension {package_name}{add_str} --force' proc = Popen(mslex.split(command), stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True) success = False for line in proc.stdout: line = line.decode() if 'Installing extensions' in line: if metadata.no_color: write( f'Code v{version} :: Installing {package_name}', 'white', metadata) else: write( f'Code v{version} :: Installing {Fore.LIGHTMAGENTA_EX}{package_name}{Fore.RESET}', 'bright_green', metadata) if 'is already installed' in line: success = True if metadata.no_color: write( f'Code v{version} :: {package_name} Is Already Installed!', 'white', metadata) else: write( f'{Fore.LIGHTGREEN_EX}Code v{version} :: {Fore.LIGHTMAGENTA_EX}{package_name}{Fore.LIGHTYELLOW_EX} Is Already Installed!', 'white', metadata) if 'was successfully installed' in line: if metadata.no_color: write( f'Code v{version} :: Successfully Installed {package_name}', 'white', metadata) success = True else: write( f'{Fore.LIGHTGREEN_EX}Code v{version} :: Successfully Installed {Fore.LIGHTMAGENTA_EX}{package_name}{Fore.RESET}', 'bright_green', metadata) if not success: write( f'{Fore.LIGHTGREEN_EX}Code v{version} :: Successfully Installed {Fore.LIGHTMAGENTA_EX}{package_name}{Fore.RESET}', 'bright_green', metadata) if mode == 'uninstall': add_str = f"@{requested_version}" if requested_version else "" command = f'{base_c} --uninstall-extension {package_name}{add_str} --force' proc = Popen(mslex.split(command), stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True) for line in proc.stdout: line = line.decode() if 'Uninstalling' in line: if metadata.no_color: write(f'Code v{version} :: Uninstalling {package_name}', 'white', metadata) else: write( f'Code v{version} :: Uninstalling {Fore.LIGHTMAGENTA_EX}{package_name}{Fore.RESET}', 'bright_green', metadata) if 'is not installed' in line: if metadata.no_color: write(f'Code v{version} :: {package_name} is not installed!', 'white', metadata) else: write(f'{Fore.LIGHTGREEN_EX}Code v{version} :: {Fore.LIGHTMAGENTA_EX}{package_name}{Fore.LIGHTYELLOW_EX} is not installed!', 'white', metadata) if 'was successfully uninstalled' in line: if metadata.no_color: write(f'Code v{version} :: Successfully Uninstalled {package_name}', 'white', metadata) else: write(f'{Fore.LIGHTGREEN_EX}Code v{version} :: Successfully Uninstalled {Fore.LIGHTMAGENTA_EX}{package_name}{Fore.RESET}', 'bright_green', metadata)
def handle_python_package(package_name: str, version: str, mode: str, metadata: Metadata): """ Installs a python package handling metadata for the method #### Arguments package_name (str): The name of the python package to be installed version (str): The version of the python package to be installed mode (str): The method (installation/uninstallation) metadata (`Metadata`): Metadata for the method """ command = '' valid = Popen(mslex.split('pip --version'), stdin=PIPE, stdout=PIPE, stderr=PIPE) _, err = valid.communicate() if err: click.echo(click.style( 'Python Is Not Installed. Exit Code [0011]', fg='red')) utils.disp_error_msg(utils.get_error_message( '0011', 'install', package_name, None, metadata, package_name), metadata) utils.handle_exit('ERROR', None, metadata) if mode == 'install': command = 'python -m pip install --upgrade --no-input' command += f' {package_name}' if version != 'latest': command += f'=={version}' proc = Popen(mslex.split(command), stdin=PIPE, stdout=PIPE, stderr=PIPE) py_version = sys.version.split() for line in proc.stdout: line = line.decode('utf-8') if f'Collecting {package_name}' in line: write( f'Python v{py_version[0]} :: Collecting {package_name}', 'bright_green', metadata) if 'Downloading' in line and package_name in line: write( f'Python v{py_version[0]} :: Downloading {package_name}', 'bright_green', metadata) if 'Installing collected packages' in line and package_name in line: write( f'Python v{py_version[0]} :: Installing {package_name}', 'bright_green', metadata) if f'Requirement ' in line and package_name in line: write( f'Python v{py_version[0]} :: {package_name} Is Already Installed And On The Latest Version ==> {line.split()[-1]}', 'bright_yellow', metadata) break if 'Successfully installed' in line and package_name in line: ver = line.split('-')[1] write( f'Python v{py_version[0]} :: Successfully Installed {package_name} {ver}', 'bright_green', metadata) if 'You should consider upgrading via' in line: wants = utils.confirm( 'Would you like to upgrade your pip version?') if wants: write('Updating Pip Version', 'bright_green', metadata) Popen(mslex.split('python -m pip install --upgrade pip')) elif mode == 'uninstall': command = 'python -m pip uninstall --no-input --yes' command += f' {package_name}' if version: command += f'=={version}' proc = Popen(mslex.split(command), stdin=PIPE, stdout=PIPE, stderr=PIPE) py_version = sys.version.split() for line in proc.stdout: line = line.decode('utf-8') if 'Uninstalling' in line and package_name in line: write( f'Python v{py_version[0]} :: Uninstalling {package_name}', 'bright_green', metadata) if 'Successfully uninstalled' in line and package_name in line: ver = line.split('-')[1] write( f'Python v{py_version[0]} :: Successfully Uninstalled {package_name} {ver}', 'bright_green', metadata) _, err = proc.communicate() if err: err = err.decode('utf-8') if f'WARNING: Skipping {package_name}' in err: write( f'Python v{py_version[0]} :: Could Not Find Any Installations Of {package_name}', 'bright_yellow', metadata)
def install_dependent_packages(packet: Packet, rate_limit: int, install_directory: str, metadata: Metadata): from limit import Limiter, TokenBucket from registry import get_environment_keys disp = str(packet.dependencies).replace("[", "").replace("]", "").replace( "\'", "") write(f'{packet.display_name} has the following dependencies: {disp}', 'bright_yellow', metadata) continue_install = confirm( 'Would you like to install the above dependencies ?') if continue_install: write(f'Installing Dependencies For => {packet.display_name}', 'cyan', metadata) if len(packet.dependencies) > 1 and len(packet.dependencies) <= 5: write( f'Using Parallel Installation For Installing Dependencies', 'bright_green', metadata) packets = [] for package in packet.dependencies: res = utils.send_req_package(package) pkg = res keys = list(pkg.keys()) idx = 0 for key in keys: if key not in [ 'package-name', 'nightly', 'display-name' ]: idx = keys.index(key) break version = keys[idx] pkg = pkg[version] custom_dir = None if install_directory: custom_dir = install_directory + \ f'\\{pkg["package-name"]}' else: custom_dir = install_directory install_exit_codes = None if 'valid-install-exit-codes' in list(pkg.keys()): install_exit_codes = pkg['valid-install-exit-codes'] packet = Packet( package, res['package-name'], pkg['url'], pkg['file-type'], pkg['custom-location'], pkg['install-switches'], pkg['uninstall-switches'], custom_dir, pkg['dependencies'], install_exit_codes, None, pkg['set-env'] if 'set-env' in list(pkg.keys()) else None, pkg['default-install-dir'] if 'default-install-dir' in list(pkg.keys()) else None, pkg['uninstall'] if 'uninstall' in list(pkg.keys()) else [], pkg['add-path'] if 'add-path' in list(pkg.keys()) else None, pkg['checksum'] if 'checksum' in list(pkg.keys()) else None, ) installation = utils.find_existing_installation( package, packet.json_name) if installation: write_debug( f'Aborting Installation As {packet.json_name} is already installed.', metadata) write_verbose( f'Found an existing installation of => {packet.json_name}', metadata) write( f'Found an existing installation {packet.json_name}.', 'bright_yellow', metadata) installation_continue = confirm( f'Would you like to reinstall {packet.json_name}') if installation_continue or metadata.yes: os.system(f'electric uninstall {packet.json_name}') os.system(f'electric install {packet.json_name}') return else: utils.handle_exit('ERROR', None, metadata) write_verbose( f'Package to be installed: {packet.json_name}', metadata) log_info(f'Package to be installed: {packet.json_name}', metadata.logfile) write_verbose( f'Finding closest match to {packet.json_name}...', metadata) log_info(f'Finding closest match to {packet.json_name}...', metadata.logfile) packets.append(packet) write_verbose('Generating system download path...', metadata) log_info('Generating system download path...', metadata.logfile) manager = ThreadedInstaller(packets, metadata) paths = manager.handle_multi_download() log_info('Finished Rapid Download...', metadata.logfile) log_info( 'Using Rapid Install To Complete Setup, Accept Prompts Asking For Admin Permission...', metadata.logfile) manager.handle_multi_install(paths) return else: write('Starting Sync Installation', 'bright_green', metadata) for package in packet.dependencies: res = utils.send_req_package(package) write( f'SuperCached [ {Fore.LIGHTCYAN_EX}{res["display-name"]}{Fore.RESET} ]', 'white', metadata) pkg = res[res['latest-version']] log_info('Generating Packet For Further Installation.', metadata.logfile) install_exit_codes = None if 'valid-install-exit-codes' in list(pkg.keys()): install_exit_codes = pkg['valid-install-exit-codes'] packet = Packet( res, res['package-name'], res['display-name'], pkg['url'], pkg['file-type'], pkg['custom-location'], pkg['install-switches'], pkg['uninstall-switches'], install_directory, pkg['dependencies'], install_exit_codes, [], None, False, pkg['set-env'] if 'set-env' in list(pkg.keys()) else None, pkg['default-install-dir'] if 'default-install-dir' in list(pkg.keys()) else None, pkg['uninstall'] if 'uninstall' in list(pkg.keys()) else [], pkg['add-path'] if 'add-path' in list(pkg.keys()) else None, pkg['checksum'] if 'checksum' in list(pkg.keys()) else None, ) log_info('Searching for existing installation of package.', metadata.logfile) installation = utils.find_existing_installation( package, packet.json_name) if installation: write_debug( f'Found existing installation of {packet.json_name}.', metadata) write_verbose( f'Found an existing installation of => {packet.json_name}', metadata) write( f'Found an existing installation {packet.json_name}.', 'bright_yellow', metadata) continue if packet.dependencies: ThreadedInstaller.install_dependent_packages( packet, rate_limit, install_directory, metadata) write_verbose( f'Package to be installed: {packet.json_name}', metadata) log_info(f'Package to be installed: {packet.json_name}', metadata.logfile) write_verbose('Generating system download path...', metadata) log_info('Generating system download path...', metadata.logfile) download_url = packet.win64 write('Initializing Rapid Download', 'bright_green', metadata) log_info('Initializing Rapid Download...', metadata.logfile) # Downloading The File From Source write_debug( f'Downloading {packet.display_name} from => {packet.win64}', metadata) write_verbose(f"Downloading from '{download_url}'", metadata) log_info(f"Downloading from '{download_url}'", metadata.logfile) if rate_limit == -1: path = utils.download(download_url, packet.json_name, metadata, packet.win64_type) else: log_info( f'Starting rate-limited installation => {rate_limit}', metadata.logfile) bucket = TokenBucket(tokens=10 * rate_limit, fill_rate=rate_limit) limiter = Limiter( bucket=bucket, filename= f'{tempfile.gettempdir()}\Setup{packet.win64_type}', ) urlretrieve( url=download_url, filename= f'{tempfile.gettempdir()}\Setup{packet.win64_type}', reporthook=limiter) path = f'{tempfile.gettempdir()}\Setup{packet.win64_type}' write('Completed Rapid Download', 'bright_green', metadata) log_info('Finished Rapid Download', metadata.logfile) if metadata.virus_check: write('Scanning File For Viruses...', 'bright_cyan', metadata) utils.check_virus(path, metadata) write( 'Using Rapid Install, Accept Prompts Asking For Admin Permission...', 'cyan', metadata) log_info( 'Using Rapid Install To Complete Setup, Accept Prompts Asking For Admin Permission...', metadata.logfile) write_debug( f'Installing {packet.json_name} through Setup{packet.win64_type}', metadata) log_info( f'Installing {packet.json_name} through Setup{packet.win64_type}', metadata.logfile) start_snap = get_environment_keys() # Running The Installer silently And Completing Setup utils.install_package(path, packet, metadata) if packet.add_path: replace_install_dir = '' if packet.directory: replace_install_dir = packet.directory elif packet.default_install_dir: replace_install_dir = packet.default_install_dir write( f'Appending "{packet.add_path.replace("<install-directory>", replace_install_dir)}" To PATH', 'bright_green', metadata) utils.append_to_path( packet.add_path.replace('<install-directory>', replace_install_dir)) if packet.set_env: name = packet.set_env['name'] replace_install_dir = '' if packet.directory: replace_install_dir = packet.directory elif packet.default_install_dir: replace_install_dir = packet.default_install_dir write(f'Setting Environment Variable {name}', 'bright_green', metadata) set_environment_variable( name, packet.set_env['value'].replace( '<install-directory>', replace_install_dir)) final_snap = get_environment_keys() if final_snap.env_length > start_snap.env_length or final_snap.sys_length > start_snap.sys_length: write('Refreshing Environment Variables...', 'bright_green', metadata) start = timer() log_info( 'Refreshing Environment Variables At scripts/refreshvars.cmd', metadata.logfile) write_debug( 'Refreshing Env Variables, Calling Batch Script At scripts/refreshvars.cmd', metadata) write_verbose('Refreshing Environment Variables', metadata) utils.refresh_environment_variables() end = timer() write_debug( f'Successfully Refreshed Environment Variables in {round(end - start)} seconds', metadata) write(f'Successfully Installed {packet.display_name}!', 'bright_magenta', metadata) log_info(f'Successfully Installed {packet.display_name}!', metadata.logfile) utils.register_package_success(packet, install_directory, metadata) if metadata.reduce_package: os.remove(path) try: os.remove( Rf'{tempfile.gettempdir()}\downloadcache.pickle' ) except: pass log_info( 'Successfully Cleaned Up Installer From Temporary Directory And DownloadCache', metadata.logfile) write( 'Successfully Cleaned Up Installer From Temp Directory...', 'bright_green', metadata) write_verbose('Dependency successfully Installed.', metadata) log_info('Dependency successfully Installed.', metadata.logfile) else: os._exit(1)