Package entropy :: Package client :: Package interfaces :: Module client

Source Code for Module entropy.client.interfaces.client

  1  # -*- coding: utf-8 -*- 
  2  """ 
  3   
  4      @author: Fabio Erculiani <lxnay@sabayonlinux.org> 
  5      @contact: lxnay@sabayonlinux.org 
  6      @copyright: Fabio Erculiani 
  7      @license: GPL-2 
  8   
  9      B{Entropy Package Manager Client Core Interface}. 
 10   
 11  """ 
 12   
 13  from __future__ import with_statement 
 14  import os 
 15  import sys 
 16  from entropy.core import Singleton 
 17  from entropy.output import TextInterface, bold, red, darkred, blue 
 18  from entropy.db import dbapi2 
 19  from entropy.client.interfaces.loaders import LoadersMixin 
 20  from entropy.client.interfaces.cache import CacheMixin 
 21  from entropy.client.interfaces.dep import CalculatorsMixin 
 22  from entropy.client.interfaces.methods import RepositoryMixin, MiscMixin, \ 
 23      MatchMixin 
 24  from entropy.client.interfaces.fetch import FetchersMixin 
 25  from entropy.client.interfaces.noticeboard import NoticeBoardMixin 
 26  from entropy.const import etpConst, etpCache, etpUi, const_debug_write 
 27  from entropy.core.settings.base import SystemSettings 
 28  from entropy.core.settings.plugins.skel import SystemSettingsPlugin 
 29  from entropy.misc import LogFile 
 30  from entropy.exceptions import SystemDatabaseError, RepositoryError 
 31  from entropy.i18n import _ 
 32   
