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