def handle_install_reverse_depends(self): """ Adds installable packages reverse depends to install list """ new_to_remove = [] i = 0 while i < len(self.to_install): reverse_depends = self.to_install[i].get_reverse_depends() for dep in reverse_depends: if dep.installed(): dep = Pkg.load_version(dep.data['name'], dep.installed()) for tmp_dep in dep.get_depends(): result = Pkg.check_state( tmp_dep, virtual={ 'install': [[ self.to_install[i].data['name'], self.to_install[i].data['version'] ]], }) if not result: a = 0 added = False while a < len(self.to_remove): if self.to_remove[a].data['name'] == dep.data[ 'name']: added = True a += 1 if not added: new_to_remove.append(dep) i += 1 if new_to_remove: self.remove(new_to_remove)
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 find_unused_packages(self): """ finds unused packages """ all_packages = Pkg.all_list()['list'] for pkg in all_packages: try: if Pkg.is_installed(pkg.data['name']): if not Pkg.is_installed_manual(pkg.data['name']): has_any_reverse_depends = False reverse_depends = Pkg.load_version( pkg.data['name'], Pkg.installed_version( pkg.data['name'])).get_reverse_depends() for rdep in reverse_depends: if rdep.installed(): rdep_is_in_unused_packages = False for upkg in self.unused_packages: if upkg.data['name'] == rdep.data['name']: rdep_is_in_unused_packages = True if not rdep_is_in_unused_packages: has_any_reverse_depends = True if not has_any_reverse_depends: self.unused_packages.append(pkg) except: pass
def run_script(self, script_name: str, script_path=None): """ runs an script in the package (only install scripts) Args: script_name (str): name of that script you want to run script_path (str, None): you can change the default path of script file with this argument Raises: dotcati.exceptions.PackageScriptError: when script returns non-zero exit code (exit code will put in `error_code` attribute of exception object) """ if script_path == None: script_path = self.extracted_package_dir + '/scripts/' + script_name if os.path.isfile(script_path): # script exists, run script os.system('chmod +x "' + script_path + '"') # run script and pass old version of package (if currently installed) old_version = '' try: old_version = self.old_version except: if Pkg.is_installed(self.pkg.data['name']): self.old_version = '"' + Pkg.installed_version(self.pkg.data['name']) + '"' old_version = self.old_version result = os.system(script_path + ' ' + old_version) if result != 0: tmp = PackageScriptError("script " + script_name + ' returned non-zero code ' + str(result)) tmp.error_code = result raise tmp
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 test """ repo_path = os.getcwd() + '/repository/test-channels' self.assert_equals(self.run_command('repo', ['--scan', repo_path]), 0) repo = 'file://' + os.getcwd( ) + '/repository/test-channels arch=all pkg=cati' self.assert_equals(self.run_command('repo', ['--add', repo]), 0) self.assert_equals(self.run_command('update'), 0) pkg = Pkg.load_last('channelpkg') versions = pkg.get_versions_list() self.assert_equals(len(versions), 10) self.refresh_env() repo = 'file://' + os.getcwd( ) + '/repository/test-channels arch=all pkg=cati channel=dev' self.assert_equals(self.run_command('repo', ['--add', repo]), 0) self.assert_equals(self.run_command('update'), 0) pkg = Pkg.load_last('channelpkg') versions = pkg.get_versions_list() self.assert_equals(len(versions), 2) self.refresh_env() repo = 'file://' + os.getcwd( ) + '/repository/test-channels arch=all pkg=cati channel=dev,alpha' self.assert_equals(self.run_command('repo', ['--add', repo]), 0) self.assert_equals(self.run_command('update'), 0) pkg = Pkg.load_last('channelpkg') versions = pkg.get_versions_list() self.assert_equals(len(versions), 5) # test upgrade self.assert_equals(self.run_command('install', ['-y', 'channelpkg']), 0) pkg = Pkg.load_last('channelpkg') self.assert_equals(pkg.installed(), '1.0-alpha2') repo = 'file://' + os.getcwd( ) + '/repository/test-channels arch=all pkg=cati channel=release' self.assert_equals(self.run_command('repo', ['--add', repo]), 0) self.assert_equals(self.run_command('update'), 0) self.assert_equals(self.run_command('upgrade', ['-y']), 0) pkg = Pkg.load_last('channelpkg') self.assert_equals(pkg.installed(), '1.0')
def refresh_lists(self): """ Refresh packages list and sync them with depends and conflicts """ # sync versions i = 0 while i < len(self.to_remove): self.to_remove[i] = Pkg.load_version( self.to_remove[i].data['name'], self.to_remove[i].installed()) i += 1 i = 0 while i < len(self.to_install): wv = self.to_install[i].wanted_version im = self.to_install[i].is_manual self.to_install[i] = Pkg.load_version( self.to_install[i].data['name'], self.to_install[i].wanted_version) self.to_install[i].wanted_version = wv self.to_install[i].is_manual = im i += 1 # remove repeated lists in to_remove list a = 0 while a < len(self.to_remove): b = 0 while b < len(self.to_remove): if a != b: if self.to_remove[a].data['name'] == self.to_remove[ b].data['name']: self.to_remove.pop(b) a -= 1 b -= 1 b += 1 a += 1 # sync to_remove list new_to_remove = [] for item in self.to_remove: # load reverse dependnecy of current package and add them to list reverse_depends = item.get_reverse_depends() for rd in reverse_depends: if rd.installed(): if not rd.data['name'] in [ tmp.data['name'] for tmp in self.to_remove ]: new_to_remove.append(rd) if new_to_remove: self.remove(new_to_remove) self.handle_install_depends() self.handle_install_conflicts()
def run(self): """ Run test """ self.assert_equals(self.run_command('update'), 0) self.assert_equals( self.run_command('repo', ['--scan', 'repository/test-repository']), 0) f = open(self.env() + '/etc/cati/repos.list', 'w') f.write(''' file://''' + os.getcwd() + '''/repository/test-repository name=main arch=i386 pkg=cati ''') f.close() self.assert_equals(len(Pkg.all_list()['list']), 0) self.assert_equals(self.run_command('update'), 0) try: pkg_count = len(Pkg.all_list()['list']) self.assert_true(pkg_count >= 9 and pkg_count <= 13) except: print('Packages count:', pkg_count) raise f = open(self.env() + '/etc/cati/repos.list.d/repo-b', 'w') f.write(''' file://''' + os.getcwd() + '''/repository/test-repository name=main-2 arch=all pkg=cati ''') f.close() try: pkg_count = len(Pkg.all_list()['list']) self.assert_true(pkg_count >= 9 and pkg_count <= 13) except: print('Packages count:', pkg_count) raise self.assert_equals(self.run_command('update'), 0) try: pkg_count = len(Pkg.all_list()['list']) self.assert_true(pkg_count >= 15 and pkg_count <= 19) except: print('Packages count:', pkg_count) raise
def read(self): """ Load package information on object. This method has not arg or output, just loads some information of package to this object. Raises: Exception: will raise normal Exception when package json data is invalid (validated by dotcati.PackageJsonValidator.validate()) """ self.data = self.info() if not PackageJsonValidator.validate(self.data): raise # try to compare version for version validation Pkg.compare_version(self.data['version'], '0.0.0') self.data['version'] = self.data['version'].strip()
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 test """ self.assert_equals( self.run_command( 'pkg', ['install', 'repository/test-repository/testpkgc-2.0.cati']), 0) state_f = open(Env.state_file(), 'w') state_f.write(f'install%testpackage1%1.0%amd64\nremove%anotherpackage') state_f.close() self.assert_equals(self.run_command('remove', [ 'testpkgc', '-y', ]), 1) self.assert_equals( self.run_command( 'pkg', ['install', 'repository/test-repository/testpkgc-2.0.cati']), 1) # tests for cli `state` command self.assert_equals(self.run_command('state'), 1) self.assert_equals(self.run_command('state', ['--abort', '-y']), 0) self.assert_equals(self.run_command('state'), 0) self.refresh_env() self.assert_equals( self.run_command( 'pkg', ['install', 'repository/test-repository/testpkgc-2.0.cati']), 0) self.assert_true(Pkg.is_installed('testpkgc')) state_f = open(Env.state_file(), 'w') state_f.write(f'remove%testpkgc') state_f.close() self.assert_equals(self.run_command('state'), 1) self.assert_equals(self.run_command('state', ['--complete']), 0) self.assert_equals(self.run_command('state'), 0) self.assert_true(not Pkg.is_installed('testpkgc'))
def run(self): """ Run test """ self.assert_equals( self.run_command('pkg', [ 'install', 'repository/test-repository/simple-test-package.cati' ]), 0) self.assert_true(os.path.isfile(self.env('/usr/bin/cati-testpkga'))) self.assert_equals( self.run_command('pkg', [ 'install', 'repository/test-repository/simple-test-package.cati' ]), 0) self.assert_true(os.path.isfile(self.env('/usr/bin/cati-testpkga'))) pkg = Pkg.load_from_index( json.loads( open(Env.packages_lists('/testpkga/index'), 'r').read()), 'testpkga') self.assert_equals(pkg.installed(), '1.0') self.refresh_env() self.assert_equals( self.run_command('pkg', [ 'install', 'repository/test-repository/testpkg-with-file-conflict-a.cati', ]), 0) self.assert_true( os.path.isfile(self.env() + '/etc/testpkg-with-file-conflict/test.txt')) self.refresh_env() os.mkdir(self.env() + '/app') self.assert_equals( self.run_command('pkg', [ 'install', 'repository/test-repository/testpkg-with-file-conflict-a.cati', '--target=/app' ]), 0) self.assert_true(not os.path.isfile( self.env() + '/etc/testpkg-with-file-conflict/test.txt')) self.assert_true( os.path.isfile(self.env() + '/app/etc/testpkg-with-file-conflict/test.txt'))
def check_dep_and_conf(self, pkg: BaseArchive): """ Checks package dependencies and conflicts. Args: pkg: (BaseArchive) the package archive object Raises: DependencyError: when a dependency is not installed (dependency will put in exception message) ConflictError: when a conflict is installed (conflict will put in exception message) """ # load package dependencies try: depends = pkg.data['depends'] except: depends = [] # load package conflicts try: conflicts = pkg.data['conflicts'] except: conflicts = [] # load package reverse cconflicts (packages has conflict to this package) reverse_conflicts = pkg.get_reverse_conflicts() for dep in depends: if not Pkg.check_state(dep): raise DependencyError(dep) for conflict in conflicts: if Pkg.check_state(conflict): raise ConflictError(conflict) # check reverse conflicts if reverse_conflicts: raise ConflictError('reverse conflict with ' + reverse_conflicts[0].data['name'] + ': ' + reverse_conflicts[0].conflict_error)
def handle_install_conflicts(self): """ Adds installable packages conflicts to install list """ new_to_remove = [] i = 0 while i < len(self.to_install): conflicts = self.to_install[i].get_conflicts() for conflict in conflicts: if Pkg.check_state(conflict): # find package conflict try: self.to_install[i].conflict_get_next[conflict] except: try: self.to_install[i].conflict_get_next[conflict] = 0 except: self.to_install[i].conflict_get_next = {} self.to_install[i].conflict_get_next[conflict] = 0 pkg = Pkg.check_state(conflict, get_true_pkg=True, get_true_pkg_next=self.to_install[i]. conflict_get_next[conflict]) self.to_install[i].conflict_get_next[conflict] += 1 a = 0 added = False if type(pkg) == list: while a < len(self.to_remove): if self.to_remove[a].data['name'] == pkg[0]: added = True a += 1 if not added: new_to_remove.append(Pkg.load_last(pkg[0])) i += 1 if new_to_remove: self.remove(new_to_remove) self.handle_install_reverse_conflicts()
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 """ 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 """ 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 test """ repo1 = "file://" + os.getcwd( ) + '/repository name=test arch=all pkg=cati' repo2 = "file://" + os.getcwd( ) + '/repository name=test arch=i386 pkg=cati' self.assert_equals( self.run_command('repo', ['--scan', os.getcwd() + '/repository']), 0) self.assert_equals(self.run_command('repo', ['--add', repo1]), 0) self.assert_equals(self.run_command('repo', ['--add', repo2]), 0) self.assert_equals(self.run_command('update'), 0) self.assert_equals(self.run_command('install', ['testpkg10', '-y']), 0) self.assert_true(Pkg.is_installed('testpkg10')) self.assert_true(Pkg.is_installed('testpkg11')) self.assert_equals(self.run_command('install', ['testpkgb', '-y']), 0) self.assert_true(Pkg.is_installed('testpkgb')) self.assert_true(Pkg.is_installed('testpkgc')) self.assert_true(not Pkg.is_installed_manual('testpkgc')) self.assert_equals(self.run_command('install', ['testpkgz', '-y']), 0) self.assert_true(not Pkg.is_installed('testpkgb')) self.assert_true(not Pkg.is_installed('testpkgc')) self.assert_true(Pkg.is_installed('testpkgz')) self.assert_equals(self.run_command('install', ['testpkgb', '-y']), 0) self.assert_true(Pkg.is_installed('testpkgb')) self.assert_true(Pkg.is_installed('testpkgc')) self.assert_true(not Pkg.is_installed('testpkgz')) self.assert_equals( self.run_command('remove', ['testpkgb', 'testpkgc', '-y']), 0) # test upgrade self.assert_equals(self.run_command('install', ['testpkgc=1.0', '-y']), 0) testpkgc = Pkg.load_last('testpkgc') self.assert_equals(testpkgc.installed(), '1.0') self.assert_equals(self.run_command('upgrade', ['-y']), 0) testpkgc = Pkg.load_last('testpkgc') self.assert_equals(testpkgc.installed(), '2.0') # test recommends self.refresh_env() self.assert_equals( self.run_command('repo', [ '--add', 'file://' + os.getcwd() + '/repository/test-repository arch=all,i386 name=test pkg=cati' ]), 0) self.assert_equals(self.run_command('update'), 0) self.assert_equals(self.run_command('install', ['testpkgr', '-y']), 0) self.assert_true(Pkg.is_installed('testpkgr')) self.assert_true(Pkg.is_installed('testpkgc')) self.assert_true(not Pkg.is_installed('testpkg11')) self.refresh_env() self.assert_equals( self.run_command('repo', [ '--add', 'file://' + os.getcwd() + '/repository/test-repository arch=all,i386 name=test pkg=cati' ]), 0) self.assert_equals(self.run_command('update'), 0) self.assert_equals( self.run_command('install', ['testpkgr', '-y', '--with-recommends']), 0) self.assert_true(Pkg.is_installed('testpkgr')) self.assert_true(Pkg.is_installed('testpkgc')) self.assert_true(Pkg.is_installed('testpkg11'))
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 install(self, pkg: BaseArchive, index_updater_events: dict, installer_events: dict, is_manual=True, run_scripts=True, target_path='', keep_conffiles=False, check_security_blacklist=True): """ Install .cati package Args: pkg (BaseArchive): the package archive object index_updater_events (dict): events will be passed to `dotcati.ListUpdater.update_indexes()` installer_events (dict): The events - package_currently_install: gets the current installed version - package_new_installs: gets package archive - package_installed: will call after package installation - dep_and_conflict_error: will run when there is depends or conflict error - arch_error: will run when package arch is not sync with sys arch is_manual (bool): installed package as manual or not (default is True means manual) run_scripts (bool): run package install scripts or not (default is True) target_path (str): where is the target path for installed files (will pass to `self.copy_files()`) keep_conffiles (bool): stil keep config files if changed (default is True) check_security_blacklist (bool): check package is in security blacklist or not """ self.conffiles = pkg.get_conffiles() self.pkg = pkg self.keep_conffiles = keep_conffiles self.uncopied_conffiles = {} # check package is in security blacklist if check_security_blacklist: self.check_security_blacklist(pkg) # check package architecture if not pkg.data['arch'] in SysArch.allowed_archs(): return installer_events['arch_error'](pkg) # check package dependencies and conflicts try: self.check_dep_and_conf(pkg) except DependencyError as ex: return installer_events['dep_and_conflict_error'](pkg, ex) except ConflictError as ex: return installer_events['dep_and_conflict_error'](pkg, ex) # load old conffiles self.old_conffiles = [] try: f = open(Env.installed_lists('/' + pkg.data['name'] + '/conffiles'), 'r') content = f.read() f.close() tmp = content.strip().split('\n') self.old_conffiles = [item.strip().split('@') for item in tmp] except: pass # add package data to lists if not os.path.isdir(Env.packages_lists('/' + pkg.data['name'])): os.mkdir(Env.packages_lists('/' + pkg.data['name'])) lists_path = Env.packages_lists('/' + pkg.data['name'] + '/' + pkg.data['version'] + '-' + pkg.data['arch']) try: lists_f = open(lists_path, 'r') old_repo = json.loads(lists_f.read())['repo'] lists_f.close() except: old_repo = 'Local' try: lists_f = open(lists_path, 'r') old_file_path = json.loads(lists_f.read())['file_path'] lists_f.close() except: old_file_path = False try: lists_f = open(lists_path, 'r') old_file_sha256 = json.loads(lists_f.read())['file_sha256'] lists_f.close() except: old_file_sha256 = False try: lists_f = open(lists_path, 'r') old_file_md5 = json.loads(lists_f.read())['file_md5'] lists_f.close() except: old_file_md5 = False lists_f = open(lists_path, 'w') pkg.data['repo'] = old_repo if old_file_path != False: pkg.data['file_path'] = old_file_path tmp_pkg_data = pkg.data if old_file_md5: tmp_pkg_data['file_md5'] = old_file_md5 if old_file_sha256: tmp_pkg_data['file_sha256'] = old_file_sha256 tmp_pkg_data['files'] = ['/' + member[6:] for member in pkg.members() if member[:6] == 'files/'] lists_f.write(json.dumps(tmp_pkg_data)) lists_f.close() ListUpdater.update_indexes(index_updater_events) # extract package in a temp place temp_dir = Temp.make_dir() os.rmdir(temp_dir) try: pkg.extractall(temp_dir) except IsADirectoryError: pass self.extracted_package_dir = temp_dir # install package if Pkg.is_installed(pkg.data['name']): installer_events['package_currently_installed'](pkg, Pkg.installed_version(pkg.data['name'])) else: installer_events['package_new_installs'](pkg) if run_scripts: self.run_script('ins-before') copied_files = self.copy_files(pkg, installer_events['directory_not_empty'], target_path) # set install configuration if not os.path.isdir(Env.installed_lists('/' + pkg.data['name'])): os.mkdir(Env.installed_lists('/' + pkg.data['name'])) f_ver = open(Env.installed_lists('/' + pkg.data['name'] + '/ver'), 'w') f_ver.write(pkg.data['version']) # write installed version f_ver.close() # write copied files list f_files = open(Env.installed_lists('/' + pkg.data['name'] + '/files'), 'w') copied_files_str = '' for copied_file in copied_files: copied_files_str += copied_file + '\n' f_files.write(copied_files_str.strip()) # write copied files f_files.close() # write conffiles list f_conffiles = open(Env.installed_lists('/' + pkg.data['name'] + '/conffiles'), 'w') copied_conffiles_str = '' for copied_conffile in copied_files: if copied_conffile.split(':')[0] == 'cf': try: conffile_hash = self.uncopied_conffiles[copied_conffile.split(':', 1)[-1]] except: conffile_hash = calc_file_sha256(Env.base_path(copied_conffile.split(':', 1)[-1])) copied_conffiles_str += conffile_hash + '@' + copied_conffile.split(':', 1)[-1] + '\n' f_conffiles.write(copied_conffiles_str.strip()) # write copied conffiles f_conffiles.close() # copy `any` script if os.path.isfile(self.extracted_package_dir + '/scripts/any'): os.system('cp "' + self.extracted_package_dir + '/scripts/any' + '" "' + Env.any_scripts('/' + pkg.data['name']) + '"') # save static files list static_files_list = pkg.get_static_files() f_static_files = open(Env.installed_lists('/' + pkg.data['name'] + '/staticfiles'), 'w') static_files_str = '' for copied_file in copied_files: copied_file_path = copied_file.split(':', 1)[1] if copied_file_path in static_files_list: if os.path.isfile(Env.base_path('/' + copied_file_path)): # calculate file sha256 sum copied_file_sha256 = calc_file_sha256(Env.base_path('/' + copied_file_path)) # add file to list static_files_str += copied_file_sha256 + '@' + copied_file_path + '\n' f_static_files.write(static_files_str.strip()) # write copied files f_static_files.close() f_installed_at = open(Env.installed_lists('/' + pkg.data['name'] + '/installed_at'), 'w') f_installed_at.write(str(time.time())) # write time (installed at) f_installed_at.close() if is_manual: f_manual = open(Env.installed_lists('/' + pkg.data['name'] + '/manual'), 'w') f_manual.write('') f_manual.close() if run_scripts: self.run_script('ins-after') # copy remove scripts if os.path.isfile(self.extracted_package_dir + '/scripts/rm-before'): os.system( 'cp "' + self.extracted_package_dir + '/scripts/rm-before' + '" "' + Env.installed_lists('/' + pkg.data['name'] + '/rm-before') + '"' ) if os.path.isfile(self.extracted_package_dir + '/scripts/rm-after'): os.system( 'cp "' + self.extracted_package_dir + '/scripts/rm-after' + '" "' + Env.installed_lists('/' + pkg.data['name'] + '/rm-after') + '"' ) # pop package from state BaseTransaction.pop_state() # call package installed event installer_events['package_installed'](pkg)
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 handle_install_depends(self): """ Adds installable packages depends to install list """ new_to_install = [] i = 0 while i < len(self.to_install): depends = self.to_install[i].get_depends() if self.with_recommends: depends = [*depends, *self.to_install[i].get_recommends()] for depend in depends: if not Pkg.check_state(depend) and depend.strip()[0] != '@': # find package depend try: self.to_install[i].depend_get_next[depend] except: try: self.to_install[i].depend_get_next[depend] = 0 except: self.to_install[i].depend_get_next = {} self.to_install[i].depend_get_next[depend] = 0 pkg = Pkg.check_state( depend, get_false_pkg=True, get_false_pkg_next=self.to_install[i]. depend_get_next[depend]) self.to_install[i].depend_get_next[depend] += 1 if len(pkg) == 1: a = 0 added = False while a < len(self.to_install): if self.to_install[a].data['name'] == pkg[0]: added = True a += 1 if not added: new_to_install.append(Pkg.load_last(pkg[0])) elif len(pkg) == 3: a = 0 added = False while a < len(self.to_install): if self.to_install[a].data['name'] == pkg[0]: wanted_version = pkg[2] installed_version = self.to_install[ a].wanted_version if pkg[1] == '=': if Pkg.compare_version( installed_version, wanted_version) == 0: added = True elif pkg[1] == '>=': if Pkg.compare_version( installed_version, wanted_version) >= 0: added = True elif pkg[1] == '<=': if Pkg.compare_version( installed_version, wanted_version) <= 0: added = True elif pkg[1] == '>': if Pkg.compare_version( installed_version, wanted_version) == 1: added = True elif pkg[1] == '<': if Pkg.compare_version( installed_version, wanted_version) == -1: added = True a += 1 if not added: pkg_obj = None if pkg[1] == '=': pkg_obj = Pkg.load_version(pkg[0], pkg[2]) elif pkg[1] == '>=' or pkg[1] == '>': pkg_obj = Pkg.load_last(pkg[0]) elif pkg[1] == '<=': pkg_obj = Pkg.load_version(pkg[0], pkg[2]) elif pkg[1] == '<': pkg_obj = Pkg.load_last(pkg[0]) versions = pkg_obj.get_versions_list() x = 0 while x < len(versions): if Pkg.compare_version( versions[x][0], pkg[0]) >= 0: versions.pop(x) x += 1 versions = [v[0] for v in versions] wanted_ver = pkg.get_last_version(versions) pkg_obj = Pkg.load_version(pkg[0], wanted_ver) new_to_install.append(pkg_obj) i += 1 if new_to_install: self.install(new_to_install) self.handle_install_reverse_depends()
def run(self): """ Run test """ self.assert_equals(self.run_command('pkg', [ 'install', 'repository/test-repository/testpkg10.cati' ]), 1) self.assert_equals(self.run_command('pkg', [ 'install', 'repository/test-repository/testpkg11.cati' ]), 0) self.assert_equals(self.run_command('pkg', [ 'install', 'repository/test-repository/testpkg10.cati' ]), 0) self.assert_true(Pkg.is_installed('testpkg10')) self.assert_true(Pkg.is_installed('testpkg11')) self.assert_equals(self.run_command('remove', [ 'testpkg10', '-y' ]), 0) self.assert_true(not Pkg.is_installed('testpkg10')) self.assert_true(Pkg.is_installed('testpkg11')) self.assert_equals(self.run_command('pkg', [ 'install', 'repository/test-repository/testpkg10.cati' ]), 0) self.assert_true(Pkg.is_installed('testpkg10')) self.assert_true(Pkg.is_installed('testpkg11')) self.assert_equals(self.run_command('remove', [ 'testpkg11', '-y' ]), 0) self.assert_true(not Pkg.is_installed('testpkg10')) self.assert_true(not Pkg.is_installed('testpkg11')) self.refresh_env() self.assert_equals(self.run_command('pkg', [ 'install', 'repository/test-repository/essential-package.cati' ]), 0) self.assert_true(Pkg.is_installed('essential-package')) self.assert_equals(self.run_command('remove', [ 'essential-package', '-y' ]), 1) self.assert_true(Pkg.is_installed('essential-package')) self.assert_equals(self.run_command('remove', [ 'essential-package', '-y', '--force' ]), 0) self.assert_true(not Pkg.is_installed('essential-package'))
def copy_files(self, pkg: BaseArchive, directory_not_empty_event, target_path='') -> list: """ Copy package files on system Args: pkg (BaseArchive): the package archive object directory_not_empty_event (callable): the function will be run when we want to delete old direcotry of package and that is not empty. target_path (str): target path prefix of copied files location. default is `/` means copies files on the root directory. you can change it. Returns: list[str]: list of copied files """ # load package old files list old_files = [] if os.path.isfile(Env.installed_lists('/' + pkg.data['name'] + '/files')): try: f = open(Env.installed_lists('/' + pkg.data['name'] + '/files'), 'r') for line in f.read().strip().split('\n'): if line != '': old_files.append(line.strip()) except: pass old_files = list(reversed(old_files)) # load unremoved conffiles list unremoved_conffiles_f = open(Env.unremoved_conffiles(), 'r') unremoved_conffiles = unremoved_conffiles_f.read().strip().split('\n') unremoved_conffiles_f.close() temp_dir = self.extracted_package_dir # load files list from `files` directory of package self.loaded_files = [] self.load_files(temp_dir + '/files', temp_dir + '/files') self.loaded_files = [[target_path + f[0], f[1]] for f in self.loaded_files] # check file conflicts all_installed_files = Pkg.get_all_installed_files_list() for lf in self.loaded_files: if not os.path.isdir(lf[1]): for insf in all_installed_files: if insf[0].split(':', 1)[0] != pkg.data['name']: if lf[0] == insf[2]: insf_pkg = Pkg.load_last(insf[0]) if insf_pkg: insf[0] = insf[0] + ':' + insf_pkg.installed() # check package is in `replaces` list do_raise_error = True replaces_list = pkg.get_replaces() for rep in replaces_list: if Pkg.check_state(rep): tmp_parts = rep.split(' ') tmp_parts = tmp_parts[0].split('>') tmp_parts = tmp_parts[0].split('<') tmp_parts = tmp_parts[0].split('=') tmp_parts = tmp_parts[0] if tmp_parts == insf[0].split(':', 1)[0]: do_raise_error = False if do_raise_error: raise FileConflictError( 'package ' + pkg.data['name'] + ':' + pkg.data['version'] + ' and ' + insf[0] + ' both has file "' + lf[0] + '"' ) # copy loaded files self.copied_files = [] for f in self.loaded_files: if os.path.exists(Env.base_path(f[0])): if os.path.isfile(Env.base_path(f[0])): if ('f:' + f[0]) in old_files or ('cf:' + f[0]) in old_files: self.copy_once_file(f) try: old_files.pop(old_files.index(('f:' + f[0]))) except: pass else: if f[0] in unremoved_conffiles: self.copy_once_file(f) unremoved_conffiles.pop(unremoved_conffiles.index(f[0])) else: self.copy_once_file(f) else: if ('d:' + f[0]) in old_files or ('cd:' + f[0]) in old_files: if ('cd:' + f[0]) in old_files: self.copied_files.append('cd:' + f[0]) old_files.pop(old_files.index(('cd:' + f[0]))) else: self.copied_files.append('d:' + f[0]) old_files.pop(old_files.index(('d:' + f[0]))) else: if f[0] in unremoved_conffiles: self.copied_files.append('d:' + f[0]) unremoved_conffiles.pop(unremoved_conffiles.index(f[0])) else: self.copy_once_file(f) # delete not wanted old files for item in old_files: parts = item.strip().split(':', 1) if parts[0] == 'cf' or parts[0] == 'cd': pass else: if os.path.isfile(parts[1]): os.remove(parts[1]) else: try: os.rmdir(parts[1]) except: # directory is not emptyr directory_not_empty_event(pkg, parts[1]) # write new unremoved conffiles list unremoved_conffiles_f = open(Env.unremoved_conffiles(), 'w') new_content = '' for item in unremoved_conffiles: new_content += item + '\n' unremoved_conffiles_f.write(new_content) unremoved_conffiles_f.close() return self.copied_files
def show(data: dict): """ shows package information from data dictonary. Args: data: (dict) package data dictonary """ output = '' output += 'Name: ' + ansi.green + data['name'] + ansi.reset + '\n' output += 'Version: ' + ansi.blue + data['version'] + ansi.reset + '\n' output += 'Arch: ' + ansi.yellow + data['arch'] + ansi.reset + '\n' try: author = data['author'] output += 'Author: ' + ansi.header + author + ansi.reset + '\n' except: pass try: maintainer = data['maintainer'] output += 'Maintainer: ' + ansi.cyan + maintainer + ansi.reset + '\n' except: pass try: changed_by = data['changed-by'] output += 'Changed-By: ' + changed_by + '\n' except: pass try: uploaders = data['uploaders'] except: uploaders = [] if uploaders: output += 'Uploaders: ' for uploader in uploaders: output += uploader + ', ' output = output[:len(output) - 2] output += '\n' try: channel = data['channel'] output += 'Channel: ' + ansi.red + channel + ansi.reset + '\n' except: pass try: homepage = data['homepage'] output += 'Homepage: ' + ansi.blue + homepage + ansi.reset + '\n' except: pass try: category = data['category'] if category: output += 'Categories: ' i = 0 while i < len(category): output += ansi.bold + category[i] + ansi.reset if i < len(category) - 1: output += ', ' i += 1 output += '\n' except: pass try: description = data['description'] output += 'Description: ' + description + '\n' except: pass try: changes = data['changes'] output += 'Changes: ' + description + '\n' except: pass try: date = data['date'] output += 'Last-Update-Date: ' + date + '\n' except: pass try: urgency = data['urgency'] output += 'Update-Level: ' + urgency + '\n' except: pass try: essential = data['essential'] if essential: essential = 'Yes' else: essential = 'No' output += 'Essential: ' + essential + '\n' except: pass try: file_size = Pkg.get_download_size_str(data['file_size']) output += 'Download-Size: ' + str(file_size) + '\n' except: pass try: installed_size = Pkg.get_download_size_str(data['installed-size']) output += 'Installed-Size: ' + str(installed_size) + '\n' except: pass try: repo = data['repo'] output += 'Repository: ' + repo + '\n' except: pass try: depends = data['depends'] except: depends = [] if depends: output += 'Depends: ' for dep in depends: output += ansi.bold + dep + ansi.reset + ', ' output = output[:len(output) - 2] output += '\n' try: recommends = data['recommends'] except: recommends = [] if recommends: output += 'Recommends: ' for rec in recommends: output += ansi.bold + rec + ansi.reset + ', ' output = output[:len(output) - 2] output += '\n' try: conflicts = data['conflicts'] except: conflicts = [] if conflicts: output += 'Conflicts: ' for conflict in conflicts: output += ansi.bold + conflict + ansi.reset + ', ' output = output[:len(output) - 2] output += '\n' try: suggests = data['suggests'] except: suggests = [] if suggests: output += 'Suggests: ' for suggest in suggests: output += ansi.bold + suggest + ansi.reset + ', ' output = output[:len(output) - 2] output += '\n' try: enhances = data['enhances'] except: enhances = [] if enhances: output += 'Enhances: ' for enhance in enhances: output += ansi.bold + enhance + ansi.reset + ', ' output = output[:len(output) - 2] output += '\n' try: provides = data['provides'] except: provides = [] if provides: output += 'Provides: ' for provide in provides: output += ansi.bold + provide + ansi.reset + ', ' output = output[:len(output) - 2] output += '\n' if Pkg.is_installed(data['name']): installed_version = Pkg.installed_version(data['name']) if Pkg.is_installed_manual(data['name']): output += 'Installed-Manual: ' + installed_version + '\n' else: output += 'Installed: ' + installed_version + '\n' # show user defined fields for k in data: if k[0] == 'x' or k[0] == 'X': # that fields start with `x` character are user defined fields output += '\n' + k + ': ' + data[k] if output[-1] == '\n': output = output[:len(output) - 1] pr.p(output.strip())
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 run(self): """ Run test """ self.assert_equals(self.run_command('pkg', [ 'install', 'repository/test-repository/testpkgc-1.0.cati' ]), 0) self.assert_equals(self.run_command('pkg', [ 'install', 'repository/test-repository/testpkgc-2.0.cati' ]), 0) self.assert_equals(self.run_command('forget', [ 'testpkgc' ]), 1) self.assert_equals(self.run_command('remove', [ 'testpkgc', '-y' ]), 0) self.assert_equals(self.run_command('forget', [ 'testpkgc' ]), 0) self.assert_true(not Pkg.load_last('testpkgc')) self.assert_equals(self.run_command('pkg', [ 'install', 'repository/test-repository/testpkgc-1.0.cati' ]), 0) self.assert_equals(self.run_command('pkg', [ 'install', 'repository/test-repository/testpkgc-2.0.cati' ]), 0) self.assert_equals(self.run_command('forget', [ 'testpkgc=1.0' ]), 0) self.assert_equals(self.run_command('forget', [ 'testpkgc=2.0' ]), 1) self.refresh_env() self.assert_equals(self.run_command('pkg', [ 'install', 'repository/test-repository/testpkgc-2.0.cati' ]), 0) self.assert_equals(self.run_command('pkg', [ 'install', 'repository/test-repository/testpkgc-2.0-alpha.cati' ]), 0) self.assert_equals(self.run_command('forget', [ 'testpkgc=2.0' ]), 0) self.assert_true(not os.path.isfile(self.env() + '/var/lib/cati/lists/testpkgc/2.0-all')) self.assert_true(os.path.isfile(self.env() + '/var/lib/cati/lists/testpkgc/2.0-alpha-all'))
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 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 test """ self.assert_equals(self.run_command('autoremove', []), 0) self.assert_equals( self.run_command('pkg', [ 'install', 'repository/test-repository/testpkg11.cati', '--auto' ]), 0) self.assert_equals( self.run_command('pkg', [ 'install', 'repository/test-repository/testpkg10.cati', ]), 0) self.assert_true(Pkg.is_installed('testpkg11')) self.assert_true(Pkg.is_installed('testpkg10')) self.assert_equals(self.run_command('autoremove', ['-y']), 0) self.assert_true(Pkg.is_installed('testpkg11')) self.assert_true(Pkg.is_installed('testpkg10')) self.assert_equals(self.run_command('remove', [ '-y', 'testpkg10', ]), 0) self.assert_true(Pkg.is_installed('testpkg11')) self.assert_true(not Pkg.is_installed('testpkg10')) self.assert_equals(self.run_command('autoremove', ['-y']), 0) self.assert_true(not Pkg.is_installed('testpkg11')) self.assert_true(not Pkg.is_installed('testpkg10')) self.refresh_env() self.assert_equals( self.run_command('pkg', [ 'install', 'repository/test-repository/testpkg11.cati', 'repository/test-repository/testpkg10.cati', '--auto', ]), 0) self.assert_equals( self.run_command('pkg', [ 'install', 'repository/test-repository/testpkg9.cati', ]), 0) self.assert_true(Pkg.is_installed('testpkg11')) self.assert_true(Pkg.is_installed('testpkg10')) self.assert_true(Pkg.is_installed('testpkg9')) self.assert_equals(self.run_command('remove', [ '-y', 'testpkg9', ]), 0) self.assert_true(Pkg.is_installed('testpkg11')) self.assert_true(Pkg.is_installed('testpkg10')) self.assert_true(not Pkg.is_installed('testpkg9')) self.assert_equals(self.run_command('autoremove', ['-y']), 0) self.assert_true(not Pkg.is_installed('testpkg11')) self.assert_true(not Pkg.is_installed('testpkg10')) self.assert_true(not Pkg.is_installed('testpkg9'))