def removing_package_event(self, pkg: Pkg): """ will run as package remover event while starting removing a package """ pr.p('Removing ' + ansi.yellow + pkg.data['name'] + ' (' + pkg.data['version'] + ')' + ansi.reset + '...', end=' ')
def show_once(self, package: Pkg): """ show once item in loaded packages list """ if self.has_option('-q') or self.has_option('--quiet'): pr.p(package.data['name']) return output = ansi.green + package.data[ 'name'] + ansi.reset + '/' + ansi.yellow + package.data[ 'version'] + ansi.reset if package.installed(): if package.is_installed_manual(package.data['name']): output += '/Installed-Manual:' + ansi.blue + package.installed( ).strip() + ansi.reset else: output += '/Installed:' + ansi.blue + package.installed( ).strip() + ansi.reset output += '/[' + package.data['repo'] + ']' # if verbose output wanted, show first line of description if self.is_verbose(): try: description_summary = package.data['description'].split( '\n')[0] if description_summary != '': output += '/ ' + ansi.header + description_summary + ansi.reset except: pass pr.p(output)
def download_once(self, pkg, output=None): """ Download once package """ try: file_path = pkg.data['file_path'] except: self.message('package "' + pkg.data['name'] + '" is local and cannot be downloaded' + ansi.reset, is_error=True, before=ansi.red) return False if not self.is_quiet(): pr.p('Downloading ' + pkg.data['name'] + ':' + pkg.data['version'] + ':' + pkg.data['arch'] + '...') if output == None: output = file_path.split('/')[-1] if file_path[:7] == 'http://' or file_path[:8] == 'https://': i = 0 while i < 5: res = DownloadProgress.download(file_path, output) if res == True: break else: pr.e(ansi.red + str(res) + ansi.reset) i += 1 if i == 5: return False else: if not os.path.isfile(file_path): return False shutil.copy(file_path, output) return True
def sub_build(self): """ build subcommand (cati pkg build) """ if len(self.arguments) <= 1: self.message('argument package directory(s) required') return 1 i = 1 while i < len(self.arguments): try: output = self.option_value('--output') if output == None: output = self.option_value('-o') builder = Builder() output_package = builder.build(self.arguments[i], output) if not self.is_quiet(): pr.p(ansi.green + 'Package ' + self.arguments[i] + ' created successfuly in ' + output_package + ansi.reset) except FileNotFoundError as ex: self.message('directory "' + self.arguments[i] + '" not found' + ansi.reset, before=ansi.red) return 1 except InvalidPackageDirException as ex: self.message('cannot build "' + self.arguments[i] + '": ' + str(ex) + ansi.reset, before=ansi.red) return 1 i += 1
def package_new_installs_event(self, package: BaseArchive): """ installer package_new_installs event will run when package will NEW installed """ pr.p('Installing ' + ansi.yellow + package.data['name'] + ':' + package.data['version'] + ansi.reset + '...', end=' ')
def install_once(self, pkg: BaseArchive): """ installs once package is called from install sub command """ target_path = self.option_value('--target') if target_path == None: target_path = '' installer = Installer() try: out = installer.install( pkg, { 'cannot_read_file': self.cannot_read_file_event, 'invalid_json_data': self.invalid_json_data_event, }, { 'package_currently_installed': self.package_currently_installed_event, 'package_new_installs': self.package_new_installs_event, 'package_installed': self.package_installed_event, 'directory_not_empty': self.directory_not_empty_event, 'dep_and_conflict_error': self.dep_and_conflict_error_event, 'arch_error': self.arch_error_event, }, (not self.has_option('--auto')), run_scripts=(not self.has_option('--without-scripts')), target_path=str(target_path), keep_conffiles=self.has_option('--keep-conffiles'), check_security_blacklist=(not self.has_option('--force') and not self.has_option('-f'))) if type(out) == int: return out except PackageScriptError as ex: pr.e(ansi.red + 'cannot install "' + pkg.data['name'] + ':' + pkg.data['version'] + '": ' + str(ex) + ansi.reset) return 1 except PackageIsInSecurityBlacklist as ex: pr.e(ansi.red + 'cannot install ' + pkg.data['name'] + ':' + pkg.data['version'] + ' because this is in security blacklist:') pr.e(' ' + ex.blacklist_item['title'] + ':') for l in ex.blacklist_item['description'].split('\n'): pr.e('\t' + l) pr.p(ansi.reset, end='') return 1 except CannotReadFileException as ex: self.message(ansi.red + str(ex), True, before=ansi.reset) return 1 except FileConflictError as ex: pr.e(ansi.red + '\nCannot install ' + pkg.data['name'] + ':' + pkg.data['version'] + ': File conflict error:') pr.e(' ' + str(ex)) pr.p(ansi.reset, end='') return 1
def package_currently_installed_event(self, package: BaseArchive, current_version: str): """ installer package_currently_installed event will run when package already installed gets package and current installed version """ pr.p('Installing ' + ansi.yellow + package.data['name'] + ':' + package.data['version'] + ansi.reset + ' (over ' + ansi.yellow + current_version + ansi.reset + ')...', end=' ')
def show_once(self, pkg: BaseArchive): """ shows once package (called from `show` subcommand function) gives package data to cli package sohwer component to show package info """ PackageShower.show(pkg.data) if self.has_option('--files') or self.has_option('-f'): pr.p('Files:') pkg.tar.list() if len(self.arguments) > 2: pr.p('=' * 50)
def run(self): """ Run command """ if not self.is_quiet(): pr.p('Loading packages list...') pr.p('========================') loaded_packages = [] for argument in self.arguments: arg_parts = argument.split('=') if len(arg_parts) == 1: # load last version as default pkg = Pkg.load_last(argument) elif len(arg_parts) == 2: # load specify version pkg = Pkg.load_version(arg_parts[0], arg_parts[1]) if pkg == 1: pkg = False elif pkg == 2: self.message('package "' + arg_parts[0] + '" has not version "' + arg_parts[1] + '"' + ansi.reset, before=ansi.red) continue else: # load specify version and specify arch pkg = Pkg.load_version(arg_parts[0], arg_parts[1], arg_parts[2]) if pkg == 1: pkg = False elif pkg == 2: self.message('package "' + arg_parts[0] + '" has not version or arch "' + arg_parts[1] + ':' + arg_parts[2] + '"' + ansi.reset, before=ansi.red) continue if pkg: loaded_packages.append(pkg) else: self.message('unknow package "' + argument + '"' + ansi.reset, before=ansi.red) if not loaded_packages: return 1 # download loaded packages is_any_success = False output_path = self.option_value('--output') for pkg in loaded_packages: if len(loaded_packages) > 1: tmp = self.download_once(pkg) else: tmp = self.download_once(pkg, output_path) if tmp: is_any_success = True if not is_any_success: return 1
def run(self): """ Run command """ if len(self.arguments) <= 0: pr.p(self.help_full()) return 0 if self.arguments[0] == 'build': return self.sub_build() elif self.arguments[0] == 'show': return self.sub_show() elif self.arguments[0] == 'install': return self.sub_install() else: self.message('unknow subcommand "' + self.arguments[0] + '"', True) return 1
def message(self, msg, is_error=False, before=''): """ Prints a message like this: `cati: <command-name>: <the-message>` Args: is_error: (bool) if this is True, message will print on stderr before: (str) before will print in the first of message for example `message("hello world")` will print `cati: cmdname: hello world` but `message("hello world", before="AAA ")` will print `AAA cati: cmdname: hello world` """ msg = before + self.cati_exec + ': ' + self.name + ': ' + msg if is_error: pr.e(msg) else: pr.p(msg)
def run(self): """ Run command """ if self.has_option('--edit') or self.has_option('-e'): return os.system('vim "' + Env.repos_config() + '"') if self.has_option('--add') or self.has_option('-a'): RootRequired.require_root_permission() repo_string = '' for arg in self.arguments: repo_string += arg + ' ' repo_string = repo_string.strip() tmp_repo = Repo(repo_string) tmp_repo.loaded_from_file = 'argument' tmp_repo.line_number = 0 if not tmp_repo.successful_loaded: ReposListErrorShower.show([tmp_repo]) return 1 # write repo path = Env.repos_config_dir('/' + tmp_repo.name + '-' + tmp_repo.get_pkg_str() + '-' + tmp_repo.get_arch_str()) tmp = '' tmp_i = 1 while os.path.isfile(path + tmp): tmp = '-' + str(tmp_i) f = open(path, 'w') f.write('# added manually\n' + repo_string) f.close() return 0 if self.has_option('--scan'): for arg in self.arguments: if os.path.isdir(arg): Scanner.scan(arg) pr.p(ansi.green + 'directory ' + arg + ' scanned successfully' + ansi.reset) else: self.message('directory' + arg + ' not found', is_error=True) return 0 # show list of repos if not self.is_quiet(): pr.p('Loading repositories list...') repos = Repo.get_list() if not self.is_quiet(): pr.p('============================') ReposListErrorShower.show(repos) for repo in repos: if repo.successful_loaded: pr.p(repo.name + ': ' + repo.url + ' pkg=' + repo.get_pkg_str() + ' arch=' + repo.get_arch_str() + ' channel=' + repo.get_channel_str())
def run(self): """ Run command """ pr.p('Loading packages list...') pr.p('========================') loaded_packages = [] for argument in self.arguments: arg_parts = argument.split('=') if len(arg_parts) == 1: # load last version as default pkg = Pkg.load_last(argument) else: # load specify version pkg = Pkg.load_version(arg_parts[0], arg_parts[1]) if pkg == 1: pkg = False elif pkg == 2: self.message('package "' + arg_parts[0] + '" has not version "' + arg_parts[1] + '"' + ansi.reset, before=ansi.red) continue if pkg: loaded_packages.append(pkg) else: self.message('unknow package "' + argument + '"' + ansi.reset, before=ansi.red) if not loaded_packages: return 1 # show loaded packages for pkg in loaded_packages: if self.has_option('--versions'): versions_list = pkg.get_versions_list() pr.p(pkg.data['name'] + ':') for ver in versions_list: pr.p(' ' + ver[0] + ':' + ver[1]) else: PackageShower.show(pkg.data) if len(loaded_packages) > 1: pr.p('---------------------')
def run(self): """ Run command """ if not self.is_quiet(): pr.p('Checking unused packages...') self.unused_packages = [] self.find_unused_packages() unused_packages = self.unused_packages package_names = [pkg.data['name'] for pkg in unused_packages] options = [op for op in self.args['options']] if not package_names: pr.p('There is not any unused package') return 0 remove_cmd = RemoveCommand() return remove_cmd.handle( ArgParser.parse(['cati', 'remove', *package_names, *options]))
def show(state_list: list): """ Shows and renders list of undoned transactions in state Args: state_list: loaded state from `transaction.BaseTransaction.state_list()` as (list) """ pr.e(ansi.yellow + 'Error: state is not done') pr.p('\tthere is some undoned transactions:') for item in state_list: pr.p('\t\t' + BaseTransaction.state_item_to_string(item)) pr.p('to complete them, run `' + sys.argv[0] + ' state --complete`') pr.p(ansi.reset, end='')
def run(self): """ Run command """ # join all of arguments as one argument full_query_string = '' if len(self.arguments) > 1: for arg in self.arguments: full_query_string += arg + ' ' full_query_string = full_query_string[:len(full_query_string)-1] else: full_query_string = self.arguments[0] result = Pkg.check_state(full_query_string) if result: if not self.is_quiet(): pr.p(ansi.green + 'True' + ansi.reset) return 0 else: if not self.is_quiet(): pr.p(ansi.red + 'False' + ansi.reset) return 1
def run(self): """ Run command """ RootRequired.require_root_permission() for f in os.listdir(Env.cache_dir()): if os.path.isfile(Env.cache_dir('/' + f)): if self.is_verbose(): pr.p('removing ' + Env.cache_dir('/' + f) + '...') os.remove(Env.cache_dir('/' + f)) for f in os.listdir(Env.cache_dir('/archives')): if os.path.isfile(Env.cache_dir('/archives/' + f)): if self.is_verbose(): pr.p('removing ' + Env.cache_dir('/archives/' + f) + '...') os.remove(Env.cache_dir('/archives/' + f)) pr.p(ansi.green + 'Cache files cleared successfully' + ansi.reset)
def run(self): """ Run command """ RootRequired.require_root_permission() pr.p('Loading packages list...') pr.p('========================') loaded_packages = [] for argument in self.arguments: arg_parts = argument.split('=') if len(arg_parts) == 1: # load last version as default pkg = Pkg.load_last(argument) else: # load specify version pkg = Pkg.load_version(arg_parts[0], arg_parts[1]) if pkg == 1: pkg = False elif pkg == 2: self.message('package "' + arg_parts[0] + '" has not version "' + arg_parts[1] + '"' + ansi.reset, before=ansi.red) continue else: pkg.only_specify_version = True if pkg: try: pkg.only_specify_version except: pkg.only_specify_version = False if pkg.installed(): if not pkg.only_specify_version: self.message( 'package "' + argument + '" is installed. cannot forget installed packages' + ansi.reset, before=ansi.red) continue else: if pkg.installed() == pkg.data['version']: self.message( 'package ' + argument + ' (' + pkg.data['version'] + ') is installed. cannot forget installed packages' + ansi.reset, before=ansi.red) continue loaded_packages.append(pkg) else: self.message('unknow package "' + argument + '"' + ansi.reset, before=ansi.red) if not loaded_packages: return 1 # forget loaded packages for pkg in loaded_packages: if not pkg.only_specify_version: # forget all of package versions shutil.rmtree(Env.packages_lists('/' + pkg.data['name'])) pr.p('Package ' + pkg.data['name'] + ' was forgoten successfully') else: files = glob.glob( Env.packages_lists('/' + pkg.data['name'] + '/' + pkg.data['version'] + '-*')) for f in files: if not '-' in f[len( Env.packages_lists('/' + pkg.data['name'] + '/' + pkg.data['version'] + '-')):]: os.remove(f) pr.p('Version ' + pkg.data['version'] + ' of package ' + pkg.data['name'] + ' was forgoten successfully') try: if len(os.listdir( Env.packages_lists('/' + pkg.data['name']))) <= 1: shutil.rmtree(Env.packages_lists('/' + pkg.data['name'])) except: pass ListUpdater.update_indexes({ 'cannot_read_file': self.empty_method_for_event, 'invalid_json_data': self.empty_method_for_event, })
def sub_install(self): """ install sub command (cati pkg install) """ if len(self.arguments) <= 1: self.message('argument package file(s) required') return 1 require_root_permission() # check transactions state before run new transactions pr.p('Checking transactions state...') state_list = BaseTransaction.state_list( ) # get list of undoned transactions if state_list: # the list is not empty StateContentShower.show(state_list) return 1 packages_to_install = [] i = 1 while i < len(self.arguments): try: pkg = archive_factory(self.arguments[i], 'r') pkg.read() pkg.package_file_path = os.path.abspath(self.arguments[i]) packages_to_install.append(pkg) except FileNotFoundError as ex: self.message('file "' + self.arguments[i] + '" not found' + ansi.reset, before=ansi.red) return 1 except: self.message('cannot open "' + self.arguments[i] + '": file is corrupt' + ansi.reset, before=ansi.red) return 1 i += 1 # add packages to state state_f = open(Env.state_file(), 'w') tmp = '' for pkg in packages_to_install: tmp += ('install%' + pkg.data['name'] + '%' + pkg.data['version'] + '%' + pkg.data['arch'] + '%' + pkg.package_file_path + '\n') state_f.write(tmp) state_f.close() packages_to_install_names_and_versions = [ pkg.data['name'] + '@' + pkg.data['version'] for pkg in packages_to_install ] i = 0 while i < len(packages_to_install): try: pkg = packages_to_install[i] tmp = self.install_once(pkg) if type(tmp) == int and tmp != 0: if not self.has_option('--dont-ignore-state'): BaseTransaction.finish_all_state() return tmp pkg.close() except: if not self.has_option('--dont-ignore-state'): BaseTransaction.finish_all_state() self.message('cannot install "' + packages_to_install[i].data['name'] + '"' + ansi.reset, before=ansi.red) return 1 i += 1 BaseTransaction.run_any_scripts( ['install', packages_to_install_names_and_versions], events={ 'start_run_script': self.start_run_any_script_event, }) BaseTransaction.finish_all_state()
def run(self): """ Run command """ if self.has_option('--installed'): if not self.is_quiet(): pr.p('Loading files list...') pr.p('=====================') all_of_installed_files_list = Pkg.get_all_installed_files_list() for item in all_of_installed_files_list: if self.is_quiet(): pr.p(item[2]) else: message = '' if item[1] == 'd': message = ' (directory)' elif item[1] == 'cf': message = ' (config file)' elif item[1] == 'cd': message = ' (config directory)' pr.p(item[0] + ': ' + item[2] + message) return 0 if not self.arguments: self.message('argument package names is required', True) return 1 if not self.is_quiet(): pr.p('Loading packages list...') pr.p('========================') loaded_packages = [] for argument in self.arguments: arg_parts = argument.split('=') if len(arg_parts) == 1: # load last version as default pkg = Pkg.load_last(argument) else: # load specify version pkg = Pkg.load_version(arg_parts[0], arg_parts[1]) if pkg == 1: pkg = False elif pkg == 2: self.message('package "' + arg_parts[0] + '" has not version "' + arg_parts[1] + '"' + ansi.reset, before=ansi.red) continue if pkg: loaded_packages.append(pkg) else: self.message('unknow package "' + argument + '"' + ansi.reset, before=ansi.red) if not loaded_packages: return 1 # show files list of loaded packages for pkg in loaded_packages: try: files_list = pkg.data['files'] except: files_list = [] if not self.is_quiet(): pr.p(pkg.data['name'] + ':') if not files_list: pr.p(ansi.yellow + ' This package is empty' + ansi.reset) for item in files_list: pr.p(' ' + item) else: for item in files_list: pr.p(item) if len(loaded_packages) > 1: if not self.is_quiet(): pr.p('========================')
def run(self): """ Run command """ if not self.is_quiet(): pr.p('Loading packages list...') pr.p('========================') loaded_packages = [] for argument in self.arguments: pkg = Pkg.load_last(argument) if pkg: loaded_packages.append(pkg) else: self.message('unknow package "' + argument + '"' + ansi.reset, before=ansi.red) if not loaded_packages: return 1 # show loaded packages for pkg in loaded_packages: # load reverse depends rdepends = pkg.get_reverse_depends() if not self.is_quiet(): pr.p(pkg.data['name'] + ':') if not rdepends: if not self.is_quiet(): pr.p(' This package has not any reverse dependency') for item in rdepends: if not self.is_quiet(): pr.p(' ' + item.data['name'] + '=' + item.data['version']) else: pr.p(item.data['name'] + '=' + item.data['version']) if len(loaded_packages) > 1: if not self.is_quiet(): pr.p('========================')
def run(self): """ Run command """ # require root permission require_root_permission() result_code = 0 packages_to_reinstall = [] if not self.is_quiet(): pr.p('Starting checking system health and security...') pr.p('===============================================') # check state state_cmd = StateCommand() out = state_cmd.handle(ArgParser.parse(['cati', 'state'])) if out > 0: return out # search for conflict and dependency corruptions if not self.is_quiet(): pr.p('Checking dependency and conflict corruptions...') dependency_problems = [] conflict_problems = [] installed_packages = Pkg.installed_list()['list'] for pkg in installed_packages: if self.is_verbose(): pr.p('[info] checking dependencies and conflicts for ' + pkg.data['name'] + '...') for dp in pkg.get_depends(): if not Pkg.check_state(dp): dependency_problems.append([pkg, dp]) for conflict in pkg.get_conflicts(): if Pkg.check_state(conflict): conflict_problems.append([pkg, conflict]) if dependency_problems or conflict_problems: for depend in dependency_problems: pr.p(ansi.red + 'dependency problem for ' + depend[0].data['name'] + ': ' + depend[1] + ansi.reset) packages_to_reinstall.append(depend[0]) for conflict in conflict_problems: pr.p(ansi.red + 'conflict problem for ' + conflict[0].data['name'] + ': ' + conflict[1] + ansi.reset) packages_to_reinstall.append(conflict[0]) result_code = 1 else: pr.p( ansi.green + 'There is not any conflict or dependnecy problem and everything is ok' + ansi.reset) # check static files if not self.is_quiet(): pr.p('Checking packages static files...') staticfile_problems = [] for pkg in installed_packages: if self.is_verbose(): pr.p('[info] checking static files for ' + pkg.data['name'] + '...') files = pkg.installed_static_files() for f in files: f[1] = Env.base_path(f[1]) if os.path.isfile(f[1]): wanted_hash = f[0] current_hash = calc_file_sha256(f[1]) if wanted_hash != current_hash: staticfile_problems.append([pkg, f, 'file is changed']) else: staticfile_problems.append([pkg, f, 'file is deleted']) if staticfile_problems: for problem in staticfile_problems: pr.p(ansi.red + 'staticfile problem in package ' + problem[0].data['name'] + ': ' + problem[1][1] + ': ' + problem[2] + ansi.reset) packages_to_reinstall.append(problem[0]) result_code = 1 else: pr.p(ansi.green + 'all of static files are ok' + ansi.reset) # check repos config files health if not self.is_quiet(): pr.p('Checking cati configuration files...') if self.is_verbose(): pr.p('[info] checking repositories config...') repos = Repo.get_list() pr.p(ansi.red, end='') ReposListErrorShower.show(repos) pr.p(ansi.reset, end='') is_any_repo_error = False for repo in repos: if repo.syntax_errors: is_any_repo_error = True result_code = 1 if not is_any_repo_error: pr.p(ansi.green + 'all of cati configuration files are ok' + ansi.reset) # check database files if not self.is_quiet(): pr.p('Checking cati database...') database_problems = [] for f in os.listdir(Env.installed_lists()): if self.is_verbose(): pr.p('[info] checking database install dir for ' + f + '...') if not os.path.isfile(Env.installed_lists( '/' + f + '/files')) or not os.path.isfile( Env.installed_lists('/' + f + '/ver')): database_problems.append( 'installed packages database: directory ' + Env.installed_lists('/' + f) + ' is corrupt') for f in os.listdir(Env.security_blacklist()): if self.is_verbose(): pr.p('[info] checking security blacklist part ' + f + '...') if not os.path.isfile(Env.security_blacklist('/' + f)): database_problems.append( 'security blacklist: an directory detected: ' + Env.security_blacklist('/' + f)) else: tmp = open(Env.security_blacklist('/' + f), 'r') try: json.loads(tmp.read()) except: database_problems.append( 'security blacklist: invalid json data in ' + Env.security_blacklist('/' + f)) if database_problems: for problem in database_problems: pr.p(ansi.red + 'database: ' + problem + ansi.reset) result_code = 1 else: pr.p(ansi.green + 'all of cati database is ok' + ansi.reset) if not self.is_quiet(): if packages_to_reinstall: pr.p(ansi.blue + 'We suggest re-install this packages:') for pkg in packages_to_reinstall: pr.p('- ' + pkg.data['name']) if not self.has_option('--autofix'): pr.p( 'use --autofix option to re-install them or do this manually' ) pr.p(ansi.reset, end='') else: pr.p(ansi.reset, end='') packages_names = [ pkg.data['name'] for pkg in packages_to_reinstall ] install_cmd = InstallCommand() args = ['cati', 'install', '--reinstall', *packages_names] cmd_str = '' for arg in args: cmd_str += arg + ' ' cmd_str = cmd_str.strip() pr.p(cmd_str) return install_cmd.handle(ArgParser.parse(args)) return result_code
def run(self): """ Run command """ if self.has_option('--abort'): require_root_permission() state_list = BaseTransaction.state_list() if not state_list: pr.p( ansi.green + 'There is not any undoned transaction and everything is ok' + ansi.reset) return 0 user_answer = 'y' if not self.has_option('-y') and not self.has_option('--yes'): pr.p(ansi.yellow + 'WARNING: this process maybe dangerous and ' + str(len(state_list)) + ' transactions will be igonred. are you sure? [y/N] ' + ansi.reset, end='') user_answer = input() if user_answer in ['Y', 'y']: BaseTransaction.finish_all_state() pr.p(ansi.green + 'state was empty successfully' + ansi.reset) else: return elif self.has_option('--complete'): require_root_permission() state_list = BaseTransaction.state_list() if not state_list: pr.p( ansi.green + 'There is not any undoned transaction and everything is ok' + ansi.reset) return 0 BaseTransaction.finish_all_state() # complete transactions for item in state_list: if item['action'] == 'remove': tmp_arguments = [item['pkg'], '-y'] tmp_arguments.insert(0, 'cati') tmp_arguments.insert(1, 'remove') cmd = RemoveCommand() cmd.handle(ArgParser.parse(tmp_arguments)) elif item['action'] == 'install': tmp_arguments = ['install', item['file']] tmp_arguments.insert(0, 'cati') tmp_arguments.insert(1, 'pkg') cmd = PkgCommand() cmd.handle(ArgParser.parse(tmp_arguments)) return else: # show list of undoned transactions state_list = BaseTransaction.state_list() if state_list: StateContentShower.show(state_list) return 1 else: pr.p( ansi.green + 'There is not any undoned transaction and everything is ok' + ansi.reset) return 0
def run(self): """ Run command """ require_root_permission() # check transactions state before run new transactions pr.p('Checking transactions state...') state_list = BaseTransaction.state_list( ) # get list of undoned transactions if state_list: # the list is not empty StateContentShower.show(state_list) return 1 pr.p('Loading packages list...') pr.p('==============================') # load list of packages packages = [] for arg in self.arguments: pkg = Pkg.load_last(arg) if pkg == False: self.message('unknow package "' + arg + '"' + ansi.reset, before=ansi.red) else: if pkg.installed(): packages.append(pkg) else: self.message('package "' + pkg.data['name'] + '" is not installed' + ansi.reset, before=ansi.red) # start removing loaded packages calc = Calculator() calc.remove(packages) # show transactions TransactionShower.show(calc) essential_packages = [] for pkg in calc.to_remove: try: if pkg.data['essential']: essential_packages.append(pkg) except: pass if not self.has_option('--force') and not self.has_option('-f'): for pkg in essential_packages: pr.p( ansi.red + 'Package "' + pkg.data['name'] + '" is a essential package and cannot be remove. use --force|-f option to force remove them' + ansi.reset) if essential_packages: return 1 if not calc.has_any_thing(): return # check user confirmation if not self.has_option('-y') and not self.has_option('--yes'): pr.p('Do you want to continue? [Y/n] ', end='') answer = input() if not (answer == 'y' or answer == 'Y' or answer == ''): pr.p(ansi.yellow + 'Abort.' + ansi.reset) pr.exit(1) # add packages to state BaseTransaction.add_to_state(calc) packages_to_remove_names_and_versions = [ pkg.data['name'] + '@' + pkg.data['version'] for pkg in calc.to_remove ] # run transactions for pkg in calc.to_remove: Remove.run(pkg, { 'removing_package': self.removing_package_event, 'package_remove_finished': self.package_remove_finished_event, 'dir_is_not_empty': self.dir_is_not_empty_event, }, self.has_option('--conffiles'), run_scripts=(not self.has_option('--without-scripts'))) BaseTransaction.pop_state() BaseTransaction.run_any_scripts( ['remove', packages_to_remove_names_and_versions], events={ 'start_run_script': self.start_run_any_script_event, }) BaseTransaction.finish_all_state()
def start_run_any_script_event(self, package_name: str): """ will run when starting running an `any` script """ pr.p('Processing scripts for ' + package_name + '...')
def package_remove_finished_event(self, pkg: Pkg): """ will run as package remover event when package remove process finished """ pr.p(ansi.green + 'OK' + ansi.reset)
def show(calc: Calculator): """ shows transactions from `Calculator` object. Args: calc: `transaction.Calculator.Calculator` object """ if calc.to_remove: pr.p('The following packages will be removed:') for pkg in calc.to_remove: pr.p('- ' + ansi.red + pkg.data['name'] + ansi.reset) to_install = [] to_upgrade = [] to_downgrade = [] to_reinstall = [] for pkg in calc.to_install: if not pkg.installed(): to_install.append(pkg) elif pkg.compare_version(pkg.wanted_version, pkg.installed()) == 1: to_upgrade.append(pkg) elif pkg.compare_version(pkg.wanted_version, pkg.installed()) == -1: to_downgrade.append(pkg) else: to_reinstall.append(pkg) if to_upgrade: pr.p('The following packages will be upgraded:') for pkg in to_upgrade: pr.p('- ' + ansi.yellow + pkg.data['name'] + '(' + pkg.installed() + ' -> ' + pkg.wanted_version + ') ' + pkg.get_file_size_str() + ansi.reset) if to_downgrade: pr.p('The following packages will be downgraded:') for pkg in to_downgrade: pr.p('- ' + ansi.yellow + pkg.data['name'] + '(' + pkg.installed() + ' >> ' + pkg.wanted_version + ') ' + pkg.get_file_size_str() + ansi.reset) if to_reinstall: pr.p('The following packages will be re-installed:') for pkg in to_reinstall: pr.p('- ' + ansi.yellow + pkg.data['name'] + '(' + pkg.wanted_version + ') ' + pkg.get_file_size_str() + ansi.reset) if to_install: pr.p('The following packages will be installed:') for pkg in to_install: pr.p('- ' + ansi.green + pkg.data['name'] + '(' + pkg.wanted_version + ') ' + pkg.get_file_size_str() + ansi.reset) total_download_size = calc.get_total_download_size() if total_download_size > 0: pr.p('Total download size: ' + str(total_download_size))
def run(self): """ Run command """ RootRequired.require_root_permission() pr.p('Loading packages list...') pr.p('========================') loaded_packages = [] for argument in self.arguments: arg_parts = argument.split('=') if len(arg_parts) == 1: # load last version as default pkg = Pkg.load_last(argument) else: # load specify version pkg = Pkg.load_version(arg_parts[0], arg_parts[1]) if pkg == 1: pkg = False elif pkg == 2: self.message('package "' + arg_parts[0] + '" has not version "' + arg_parts[1] + '"' + ansi.reset, before=ansi.red) continue if pkg: loaded_packages.append(pkg) else: self.message('unknow package "' + argument + '"' + ansi.reset, before=ansi.red) # remove local packages from list new_loaded_packages = [] for pkg in loaded_packages: try: file_path = pkg.data['file_path'] new_loaded_packages.append(pkg) except: self.message('package "' + pkg.data['name'] + '" is a local package', is_error=True) loaded_packages = new_loaded_packages if not loaded_packages: return 1 # calculate transactions pr.p('Calculating transactions...') calc = Calculator(with_recommends=self.has_option('--with-recommends')) i = 0 while i < len(loaded_packages): loaded_packages[i].is_manual = True i += 1 try: calc.install(list(reversed(loaded_packages))) except: pr.e(ansi.red + 'ERROR: There is some dependnecy problems.' + ansi.reset) return 1 # handle reinstallable packages i = 0 while i < len(calc.to_install): if calc.to_install[i].installed(): if calc.to_install[i].installed( ) == calc.to_install[i].wanted_version: if not self.has_option('--reinstall'): pr.p( 'Package ' + calc.to_install[i].data['name'] + '=' + calc.to_install[i].wanted_version + ' is currently installed. use --reinstall option to re-install it.' ) if calc.to_install[i].is_manual: try: pr.p( 'Setting it as manual installed package...' ) manual_f = open( Env.installed_lists('/' + pkg.data['name'] + '/manual'), 'w') manual_f.write('') manual_f.close() except: pass calc.to_install.pop(i) i += 1 # check transactions exists if not calc.has_any_thing(): pr.p('Nothing to do.') return 0 # show transaction TransactionShower.show(calc) if not self.has_option('-y') or self.has_option('--yes'): pr.p('Do you want to continue? [Y/n] ', end='') answer = input() if answer == 'y' or answer == 'Y' or answer == '': pass else: pr.p('Abort.') return 1 # start download packages pr.p('Downloading packages...') downloaed_paths = [] for pkg in calc.to_install: download_path = Env.cache_dir('/archives/' + pkg.data['name'] + '-' + pkg.wanted_version + '-' + pkg.data['arch']) if os.path.isfile(download_path): file_sha256 = calc_file_sha256(download_path) file_md5 = calc_file_md5(download_path) valid_sha256 = None valid_md5 = None try: valid_sha256 = pkg.data['file_sha256'] except: valid_sha256 = file_sha256 try: valid_md5 = pkg.data['file_md5'] except: valid_md5 = file_md5 if file_md5 != valid_md5 or file_sha256 != valid_sha256: # file is corrupt and should be download again os.remove(download_path) else: pr.p('Using Cache for ' + pkg.data['name'] + ':' + pkg.data['version'] + ':' + pkg.data['arch'] + '...') downloaed_paths.append(download_path) continue download_cmd = DownloadCommand() i = 0 res = 1 tmp = True while tmp: if i > 5: pr.e(ansi.red + 'Failed to download packages' + ansi.reset) return res pr.p('Downloading ' + pkg.data['name'] + ':' + pkg.data['version'] + ':' + pkg.data['arch'] + '...') res = download_cmd.handle( ArgParser.parse([ 'cati', 'download', '-q', pkg.data['name'] + '=' + pkg.wanted_version, '--output=' + download_path ])) if res == 1 or res == None: tmp = False i += 1 downloaed_paths.append(download_path) pr.p('Download completed.') # check --download-only option if self.has_option('--download-only'): return 0 cati_pkg_cmd_options = [] remove_cmd_options = [] if self.has_option('--keep-conffiles'): cati_pkg_cmd_options.append('--keep-conffiles') if self.has_option('--target'): cati_pkg_cmd_options.append('--target') if self.has_option('--without-scripts'): cati_pkg_cmd_options.append('--without-scripts') remove_cmd_options.append('--without-scripts') # remove packages if calc.to_remove: pr.p('Removing packages...') package_names = [pkg.data['name'] for pkg in calc.to_remove] remove_cmd = RemoveCommand() res = remove_cmd.handle( ArgParser.parse([ 'cati', 'remove', *package_names, '-y', *remove_cmd_options ])) if res != 0 and res != None: pr.e(ansi.red + 'Failed to remove packages' + ansi.reset) return res # install packages pr.p('Installing packages...') pkg_cmd = PkgCommand() res = pkg_cmd.handle( ArgParser.parse([ 'cati', 'pkg', 'install', *downloaed_paths, *cati_pkg_cmd_options ])) if res != 0 and res != None: self.set_manual_installs(calc.to_install) pr.e(ansi.red + 'Failed to install packages' + ansi.reset) return res self.set_manual_installs(calc.to_install) pr.p(ansi.green + 'Done.' + ansi.reset)
def run(self): """ Run command """ if not self.has_option('-q') and not self.has_option('--quiet'): pr.p('Loading packages list...') pr.p('========================') # load list of packages if self.has_option('--installed'): # just list installed packages packages = Pkg.installed_list() elif self.has_option('--installed-manual'): packages = Pkg.installed_list() packages_list = [ tmp_pkg for tmp_pkg in packages['list'] if Pkg.is_installed_manual(tmp_pkg.data['name']) ] packages['list'] = packages_list else: packages = Pkg.all_list() for error in packages['errors']: self.message(error + ansi.reset, True, before=ansi.red) # load filter options wanted_authors = [] if self.has_option('--author'): wanted_authors = self.option_value('--author').strip().split('|') wanted_authors = [author.strip() for author in wanted_authors] wanted_maintainers = [] if self.has_option('--maintainer'): wanted_maintainers = self.option_value( '--maintainer').strip().split('|') wanted_maintainers = [ maintainer.strip() for maintainer in wanted_maintainers ] wanted_categories = [] if self.has_option('--category'): wanted_categories = self.option_value('--category').strip().split( '|') wanted_categories = [ category.strip() for category in wanted_categories ] search_query = self.option_value('--search') if search_query: search_query_words = search_query.strip().split(' ') search_query_words = [word.strip() for word in search_query_words] else: search_query_words = [] for package in packages['list']: # check filters if wanted_authors: try: if not package.data['author'].strip() in wanted_authors: continue except: continue if wanted_maintainers: try: if not package.data['maintainer'].strip( ) in wanted_maintainers: continue except: continue if wanted_categories: try: if not package.data['category'].strip( ) in wanted_categories: continue except: continue if search_query: is_math_with_query = False for word in search_query_words: if word in package.data['name']: is_math_with_query = True try: if search_query in package.data['description']: is_math_with_query = True except: pass if not is_math_with_query: continue if self.has_option('--upgradable'): if package.installed(): if Pkg.compare_version(package.data['version'], package.installed()) != 1: continue else: continue # show item self.show_once(package)
def run(self): """ Run command """ RootRequired.require_root_permission() if not self.is_quiet(): pr.p('Loading repositories list...') repos = Repo.get_list() ReposListErrorShower.show(repos) if not self.is_quiet(): pr.p('Prepairing to update repos...') orig_repos = [] for repo in repos: if repo.successful_loaded: if repo.test(): orig_repos.append(repo) else: pr.e(ansi.red + 'Cannot make connection to repo "' + repo.full_string + '"' + ansi.reset) if not self.is_quiet(): pr.p('Updating repositories...') pr.p('=============================') # downloaded repos data files paths downloaded_paths = [] # update repos for repo in list(reversed(orig_repos)): if not self.is_quiet(): pr.p('Fetching ' + repo.name + ' (' + repo.url + ') data...') data = repo.get_data(download_event=self.download_event) if type(data) == int: pr.e(ansi.red + 'Cannot update ' + repo.name + ' (' + repo.url + '): error code ' + str(data) + ansi.reset) elif isinstance(data, Exception): pr.e(ansi.red + 'Cannot update ' + repo.name + ' (' + repo.url + '): ' + str(data) + ansi.reset) else: # validate data try: tmp = json.loads(data) # save data in an file path = Env.cache_dir('/' + repo.name + '-' + str(time.time()) + str(random.random())) + '.json' f = open(path, 'w') f.write(data) f.close() downloaded_paths.append(path) except: pr.e(ansi.red + 'Cannot update ' + repo.name + ' (' + repo.url + '): invalid json data recived' + ansi.reset) if not self.is_quiet(): pr.p('Updating packages list...') # load downloaded data packages = [] for path in downloaded_paths: f = open(path, 'r') data = f.read().strip() f.close() items = json.loads(data) for item in items: if PackageJsonValidator.validate(item): packages.append(item) else: pass for pkg in packages: if PackageJsonValidator.validate(pkg): if self.is_verbose(): pr.p('adding ' + pkg['name'] + ':' + pkg['version'] + ':' + pkg['arch'] + '...') # write package on list if not os.path.isdir(Env.packages_lists('/' + pkg['name'])): os.mkdir(Env.packages_lists('/' + pkg['name'])) try: f = open( Env.packages_lists('/' + pkg['name'] + '/' + pkg['version'] + '-' + pkg['arch']), 'w') f.write(json.dumps(pkg)) f.close() except: pr.e(ansi.red + 'error while adding ' + pkg['name'] + ':' + pkg['version'] + ':' + pkg['arch'] + ansi.reset) else: if self.is_verbose(): pr.p(ansi.yellow + 'invalid json data in an item. ignored...' + ansi.reset) if self.is_quiet(): pr.p('Finishing update...') ListUpdater.update_indexes({ 'cannot_read_file': self.empty_method, 'invalid_json_data': self.empty_method, }) pr.p(ansi.green + 'Done.' + ansi.reset)