def install_dependent_packages(packet: Packet, rate_limit: int, install_directory: str, 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['clswitch'], pkg['iswitches'], pkg['uswitches'], 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, pkg['bin'] if 'bin' in list(pkg.keys()) else None, pkg['pre-update'] if 'pre-update' 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) 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['clswitch'], pkg['iswitches'], pkg['uswitches'], 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, pkg['bin'] if 'bin' in list(pkg.keys()) else None, pkg['pre-update'] if 'pre-update' 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 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}', ) from urllib.request import urlretrieve urlretrieve( url=download_url, filename=f'{tempfile.gettempdir()}\Setup{packet.win64_type}', reporthook=limiter ) path = f'{tempfile.gettempdir()}\Setup{packet.win64_type}' 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( f'Installing {packet.display_name}', 'cyan', metadata) log_info( 'Using Rapid Install To Complete Setup, Accept Prompts Asking For Admin Permission...', metadata.logfile) write_verbose('Creating registry start snapshot', metadata) log_info('Creating start snapshot of registry...', metadata.logfile) start_snap = get_environment_keys() 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) # Running The Installer silently And Completing Setup utils.install_package(path, packet, metadata) changes_environment = False if packet.shim: changes_environment = True for shim in packet.shim: replace_install_dir = '' if packet.directory: replace_install_dir = packet.directory elif packet.default_install_dir: replace_install_dir = packet.default_install_dir shim = shim.replace( '<install-directory>', replace_install_dir).replace('<version>', packet.version) shim_name = shim.split( "\\")[-1].split('.')[0].replace('<version>', packet.version) write( f'Generating Shim For {shim_name}', 'cyan', metadata) utils.generate_shim( shim, shim_name, shim.split('.')[-1]) 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: if isinstance(packet.set_env, list): for obj in packet.set_env: name = obj['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) write_verbose( f'Setting Environment Variable {name} to {obj["value"].replace("<install-directory>", replace_install_dir)}', metadata) log_info( f'Setting Environment Variable {name} to {obj["value"].replace("<install-directory>", replace_install_dir)}', metadata.logfile) set_environment_variable( name, obj['value'].replace('<install-directory>', replace_install_dir)) else: 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) write_verbose( f'Setting Environment Variable {name} to {packet.set_env["value"].replace("<install-directory>", replace_install_dir)}', metadata) log_info( f'Setting Environment Variable {name} to {packet.set_env["value"].replace("<install-directory>", replace_install_dir)}', metadata.logfile) set_environment_variable( name, packet.set_env['value'].replace('<install-directory>', replace_install_dir)) write_verbose( 'Creating Final Snapshot Of Environment Keys', metadata) final_snap = get_environment_keys() if final_snap.env_length > start_snap.env_length or final_snap.sys_length > start_snap.sys_length or changes_environment: write('The PATH environment variable has changed. Run `refreshenv` to refresh your environment variables.', 'bright_green', metadata) write_verbose( 'Successfully Verified Installation Of Packages', 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)
def handle_multi_download(self) -> list: from threading import Thread self.handle_dependencies() metadata = self.metadata package_list = [packet.display_name for packet in self.packets] package_list = str(package_list).replace( '[', '').replace(']', '').replace('\'', '') if not metadata.no_color: write( f'SuperCached [ {Fore.LIGHTCYAN_EX}{package_list}{Fore.RESET} ]', 'white', metadata) else: write( f'SuperCached [ {package_list} ]', 'white', metadata) log_info('Initializing Rapid Download', metadata.logfile) packets = self.packets download_items = [] if len(packets) > 1: for idx, packet in enumerate(packets): download_items.append(Download(packet.win64, packet.win64_type, f'Setup{idx}', packet.display_name, f"{tempfile.gettempdir()}\\electric\\Setup{idx}{packet.win64_type}")) elif len(packets) == 1: download_items.append(Download(packets[0].win64, packets[0].win64_type, 'Setup0', packets[0].display_name, f"{tempfile.gettempdir()}\\electric\\Setup0{packets[0].win64_type}")) for item in download_items: write_verbose( f'Sending request to {item.url} for downloading {item.display_name}', self.metadata) write_debug( f'Downloading {item.display_name} from {item.url} into {item.name}{item.extension}', self.metadata) method = self.calculate_spwn(len(packets)) if method == 'threading': threads = [ Thread(target=self.download, args=(item,)) for item in download_items ] for thread in threads: thread.start() for x in threads: x.join() if method == 'processing': from multiprocessing import Process processes = [Process( target=self.download, args=(item,)) for item in download_items] for process in processes: process.start() for x in processes: x.join() for item in download_items: if self.metadata.virus_check: write( f'\nScanning {item.display_name} For Viruses...', 'bright_cyan', metadata) utils.check_virus(item.path, metadata, None) write_debug( f'Rapid Download Successfully Downloaded {len(download_items)} Packages Using RapidThreading', metadata, newline=True) write_debug('Rapid Download Exiting With Code 0', metadata) if not self.metadata.debug: write('\nSuccessfully Downloaded Installation Files', 'bright_green', metadata) else: write('Successfully Downloaded Installation Files', 'bright_green', metadata) log_info('Finished Rapid Download', metadata.logfile) write_verbose('Running Installers Using Multi-Threading', metadata) write( 'Installing Packages', 'cyan', metadata) log_info( 'Using Rapid Install To Complete Setup, Accept ompts Asking For Admin Permission...', metadata.logfile) return paths