33 -class ClientSystemSettingsPlugin(SystemSettingsPlugin):
34 35 import entropy.tools as entropyTools 36
37 - def __init__(self, plugin_id, helper_interface):
38 SystemSettingsPlugin.__init__(self, plugin_id, helper_interface) 39 self.__repos_files = {} 40 self.__repos_mtime = {}
41
42 - def __setup_repos_files(self, system_settings):
43 """ 44 This function collects available repositories configuration files 45 by filling internal dict() __repos_files and __repos_mtime. 46 47 @param system_settings: SystemSettings instance 48 @type system_settings: instance of SystemSettings 49 @return: None 50 @rtype: None 51 """ 52 53 self.__repos_mtime = { 54 'repos_license_whitelist': {}, 55 'repos_mask': {}, 56 'repos_system_mask': {}, 57 'repos_critical_updates': {}, 58 'repos_keywords': {}, 59 } 60 self.__repos_files = { 61 'repos_license_whitelist': {}, 62 'repos_mask': {}, 63 'repos_system_mask': {}, 64 'conflicting_tagged_packages': {}, 65 'repos_critical_updates': {}, 66 'repos_keywords': {}, 67 } 68 69 dmp_dir = etpConst['dumpstoragedir'] 70 for repoid in system_settings['repositories']['order']: 71 72 repos_mask_setting = {} 73 repos_mask_mtime = {} 74 repos_lic_wl_setting = {} 75 repos_lic_wl_mtime = {} 76 repo_data = system_settings['repositories']['available'][repoid] 77 repos_sm_mask_setting = {} 78 repos_sm_mask_mtime = {} 79 confl_tagged = {} 80 repos_critical_updates_setting = {} 81 repos_critical_updates_mtime = {} 82 repos_keywords_setting = {} 83 repos_keywords_mtime = {} 84 85 maskpath = os.path.join(repo_data['dbpath'], 86 etpConst['etpdatabasemaskfile']) 87 wlpath = os.path.join(repo_data['dbpath'], 88 etpConst['etpdatabaselicwhitelistfile']) 89 sm_path = os.path.join(repo_data['dbpath'], 90 etpConst['etpdatabasesytemmaskfile']) 91 ct_path = os.path.join(repo_data['dbpath'], 92 etpConst['etpdatabaseconflictingtaggedfile']) 93 critical_path = os.path.join(repo_data['dbpath'], 94 etpConst['etpdatabasecriticalfile']) 95 keywords_path = os.path.join(repo_data['dbpath'], 96 etpConst['etpdatabasekeywordsfile']) 97 98 if os.access(maskpath, os.R_OK | os.F_OK): 99 repos_mask_setting[repoid] = maskpath 100 repos_mask_mtime[repoid] = dmp_dir + "/repo_" + \ 101 repoid + "_" + etpConst['etpdatabasemaskfile'] + ".mtime" 102 103 if os.access(wlpath, os.R_OK | os.F_OK): 104 repos_lic_wl_setting[repoid] = wlpath 105 repos_lic_wl_mtime[repoid] = dmp_dir + "/repo_" + \ 106 repoid + "_" + etpConst['etpdatabaselicwhitelistfile'] + \ 107 ".mtime" 108 109 if os.access(sm_path, os.R_OK | os.F_OK): 110 repos_sm_mask_setting[repoid] = sm_path 111 repos_sm_mask_mtime[repoid] = dmp_dir + "/repo_" + \ 112 repoid + "_" + etpConst['etpdatabasesytemmaskfile'] + \ 113 ".mtime" 114 if os.access(ct_path, os.R_OK | os.F_OK): 115 confl_tagged[repoid] = ct_path 116 117 if os.access(critical_path, os.R_OK | os.F_OK): 118 repos_critical_updates_setting[repoid] = critical_path 119 repos_critical_updates_mtime[repoid] = dmp_dir + "/repo_" + \ 120 repoid + "_" + etpConst['etpdatabasecriticalfile'] + \ 121 ".mtime" 122 123 if os.access(keywords_path, os.R_OK | os.F_OK): 124 repos_keywords_setting[repoid] = keywords_path 125 repos_keywords_mtime[repoid] = dmp_dir + "/repo_" + \ 126 repoid + "_" + etpConst['etpdatabasekeywordsfile'] + \ 127 ".mtime" 128 129 self.__repos_files['repos_mask'].update(repos_mask_setting) 130 self.__repos_mtime['repos_mask'].update(repos_mask_mtime) 131 132 self.__repos_files['repos_license_whitelist'].update( 133 repos_lic_wl_setting) 134 self.__repos_mtime['repos_license_whitelist'].update( 135 repos_lic_wl_mtime) 136 137 self.__repos_files['repos_system_mask'].update( 138 repos_sm_mask_setting) 139 self.__repos_mtime['repos_system_mask'].update( 140 repos_sm_mask_mtime) 141 142 self.__repos_files['conflicting_tagged_packages'].update( 143 confl_tagged) 144 145 self.__repos_files['repos_critical_updates'].update( 146 repos_critical_updates_setting) 147 self.__repos_mtime['repos_critical_updates'].update( 148 repos_critical_updates_mtime) 149 150 self.__repos_files['repos_keywords'].update(repos_keywords_setting) 151 self.__repos_mtime['repos_keywords'].update(repos_keywords_mtime)
152
153 - def __run_post_branch_migration_hooks(self, sys_settings_instance):
154 155 # only root can do this 156 if os.getuid() != 0: 157 return 158 159 old_branch_path = etpConst['etp_previous_branch_file'] 160 in_branch_upgrade_path = etpConst['etp_in_branch_upgrade_file'] 161 current_branch = sys_settings_instance['repositories']['branch'] 162 163 def write_current_branch(branch): 164 old_brf = open(old_branch_path, "w") 165 old_brf.write(branch) 166 old_brf.flush() 167 old_brf.close()
168 169 def write_in_branch_upgrade(branch): 170 brf = open(in_branch_upgrade_path, "w") 171 brf.write("in branch upgrade: %s" % (branch,)) 172 brf.flush() 173 brf.close()
174 175 if not os.access(old_branch_path, os.F_OK | os.R_OK): 176 write_current_branch(current_branch) 177 return 178 179 old_f = open(old_branch_path, "r") 180 old_branch = old_f.readline().strip() 181 old_f.close() 182 183 if old_branch == current_branch: # all fine, no need to run 184 return 185 186 repos, err = self._helper.run_repositories_post_branch_switch_hooks( 187 old_branch, current_branch) 188 if not err: 189 write_in_branch_upgrade(current_branch) 190 write_current_branch(current_branch) 191
192 - def __run_post_branch_upgrade_hooks(self, sys_settings_instance):
193 194 # only root can do this 195 if os.getuid() != 0: 196 return 197 198 repos, errors = self._helper.run_repository_post_branch_upgrade_hooks( 199 pretend = True) 200 if not repos: 201 # no scripts to run 202 return 203 204 # look for updates 205 # critical_updates = False is needed to avoid 206 # issues with metadata not being available 207 try: 208 update, remove, fine, spm_fine = \ 209 self._helper.calculate_world_updates( 210 critical_updates = False) 211 except (ValueError, SystemDatabaseError, RepositoryError,): 212 # RepositoryError is triggered when branch is hopped 213 # SystemDatabaseError is triggered when no client db is avail 214 # ValueError is triggered when repos are broken 215 update = 1 # foo! 216 217 def delete_in_branch_upgrade(): 218 br_path = etpConst['etp_in_branch_upgrade_file'] 219 if os.access(br_path, os.W_OK | os.F_OK): 220 os.remove(br_path)
221 222 # actually execute this only if 223 # there are no updates left 224 if not update: 225 self._helper.run_repository_post_branch_upgrade_hooks() 226 delete_in_branch_upgrade() 227
228 - def system_mask_parser(self, system_settings_instance):
229 230 parser_data = {} 231 # match installed packages of system_mask 232 mask_installed = [] 233 mask_installed_keys = {} 234 while (self._helper.clientDbconn != None): 235 try: 236 self._helper.clientDbconn.validateDatabase() 237 except SystemDatabaseError: 238 break 239 mc_cache = set() 240 repos_mask_list = self.__repositories_system_mask( 241 system_settings_instance) 242 m_list = repos_mask_list + system_settings_instance['system_mask'] 243 for atom in m_list: 244 m_ids, m_r = self._helper.clientDbconn.atomMatch(atom, 245 multiMatch = True) 246 if m_r != 0: 247 continue 248 mykey = self.entropyTools.dep_getkey(atom) 249 if mykey not in mask_installed_keys: 250 mask_installed_keys[mykey] = set() 251 for m_id in m_ids: 252 if m_id in mc_cache: 253 continue 254 mc_cache.add(m_id) 255 mask_installed.append(m_id) 256 mask_installed_keys[mykey].add(m_id) 257 break 258 259 parser_data.update({ 260 'repos_installed': mask_installed, 261 'repos_installed_keys': mask_installed_keys, 262 }) 263 return parser_data
264
265 - def masking_validation_parser(self, system_settings_instance):
266 data = { 267 'cache': {}, # package masking validation cache 268 } 269 return data
270
271 - def __repositories_repos_keywords(self, repo_keywords_path):
272 """ 273 Parser returning system packages mask metadata read from 274 packages.db.keywords file inside the repository directory. 275 This file contains maintainer supplied per-repository extra 276 package keywords. 277 """ 278 data = { 279 # universal keywords: keywords added repository-wide to all 280 # the available packages (in repo). 281 'universal': set(), 282 # per-package keywording, keys are atoms/dep (first line argument) 283 # values are provided keywords 284 'packages': {}, 285 'packages_ids': None, # reserved for entropy.db package validation 286 } 287 288 entries = self.entropyTools.generic_file_content_parser( 289 repo_keywords_path) 290 291 # iterate over config file data 292 for entry in entries: 293 entry = entry.split() 294 if len(entry) == 1: 295 # universal keyword 296 item = entry[0] 297 if item == "**": 298 item = '' 299 data['universal'].add(item) 300 301 elif len(entry) > 1: 302 # per package keyword 303 pkg = entry[0] 304 keywords = entry[1:] 305 obj = data['packages'].setdefault(pkg, set()) 306 obj.update(keywords) 307 308 return data
309 310
311 - def __repositories_system_mask(self, sys_settings_instance):
312 """ 313 Parser returning system packages mask metadata read from 314 packages.db.system_mask file inside the repository directory. 315 This file contains packages that should be always kept 316 installed, extending the already defined (in repository database) 317 set of atoms. 318 """ 319 system_mask = [] 320 for repoid in self.__repos_files['repos_system_mask']: 321 sys_settings_instance.validate_entropy_cache( 322 self.__repos_files['repos_system_mask'][repoid], 323 self.__repos_mtime['repos_system_mask'][repoid], 324 repoid = repoid) 325 system_mask += [x for x in \ 326 self.entropyTools.generic_file_content_parser( 327 self.__repos_files['repos_system_mask'][repoid]) if x \ 328 not in system_mask] 329 return system_mask
330
331 - def repositories_parser(self, sys_settings_instance):
332 """ 333 Parser that generates repository settings metadata. 334 335 @param sys_settings_instance: SystemSettings instance 336 @type sys_settings_instance: instance of SystemSettings 337 @return: parsed metadata 338 @rtype: dict 339 """ 340 341 # fill repositories metadata dictionaries 342 self.__setup_repos_files(sys_settings_instance) 343 344 data = { 345 'license_whitelist': {}, 346 'mask': {}, 347 'system_mask': [], 348 'critical_updates': {}, 349 'conflicting_tagged_packages': {}, 350 'repos_keywords': {}, 351 } 352 353 # parse license whitelist 354 """ 355 Parser returning licenses considered accepted by default 356 (= GPL compatibles) read from package.lic_whitelist. 357 """ 358 for repoid in self.__repos_files['repos_license_whitelist']: 359 sys_settings_instance.validate_entropy_cache( 360 self.__repos_files['repos_license_whitelist'][repoid], 361 self.__repos_mtime['repos_license_whitelist'][repoid], 362 repoid = repoid) 363 364 data['license_whitelist'][repoid] = \ 365 self.entropyTools.generic_file_content_parser( 366 self.__repos_files['repos_license_whitelist'][repoid]) 367 368 # package masking 369 """ 370 Parser returning packages masked at repository level read from 371 packages.db.mask inside the repository database directory. 372 """ 373 for repoid in self.__repos_files['repos_mask']: 374 sys_settings_instance.validate_entropy_cache( 375 self.__repos_files['repos_mask'][repoid], 376 self.__repos_mtime['repos_mask'][repoid], repoid = repoid) 377 378 data['mask'][repoid] = \ 379 self.entropyTools.generic_file_content_parser( 380 self.__repos_files['repos_mask'][repoid]) 381 382 # keywords masking 383 """ 384 Parser returning packages masked at repository level read from 385 packages.db.keywords inside the repository database directory. 386 """ 387 for repoid in self.__repos_files['repos_keywords']: 388 sys_settings_instance.validate_entropy_cache( 389 self.__repos_files['repos_keywords'][repoid], 390 self.__repos_mtime['repos_keywords'][repoid], repoid = repoid) 391 392 data['repos_keywords'][repoid] = \ 393 self.__repositories_repos_keywords( 394 self.__repos_files['repos_keywords'][repoid]) 395 396 # system masking 397 data['system_mask'] = self.__repositories_system_mask( 398 sys_settings_instance) 399 400 # critical updates 401 """ 402 Parser returning critical packages list metadata read from 403 packages.db.critical file inside the repository directory. 404 This file contains packages that should be always updated 405 before anything else. 406 """ 407 for repoid in self.__repos_files['repos_critical_updates']: 408 sys_settings_instance.validate_entropy_cache( 409 self.__repos_files['repos_critical_updates'][repoid], 410 self.__repos_mtime['repos_critical_updates'][repoid], 411 repoid = repoid) 412 data['critical_updates'][repoid] = \ 413 self.entropyTools.generic_file_content_parser( 414 self.__repos_files['repos_critical_updates'][repoid]) 415 416 417 # conflicts map 418 """ 419 Parser returning packages that could have been installed because 420 they aren't in the same scope, but ending up creating critical 421 issues. You can see it as a configurable conflict map. 422 """ 423 # keep priority order 424 repoids = [x for x in sys_settings_instance['repositories']['order'] \ 425 if x in self.__repos_files['conflicting_tagged_packages']] 426 for repoid in repoids: 427 filepath = self.__repos_files['conflicting_tagged_packages'].get( 428 repoid) 429 if os.access(filepath, os.R_OK | os.F_OK): 430 confl_f = open(filepath,"r") 431 content = confl_f.readlines() 432 confl_f.close() 433 content = [x.strip().rsplit("#", 1)[0].strip().split() for x \ 434 in content if not x.startswith("#") and x.strip()] 435 for mydata in content: 436 if len(mydata) < 2: 437 continue 438 data['conflicting_tagged_packages'][mydata[0]] = mydata[1:] 439 440 return data
441
442 - def misc_parser(self, sys_settings_instance):
443 444 """ 445 Parses Entropy client system configuration file. 446 447 @return dict data 448 """ 449 450 data = { 451 'filesbackup': etpConst['filesbackup'], 452 'forcedupdates': etpConst['forcedupdates'], 453 'ignore_spm_downgrades': etpConst['spm']['ignore-spm-downgrades'], 454 'collisionprotect': etpConst['collisionprotect'], 455 'configprotect': etpConst['configprotect'][:], 456 'configprotectmask': etpConst['configprotectmask'][:], 457 'configprotectskip': etpConst['configprotectskip'][:], 458 } 459 460 cli_conf = etpConst['clientconf'] 461 if not (os.path.isfile(cli_conf) and os.access(cli_conf, os.R_OK)): 462 return data 463 464 client_f = open(cli_conf,"r") 465 clientconf = [x.strip() for x in client_f.readlines() if \ 466 x.strip() and not x.strip().startswith("#")] 467 client_f.close() 468 for line in clientconf: 469 470 split_line = line.split("|") 471 split_line_len = len(split_line) 472 473 if line.startswith("filesbackup|") and (split_line_len == 2): 474 475 compatopt = split_line[1].strip().lower() 476 if compatopt in ("disable", "disabled","false", "0", "no",): 477 data['filesbackup'] = False 478 479 if line.startswith("forcedupdates|") and (split_line_len == 2): 480 481 compatopt = split_line[1].strip().lower() 482 if compatopt in ("disable", "disabled","false", "0", "no",): 483 data['forcedupdates'] = False 484 else: 485 data['forcedupdates'] = True 486 487 elif line.startswith("ignore-spm-downgrades|") and \ 488 (split_line_len == 2): 489 490 compatopt = split_line[1].strip().lower() 491 if compatopt in ("enable", "enabled", "true", "1", "yes"): 492 data['ignore_spm_downgrades'] = True 493 494 elif line.startswith("collisionprotect|") and (split_line_len == 2): 495 496 collopt = split_line[1].strip() 497 if collopt.lower() in ("0", "1", "2",): 498 data['collisionprotect'] = int(collopt) 499 500 elif line.startswith("configprotect|") and (split_line_len == 2): 501 502 configprotect = split_line[1].strip() 503 for myprot in configprotect.split(): 504 data['configprotect'].append( 505 unicode(myprot,'raw_unicode_escape')) 506 507 elif line.startswith("configprotectmask|") and \ 508 (split_line_len == 2): 509 510 configprotect = split_line[1].strip() 511 for myprot in configprotect.split(): 512 data['configprotectmask'].append( 513 unicode(myprot,'raw_unicode_escape')) 514 515 elif line.startswith("configprotectskip|") and \ 516 (split_line_len == 2): 517 518 configprotect = split_line[1].strip() 519 for myprot in configprotect.split(): 520 data['configprotectskip'].append( 521 etpConst['systemroot']+unicode(myprot, 522 'raw_unicode_escape')) 523 524 return data
525
526 - def post_setup(self, system_settings_instance):
527 """ 528 Reimplemented from SystemSettingsPlugin. 529 """ 530 531 if self._helper._can_run_sys_set_hooks: 532 # run post-branch migration scripts if branch setting got changed 533 self.__run_post_branch_migration_hooks(system_settings_instance) 534 # run post-branch upgrade migration scripts if the function 535 # above created migration files to handle 536 self.__run_post_branch_upgrade_hooks(system_settings_instance)
537 538
539 -class Client(Singleton, TextInterface, LoadersMixin, CacheMixin, CalculatorsMixin, \ 540 RepositoryMixin, MiscMixin, MatchMixin, FetchersMixin, NoticeBoardMixin):
541
542 - def init_singleton(self, indexing = True, noclientdb = 0, 543 xcache = True, user_xcache = False, repo_validation = True, 544 load_ugc = True, url_fetcher = None, 545 multiple_url_fetcher = None):
546 547 self._can_run_sys_set_hooks = False 548 const_debug_write(__name__, "debug enabled") 549 self.sys_settings_client_plugin_id = \ 550 etpConst['system_settings_plugins_ids']['client_plugin'] 551 self.__instance_destroyed = False 552 self.atomMatchCacheKey = etpCache['atomMatch'] 553 self.dbapi2 = dbapi2 # export for third parties 554 self.FileUpdates = None 555 self.validRepositories = [] 556 self.UGC = None 557 # supporting external updateProgress stuff, you can point self.progress 558 # to your progress bar and reimplement updateProgress 559 self.progress = None 560 self.clientDbconn = None 561 self.safe_mode = 0 562 self.indexing = indexing 563 self.repo_validation = repo_validation 564 self.noclientdb = False 565 self.openclientdb = True 566 567 # setup package settings (masking and other stuff) 568 self.SystemSettings = SystemSettings() 569 const_debug_write(__name__, "SystemSettings loaded") 570 571 # modules import 572 import entropy.dump as dumpTools 573 import entropy.tools as entropyTools 574 self.dumpTools = dumpTools 575 self.entropyTools = entropyTools 576 self.clientLog = LogFile(level = self.SystemSettings['system']['log_level'], 577 filename = etpConst['equologfile'], header = "[client]") 578 579 self.MultipleUrlFetcher = multiple_url_fetcher 580 self.urlFetcher = url_fetcher 581 if self.urlFetcher == None: 582 from entropy.transceivers import UrlFetcher 583 self.urlFetcher = UrlFetcher 584 if self.MultipleUrlFetcher == None: 585 from entropy.transceivers import MultipleUrlFetcher 586 self.MultipleUrlFetcher = MultipleUrlFetcher 587 588 from entropy.cache import EntropyCacher 589 self.Cacher = EntropyCacher() 590 591 from entropy.client.misc import FileUpdates 592 self.FileUpdates = FileUpdates(self) 593 594 from entropy.client.mirrors import StatusInterface 595 # mirror status interface 596 self.MirrorStatus = StatusInterface() 597 598 if noclientdb in (False,0): 599 self.noclientdb = False 600 elif noclientdb in (True,1): 601 self.noclientdb = True 602 elif noclientdb == 2: 603 self.noclientdb = True 604 self.openclientdb = False 605 606 # load User Generated Content Interface 607 if load_ugc: 608 from entropy.client.services.ugc.interfaces import Client as ugc_cl 609 self.UGC = ugc_cl(self) 610 611 # class init 612 LoadersMixin.__init__(self) 613 614 self.xcache = xcache 615 shell_xcache = os.getenv("ETP_NOCACHE") 616 if shell_xcache: 617 self.xcache = False 618 619 do_validate_repo_cache = False 620 # now if we are on live, we should disable it 621 # are we running on a livecd? (/proc/cmdline has "cdroot") 622 if self.entropyTools.islive(): 623 self.xcache = False 624 elif (not self.entropyTools.is_user_in_entropy_group()) and not user_xcache: 625 self.xcache = False 626 elif not user_xcache: 627 do_validate_repo_cache = True 628 629 if not self.xcache and (self.entropyTools.is_user_in_entropy_group()): 630 try: 631 self.purge_cache(False) 632 except: 633 pass 634 635 if self.openclientdb: 636 self.open_client_repository() 637 638 # create our SystemSettings plugin 639 self.sys_settings_client_plugin = ClientSystemSettingsPlugin( 640 self.sys_settings_client_plugin_id, self) 641 642 # needs to be started here otherwise repository cache will be 643 # always dropped 644 if self.xcache: 645 self.Cacher.start() 646 647 if do_validate_repo_cache: 648 self.validate_repositories_cache() 649 650 if self.repo_validation: 651 self.validate_repositories() 652 else: 653 self.validRepositories.extend( 654 self.SystemSettings['repositories']['order']) 655 656 # add our SystemSettings plugin 657 # Make sure we connect Entropy Client plugin AFTER client db init 658 self.SystemSettings.add_plugin(self.sys_settings_client_plugin) 659 660 # enable System Settings hooks 661 self._can_run_sys_set_hooks = True 662 const_debug_write(__name__, "singleton loaded")
663 664
665 - def destroy(self):
666 self.__instance_destroyed = True 667 if hasattr(self,'clientDbconn'): 668 if self.clientDbconn != None: 669 self.clientDbconn.closeDB() 670 del self.clientDbconn 671 if hasattr(self,'FileUpdates'): 672 del self.FileUpdates 673 if hasattr(self,'clientLog'): 674 self.clientLog.close() 675 if hasattr(self,'SystemSettings') and \ 676 hasattr(self,'sys_settings_client_plugin_id'): 677 678 if hasattr(self.SystemSettings,'remove_plugin'): 679 try: 680 self.SystemSettings.remove_plugin( 681 self.sys_settings_client_plugin_id) 682 except KeyError: 683 pass 684 685 self.close_all_repositories(mask_clear = False) 686 self.closeAllSecurity() 687 self.closeAllQA()
688
689 - def repository_packages_spm_sync(self, repository_identifier, repo_db, 690 force = False):
691 """ 692 Service method used to sync package names with Source Package Manager 693 via metadata stored in Repository dbs collected at server-time. 694 Source Package Manager can change package names, categories or slot 695 and Entropy repositories must be kept in sync. 696 697 In other words, it checks for /usr/portage/profiles/updates changes, 698 of course indirectly, since there is no way entropy.client can directly 699 depend on Portage. 700 701 @param repository_identifier: repository identifier which repo_db 702 parameter is bound 703 @type repository_identifier: string 704 @param repo_db: repository database instance 705 @type repo_db: entropy.db.EntropyRepository 706 @return: bool stating if changes have been made 707 @rtype: bool 708 """ 709 if not self.clientDbconn: 710 # nothing to do if client db is not availabe 711 return False 712 713 etpConst['client_treeupdatescalled'].add(repository_identifier) 714 715 doRescan = False 716 shell_rescan = os.getenv("ETP_TREEUPDATES_RESCAN") 717 if shell_rescan: 718 doRescan = True 719 720 # check database digest 721 stored_digest = repo_db.retrieveRepositoryUpdatesDigest( 722 repository_identifier) 723 if stored_digest == -1: 724 doRescan = True 725 726 # check stored value in client database 727 client_digest = "0" 728 if not doRescan: 729 client_digest = self.clientDbconn.retrieveRepositoryUpdatesDigest( 730 repository_identifier) 731 732 if doRescan or (str(stored_digest) != str(client_digest)) or force: 733 734 # reset database tables 735 self.clientDbconn.clearTreeupdatesEntries(repository_identifier) 736 737 # load updates 738 update_actions = repo_db.retrieveTreeUpdatesActions( 739 repository_identifier) 740 # now filter the required actions 741 update_actions = self.clientDbconn.filterTreeUpdatesActions( 742 update_actions) 743 744 if update_actions: 745 746 mytxt = "%s: %s." % ( 747 bold(_("ATTENTION")), 748 red(_("forcing packages metadata update")), 749 ) 750 self.updateProgress( 751 mytxt, 752 importance = 1, 753 type = "info", 754 header = darkred(" * ") 755 ) 756 mytxt = "%s %s." % ( 757 red(_("Updating system database using repository")), 758 blue(repository_identifier), 759 ) 760 self.updateProgress( 761 mytxt, 762 importance = 1, 763 type = "info", 764 header = darkred(" * ") 765 ) 766 # run stuff 767 self.clientDbconn.runTreeUpdatesActions(update_actions) 768 769 # store new digest into database 770 self.clientDbconn.setRepositoryUpdatesDigest(repository_identifier, 771 stored_digest) 772 # store new actions 773 self.clientDbconn.addRepositoryUpdatesActions(etpConst['clientdbid'], 774 update_actions, self.SystemSettings['repositories']['branch']) 775 self.clientDbconn.commitChanges() 776 # clear client cache 777 self.clientDbconn.clearCache() 778 return True
779
780 - def is_destroyed(self):
781 return self.__instance_destroyed
782
783 - def __del__(self):
784 self.destroy()
785