def add_package_to_lists(self, pkg: Pkg, index_updater_events: dict): """ Adds the package information to database Args: pkg (Pkg): the package index_updater_events (dict): events for index updater """ 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) ListUpdater.index_reverse_depends_and_conflicts(pkg)
def update_indexes(events: dict): """ This function loads available versions of a package and index them in index file and do this action for all of packages in lists. Args: events: (dict) the `events` argument should be a dictonary from functions. this will use to handle errors for example if some thing went wrong, the spesific function in events will run. events: - cannot_read_file: if in this process, an error happened while reading a file, this will run with file path arg - invalid_json_data: if json content of a file is curropt, this will run with file path and content args """ require_root_permission() for pkg in os.listdir(Env.packages_lists()): pkg_index = {} if os.path.isdir(Env.packages_lists('/' + pkg)): for version in os.listdir(Env.packages_lists('/' + pkg)): if version not in [ 'index', 'reverse_depends', 'reverse_conflicts' ]: if os.path.isfile( Env.packages_lists('/' + pkg + '/' + version)): content = None try: f = open( Env.packages_lists('/' + pkg + '/' + version), 'r') content = f.read() except: events['cannot_read_file']( Env.packages_lists('/' + pkg + '/' + version)) if content != None: try: content_json = json.loads(content) try: tmp = pkg_index[content_json['arch']] del tmp except: pkg_index[content_json['arch']] = [] pkg_index[content_json['arch']].append( content_json['version']) except: events['invalid_json_data']( Env.packages_lists('/' + pkg + '/' + version), content) # write generated index to index file f_index = open(Env.packages_lists('/' + pkg + '/index'), 'w') f_index.write(json.dumps(pkg_index)) f_index.close()
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 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 index_reverse_depends_and_conflicts(pkg: Pkg): """ Packages have `depends` and `conflicts` But also they have `Reverse` depends and conflicts Reverse d/c should be indexed because loading them real time is so big process We index them in a place, and when a package is added/changed, this function should be called Args: pkg (Pkg): changed/added package (reverse c/d will be set for that packages this package is related to them) """ # load the packages depend_pkgs = [] conflict_pkgs = [] for depend in pkg.get_depends(): query_parts = Pkg.check_state(depend, only_parse=True) for depth1 in query_parts: for depth2 in depth1: depend_pkgs.append(depth2[0]) for conflict in pkg.get_conflicts(): query_parts = Pkg.check_state(conflict, only_parse=True) for depth1 in query_parts: for depth2 in depth1: conflict_pkgs.append(depth2[0]) # set reverse depends/conflicts for found packages for p in depend_pkgs: f_path = Env.packages_lists('/' + p + '/reverse_depends') current_list = None try: if not os.path.isdir(Env.packages_lists('/' + p)): os.mkdir(Env.packages_lists('/' + p)) if not os.path.isfile(f_path): current_list = [] else: f = open(f_path, 'r') current_list = [ item.strip() for item in f.read().strip().split('\n') if item.strip() != '' ] f.close() if not pkg.data['name'] in current_list: current_list.append(pkg.data['name']) # write new list new_list_str = '' for item in current_list: new_list_str += item + '\n' new_list_str = new_list_str.strip() f = open(f_path, 'w') f.write(new_list_str) f.close() except: pass for p in conflict_pkgs: f_path = Env.packages_lists('/' + p + '/reverse_conflicts') current_list = None try: if not os.path.isdir(Env.packages_lists('/' + p)): os.mkdir(Env.packages_lists('/' + p)) if not os.path.isfile(f_path): current_list = [] else: f = open(f_path, 'r') current_list = [ item.strip() for item in f.read().strip().split('\n') if item.strip() != '' ] f.close() if not pkg.data['name'] in current_list: current_list.append(pkg.data['name']) # write new list new_list_str = '' for item in current_list: new_list_str += item + '\n' new_list_str = new_list_str.strip() f = open(f_path, 'w') f.write(new_list_str) f.close() except: pass
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(): if not repo.is_disable: orig_repos.append(repo) else: if not self.is_quiet(): self.message('Warning: ignoring repository "' + repo.name + '" because this is disable') 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() ListUpdater.index_reverse_depends_and_conflicts(Pkg(pkg)) 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)