Package entropy :: Module db

Source Code for Module entropy.db

   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 Framework repository database module}. 
  10      Entropy repositories (server and client) are implemented as relational 
  11      databases. Currently, EntropyRepository class is the object that wraps 
  12      sqlite3 database queries and repository logic: there are no more 
  13      abstractions between the two because there is only one implementation 
  14      available at this time. In future, entropy.db will feature more backends 
  15      such as MySQL embedded, SparQL, remote repositories support via TCP socket, 
  16      etc. This will require a new layer between the repository interface now 
  17      offered by EntropyRepository and the underlying data retrieval logic. 
  18      Every repository interface available inherits from EntropyRepository 
  19      class and has to reimplement its own Schema subclass and its get_init 
  20      method (see EntropyRepository documentation for more information). 
  21   
  22      I{EntropyRepository} is the sqlite3 implementation of the repository 
  23      interface, as written above. 
  24   
  25      I{ServerRepositoryStatus} is a singleton containing the status of 
  26      server-side repositories. It is used to determine if repository has 
  27      been modified (tainted) or has been revision bumped already. 
  28      Revision bumps are automatic and happen on the very first data "commit". 
  29      Every repository features a revision number which is stored into the 
  30      "packages.db.revision" file. Only server-side (or community) repositories 
  31      are subject to this automation (revision file update on commit). 
  32   
  33  """ 
  34   
  35  from __future__ import with_statement 
  36  import os 
  37  import shutil 
  38  from entropy.const import etpConst, etpCache 
  39  from entropy.exceptions import IncorrectParameter, InvalidAtom, \ 
  40      SystemDatabaseError, OperationNotPermitted 
  41  from entropy.i18n import _ 
  42  from entropy.output import brown, bold, red, blue, purple, darkred, darkgreen, \ 
  43      TextInterface 
  44  from entropy.cache import EntropyCacher 
  45  from entropy.core import Singleton, SystemSettings 
  46   
  47  try: # try with sqlite3 from >=python 2.5 
  48      from sqlite3 import dbapi2 
  49  except ImportError: # fallback to pysqlite 
  50      try: 
  51          from pysqlite2 import dbapi2 
  52      except ImportError, e: 
  53          raise SystemError( 
  54              "%s. %s: %s" % ( 
  55                  _("Entropy needs Python compiled with sqlite3 support"), 
  56                  _("Error"), 
  57                  e, 
  58              ) 
  59          ) 
  60   
61 -class ServerRepositoryStatus(Singleton):
62 63 """ 64 Server-side Repositories status information container. 65 """ 66
67 - def init_singleton(self):
68 """ Singleton "constructor" """ 69 self.__data = {}
70
71 - def __create_if_necessary(self, db):
72 if db not in self.__data: 73 self.__data[db] = {} 74 self.__data[db]['tainted'] = False 75 self.__data[db]['bumped'] = False 76 self.__data[db]['unlock_msg'] = False
77
78 - def set_unlock_msg(self, db):
79 """ 80 Set bit which determines if the unlock warning has been already 81 printed to user. 82 83 @param db: database identifier 84 @type db: string 85 """ 86 self.__create_if_necessary(db) 87 self.__data[db]['unlock_msg'] = True
88
89 - def unset_unlock_msg(self, db):
90 """ 91 Unset bit which determines if the unlock warning has been already 92 printed to user. 93 94 @param db: database identifier 95 @type db: string 96 """ 97 self.__create_if_necessary(db) 98 self.__data[db]['unlock_msg'] = False
99
100 - def set_tainted(self, db):
101 """ 102 Set bit which determines if the repository which db points to has been 103 modified. 104 105 @param db: database identifier 106 @type db: string 107 """ 108 self.__create_if_necessary(db) 109 self.__data[db]['tainted'] = True
110
111 - def unset_tainted(self, db):
112 """ 113 Unset bit which determines if the repository which db points to has been 114 modified. 115 116 @param db: database identifier 117 @type db: string 118 """ 119 self.__create_if_necessary(db) 120 self.__data[db]['tainted'] = False
121
122 - def set_bumped(self, db):
123 """ 124 Set bit which determines if the repository which db points to has been 125 revision bumped. 126 127 @param db: database identifier 128 @type db: string 129 """ 130 self.__create_if_necessary(db) 131 self.__data[db]['bumped'] = True
132
133 - def unset_bumped(self, db):
134 """ 135 Unset bit which determines if the repository which db points to has been 136 revision bumped. 137 138 @param db: database identifier 139 @type db: string 140 """ 141 self.__create_if_necessary(db) 142 self.__data[db]['bumped'] = False
143
144 - def is_tainted(self, db):
145 """ 146 Return whether repository which db points to has been modified. 147 148 @param db: database identifier 149 @type db: string 150 """ 151 self.__create_if_necessary(db) 152 return self.__data[db]['tainted']
153
154 - def is_bumped(self, db):
155 """ 156 Return whether repository which db points to has been revision bumped. 157 158 @param db: database identifier 159 @type db: string 160 """ 161 self.__create_if_necessary(db) 162 return self.__data[db]['bumped']
163
164 - def is_unlock_msg(self, db):
165 """ 166 Return whether repository which db points to has outputed the unlock 167 warning message. 168 169 @param db: database identifier 170 @type db: string 171 """ 172 self.__create_if_necessary(db) 173 return self.__data[db]['unlock_msg']
174 175
176 -class EntropyRepository:
177 178 """ 179 EntropyRepository implements SQLite3 based storage. In a Model-View based 180 pattern, it can be considered the "model". 181 Actually it's the only one available but more model backends will be 182 supported in future (which will inherit this class directly). 183 184 Every Entropy repository storage interface MUST inherit from this base 185 class. 186 187 @todo: refactoring and generalization needed 188 """ 189
190 - class Schema:
191
192 - def get_init(self):
193 return """ 194 CREATE TABLE baseinfo ( 195 idpackage INTEGER PRIMARY KEY AUTOINCREMENT, 196 atom VARCHAR, 197 idcategory INTEGER, 198 name VARCHAR, 199 version VARCHAR, 200 versiontag VARCHAR, 201 revision INTEGER, 202 branch VARCHAR, 203 slot VARCHAR, 204 idlicense INTEGER, 205 etpapi INTEGER, 206 trigger INTEGER 207 ); 208 209 CREATE TABLE extrainfo ( 210 idpackage INTEGER PRIMARY KEY, 211 description VARCHAR, 212 homepage VARCHAR, 213 download VARCHAR, 214 size VARCHAR, 215 idflags INTEGER, 216 digest VARCHAR, 217 datecreation VARCHAR 218 ); 219 220 CREATE TABLE content ( 221 idpackage INTEGER, 222 file VARCHAR, 223 type VARCHAR 224 ); 225 226 CREATE TABLE provide ( 227 idpackage INTEGER, 228 atom VARCHAR 229 ); 230 231 CREATE TABLE dependencies ( 232 idpackage INTEGER, 233 iddependency INTEGER, 234 type INTEGER 235 ); 236 237 CREATE TABLE dependenciesreference ( 238 iddependency INTEGER PRIMARY KEY AUTOINCREMENT, 239 dependency VARCHAR 240 ); 241 242 CREATE TABLE dependstable ( 243 iddependency INTEGER PRIMARY KEY, 244 idpackage INTEGER 245 ); 246 247 CREATE TABLE conflicts ( 248 idpackage INTEGER, 249 conflict VARCHAR 250 ); 251 252 CREATE TABLE mirrorlinks ( 253 mirrorname VARCHAR, 254 mirrorlink VARCHAR 255 ); 256 257 CREATE TABLE sources ( 258 idpackage INTEGER, 259 idsource INTEGER 260 ); 261 262 CREATE TABLE sourcesreference ( 263 idsource INTEGER PRIMARY KEY AUTOINCREMENT, 264 source VARCHAR 265 ); 266 267 CREATE TABLE useflags ( 268 idpackage INTEGER, 269 idflag INTEGER 270 ); 271 272 CREATE TABLE useflagsreference ( 273 idflag INTEGER PRIMARY KEY AUTOINCREMENT, 274 flagname VARCHAR 275 ); 276 277 CREATE TABLE keywords ( 278 idpackage INTEGER, 279 idkeyword INTEGER 280 ); 281 282 CREATE TABLE keywordsreference ( 283 idkeyword INTEGER PRIMARY KEY AUTOINCREMENT, 284 keywordname VARCHAR 285 ); 286 287 CREATE TABLE categories ( 288 idcategory INTEGER PRIMARY KEY AUTOINCREMENT, 289 category VARCHAR 290 ); 291 292 CREATE TABLE licenses ( 293 idlicense INTEGER PRIMARY KEY AUTOINCREMENT, 294 license VARCHAR 295 ); 296 297 CREATE TABLE flags ( 298 idflags INTEGER PRIMARY KEY AUTOINCREMENT, 299 chost VARCHAR, 300 cflags VARCHAR, 301 cxxflags VARCHAR 302 ); 303 304 CREATE TABLE configprotect ( 305 idpackage INTEGER PRIMARY KEY, 306 idprotect INTEGER 307 ); 308 309 CREATE TABLE configprotectmask ( 310 idpackage INTEGER PRIMARY KEY, 311 idprotect INTEGER 312 ); 313 314 CREATE TABLE configprotectreference ( 315 idprotect INTEGER PRIMARY KEY AUTOINCREMENT, 316 protect VARCHAR 317 ); 318 319 CREATE TABLE systempackages ( 320 idpackage INTEGER PRIMARY KEY 321 ); 322 323 CREATE TABLE injected ( 324 idpackage INTEGER PRIMARY KEY 325 ); 326 327 CREATE TABLE installedtable ( 328 idpackage INTEGER PRIMARY KEY, 329 repositoryname VARCHAR, 330 source INTEGER 331 ); 332 333 CREATE TABLE sizes ( 334 idpackage INTEGER PRIMARY KEY, 335 size INTEGER 336 ); 337 338 CREATE TABLE messages ( 339 idpackage INTEGER, 340 message VARCHAR 341 ); 342 343 CREATE TABLE counters ( 344 counter INTEGER, 345 idpackage INTEGER, 346 branch VARCHAR, 347 PRIMARY KEY(idpackage,branch) 348 ); 349 350 CREATE TABLE trashedcounters ( 351 counter INTEGER 352 ); 353 354 CREATE TABLE eclasses ( 355 idpackage INTEGER, 356 idclass INTEGER 357 ); 358 359 CREATE TABLE eclassesreference ( 360 idclass INTEGER PRIMARY KEY AUTOINCREMENT, 361 classname VARCHAR 362 ); 363 364 CREATE TABLE needed ( 365 idpackage INTEGER, 366 idneeded INTEGER, 367 elfclass INTEGER 368 ); 369 370 CREATE TABLE neededreference ( 371 idneeded INTEGER PRIMARY KEY AUTOINCREMENT, 372 library VARCHAR 373 ); 374 375 CREATE TABLE neededlibrarypaths ( 376 library VARCHAR, 377 path VARCHAR, 378 elfclass INTEGER, 379 PRIMARY KEY(library, path, elfclass) 380 ); 381 382 CREATE TABLE neededlibraryidpackages ( 383 idpackage INTEGER, 384 library VARCHAR, 385 elfclass INTEGER 386 ); 387 388 CREATE TABLE treeupdates ( 389 repository VARCHAR PRIMARY KEY, 390 digest VARCHAR 391 ); 392 393 CREATE TABLE treeupdatesactions ( 394 idupdate INTEGER PRIMARY KEY AUTOINCREMENT, 395 repository VARCHAR, 396 command VARCHAR, 397 branch VARCHAR, 398 date VARCHAR 399 ); 400 401 CREATE TABLE licensedata ( 402 licensename VARCHAR UNIQUE, 403 text BLOB, 404 compressed INTEGER 405 ); 406 407 CREATE TABLE licenses_accepted ( 408 licensename VARCHAR UNIQUE 409 ); 410 411 CREATE TABLE triggers ( 412 idpackage INTEGER PRIMARY KEY, 413 data BLOB 414 ); 415 416 CREATE TABLE entropy_misc_counters ( 417 idtype INTEGER PRIMARY KEY, 418 counter INTEGER 419 ); 420 421 CREATE TABLE categoriesdescription ( 422 category VARCHAR, 423 locale VARCHAR, 424 description VARCHAR 425 ); 426 427 CREATE TABLE packagesets ( 428 setname VARCHAR, 429 dependency VARCHAR 430 ); 431 432 CREATE TABLE packagechangelogs ( 433 category VARCHAR, 434 name VARCHAR, 435 changelog BLOB, 436 PRIMARY KEY (category, name) 437 ); 438 439 CREATE TABLE automergefiles ( 440 idpackage INTEGER, 441 configfile VARCHAR, 442 md5 VARCHAR 443 ); 444 445 CREATE TABLE packagesignatures ( 446 idpackage INTEGER PRIMARY KEY, 447 sha1 VARCHAR, 448 sha256 VARCHAR, 449 sha512 VARCHAR 450 ); 451 452 CREATE TABLE packagespmphases ( 453 idpackage INTEGER PRIMARY KEY, 454 phases VARCHAR 455 ); 456 457 CREATE TABLE entropy_branch_migration ( 458 repository VARCHAR, 459 from_branch VARCHAR, 460 to_branch VARCHAR, 461 post_migration_md5sum VARCHAR, 462 post_upgrade_md5sum VARCHAR, 463 PRIMARY KEY (repository, from_branch, to_branch) 464 ); 465 466 """
467 468 import entropy.tools as entropyTools 469 import entropy.dump as dumpTools 470 import threading
471 - def __init__(self, readOnly = False, noUpload = False, dbFile = None, 472 clientDatabase = False, xcache = False, dbname = etpConst['serverdbid'], 473 indexing = True, OutputInterface = None, ServiceInterface = None, 474 skipChecks = False, useBranch = None, lockRemote = True):
475 476 """ 477 EntropyRepository constructor. 478 479 @keyword readOnly: open file in read-only mode 480 @type readOnly: bool 481 @keyword noUpload: server-side setting for not allowing database 482 uploads when remote revision is lower than local 483 @type noUpload: bool 484 @keyword dbFile: path to database to open 485 @type dbFile: string 486 @keyword clientDatabase: state that EntropyRepository instance is 487 a client-side one 488 @type clientDatabase: bool 489 @keyword xcache: enable on-disk cache 490 @type xcache: bool 491 @keyword dbname: EntropyRepository instance identifier 492 @type dbname: string 493 @keyword indexing: enable database indexes 494 @type indexing: bool 495 @keyword OutputInterface: interface used to communicate with the user. 496 must inherit entropy.output.TextInterface 497 @type OutputInterface: entropy.output.TextInterface based instance 498 @keyword ServiceInterface: any class instance that could be useful 499 when writing custom routines 500 @type ServiceInterface: Python class instance 501 @keyword skipChecks: if True, skip integrity checks 502 @type skipChecks: bool 503 @keyword useBranch: if True, it won't use SystemSettings' branch 504 setting but rather the one provided 505 @type useBranch: string 506 @keyword lockRemote: determine whether remote server-side database 507 should be locked when updating the local version 508 @type lockRemote: bool 509 """ 510 511 self.SystemSettings = SystemSettings() 512 self.srv_sys_settings_plugin = \ 513 etpConst['system_settings_plugins_ids']['server_plugin'] 514 self.dbMatchCacheKey = etpCache['dbMatch'] 515 self.client_settings_plugin_id = etpConst['system_settings_plugins_ids']['client_plugin'] 516 self.db_branch = self.SystemSettings['repositories']['branch'] 517 self.Cacher = EntropyCacher() 518 519 self.dbname = dbname 520 self.lockRemote = lockRemote 521 if self.dbname == etpConst['clientdbid']: 522 self.db_branch = None 523 if useBranch != None: 524 self.db_branch = useBranch 525 526 if OutputInterface == None: 527 OutputInterface = TextInterface() 528 529 if dbFile == None: 530 raise IncorrectParameter("IncorrectParameter: %s" % ( 531 _("valid database path needed"),) ) 532 533 self.__write_mutex = self.threading.Lock() 534 self.dbapi2 = dbapi2 535 # setup output interface 536 self.OutputInterface = OutputInterface 537 self.updateProgress = self.OutputInterface.updateProgress 538 self.askQuestion = self.OutputInterface.askQuestion 539 # setup service interface 540 self.ServiceInterface = ServiceInterface 541 self.readOnly = readOnly 542 self.noUpload = noUpload 543 self.clientDatabase = clientDatabase 544 self.xcache = xcache 545 self.indexing = indexing 546 self.skipChecks = skipChecks 547 if not self.skipChecks: 548 if not self.entropyTools.is_user_in_entropy_group(): 549 # forcing since we won't have write access to db 550 self.indexing = False 551 # live systems don't like wasting RAM 552 if self.entropyTools.islive(): 553 self.indexing = False 554 self.dbFile = dbFile 555 self.dbclosed = True 556 self.server_repo = None 557 558 if not self.clientDatabase: 559 self.server_repo = self.dbname[len(etpConst['serverdbid']):] 560 self._create_dbstatus_data() 561 562 if not self.skipChecks: 563 # no caching for non root and server connections 564 if (self.dbname.startswith(etpConst['serverdbid'])) or \ 565 (not self.entropyTools.is_user_in_entropy_group()): 566 self.xcache = False 567 self.live_cache = {} 568 569 # create connection 570 self.connection = self.dbapi2.connect(dbFile, timeout=300.0, 571 check_same_thread = False) 572 self.cursor = self.connection.cursor() 573 574 if not self.skipChecks: 575 try: 576 if os.access(self.dbFile, os.W_OK) and \ 577 self.doesTableExist('baseinfo') and \ 578 self.doesTableExist('extrainfo'): 579 580 if self.entropyTools.islive() and etpConst['systemroot']: 581 self.databaseStructureUpdates() 582 else: 583 self.databaseStructureUpdates() 584 except self.dbapi2.Error: 585 self.cursor.close() 586 self.connection.close() 587 raise 588 589 # now we can set this to False 590 self.dbclosed = False
591
592 - def setCacheSize(self, size):
593 """ 594 Change low-level, storage engine based cache size. 595 596 @param size: new size 597 @type size: int 598 """ 599 self.cursor.execute('PRAGMA cache_size = '+str(size))
600
601 - def setDefaultCacheSize(self, size):
602 """ 603 Change default low-level, storage engine based cache size. 604 605 @param size: new default size 606 @type size: int 607 """ 608 self.cursor.execute('PRAGMA default_cache_size = '+str(size))
609 610
611 - def __del__(self):
612 if not self.dbclosed: 613 self.closeDB()
614
615 - def _create_dbstatus_data(self):
616 """ 617 Server-side function that setups server status information 618 """ 619 taint_file = self.ServiceInterface.get_local_database_taint_file( 620 self.server_repo) 621 if os.path.isfile(taint_file): 622 dbs = ServerRepositoryStatus() 623 dbs.set_tainted(self.dbFile) 624 dbs.set_bumped(self.dbFile)
625
626 - def closeDB(self):
627 """ 628 Close repository storage communication. 629 Note: once issues this, you won't be able to use such instance 630 anymore. 631 """ 632 self.dbclosed = True 633 634 # if the class is opened readOnly, close and forget 635 if self.readOnly: 636 self.cursor.close() 637 self.connection.close() 638 return 639 640 if self.clientDatabase: 641 self.commitChanges() 642 self.cursor.close() 643 self.connection.close() 644 return 645 646 sts = ServerRepositoryStatus() 647 if not sts.is_tainted(self.dbFile): 648 # we can unlock it, no changes were made 649 self.ServiceInterface.MirrorsService.lock_mirrors(False, 650 repo = self.server_repo) 651 elif not sts.is_unlock_msg(self.dbFile): 652 u_msg = _("Mirrors have not been unlocked. Remember to sync them.") 653 self.updateProgress( 654 darkgreen(u_msg), 655 importance = 1, 656 type = "info", 657 header = brown(" * ") 658 ) 659 sts.set_unlock_msg(self.dbFile) # avoid spamming 660 661 self.commitChanges() 662 self.cursor.close() 663 self.connection.close()
664
665 - def vacuum(self):
666 """ 667 Repository storage cleanup and optimization function. 668 """ 669 self.cursor.execute("vacuum")
670
671 - def commitChanges(self):
672 """ 673 Commit actual changes and make them permanently stored. 674 """ 675 if self.readOnly: 676 return 677 678 try: 679 self.connection.commit() 680 except self.dbapi2.Error: 681 pass 682 683 if not self.clientDatabase: 684 self.taintDatabase() 685 dbs = ServerRepositoryStatus() 686 if (dbs.is_tainted(self.dbFile)) and \ 687 (not dbs.is_bumped(self.dbFile)): 688 # bump revision, setting DatabaseBump causes 689 # the session to just bump once 690 dbs.set_bumped(self.dbFile) 691 self._revisionBump()
692
693 - def taintDatabase(self):
694 """ 695 Server-side method that render your repository storage tainted, 696 modified. 697 """ 698 # if it's equo to open it, this should be avoided 699 if self.clientDatabase: 700 return 701 # taint the database status 702 taint_file = self.ServiceInterface.get_local_database_taint_file( 703 repo = self.server_repo) 704 f = open(taint_file, "w") 705 f.write(etpConst['currentarch']+" database tainted\n") 706 f.flush() 707 f.close() 708 ServerRepositoryStatus().set_tainted(self.dbFile)
709
710 - def untaintDatabase(self):
711 """ 712 Server-side method that render your repository storage NOT tainted, 713 modified. 714 """ 715 # if it's equo to open it, this should be avoided 716 if self.clientDatabase: 717 return 718 ServerRepositoryStatus().unset_tainted(self.dbFile) 719 # untaint the database status 720 taint_file = self.ServiceInterface.get_local_database_taint_file( 721 repo = self.server_repo) 722 if os.path.isfile(taint_file): 723 os.remove(taint_file)
724
725 - def _revisionBump(self):
726 """ 727 Entropy repository revision bumping function. Every time it's called, 728 revision is incremented by 1. 729 """ 730 revision_file = self.ServiceInterface.get_local_database_revision_file( 731 repo = self.server_repo) 732 if not os.path.isfile(revision_file): 733 revision = 1 734 else: 735 f = open(revision_file, "r") 736 revision = int(f.readline().strip()) 737 revision += 1 738 f.close() 739 f = open(revision_file, "w") 740 f.write(str(revision)+"\n") 741 f.flush() 742 f.close()
743
744 - def isDatabaseTainted(self):
745 taint_file = self.ServiceInterface.get_local_database_taint_file( 746 repo = self.server_repo) 747 if os.path.isfile(taint_file): 748 return True 749 return False
750 751 # never use this unless you know what you're doing
752 - def initializeDatabase(self):
753 self.checkReadOnly() 754 my = self.Schema() 755 for table in self.listAllTables(): 756 try: 757 self.cursor.execute("DROP TABLE %s" % (table,)) 758 except self.dbapi2.OperationalError: 759 # skip tables that can't be dropped 760 continue 761 self.cursor.executescript(my.get_init()) 762 self.databaseStructureUpdates() 763 # set cache size 764 self.setCacheSize(8192) 765 self.setDefaultCacheSize(8192) 766 self.commitChanges()
767
768 - def checkReadOnly(self):
769 if self.readOnly: 770 raise OperationNotPermitted("OperationNotPermitted: %s." % ( 771 _("can't do that on a readonly database"), 772 ) 773 )
774 775 # check for /usr/portage/profiles/updates changes
776 - def serverUpdatePackagesData(self):
777 778 etpConst['server_treeupdatescalled'].add(self.server_repo) 779 780 repo_updates_file = self.ServiceInterface.get_local_database_treeupdates_file(self.server_repo) 781 doRescan = False 782 783 stored_digest = self.retrieveRepositoryUpdatesDigest(self.server_repo) 784 if stored_digest == -1: 785 doRescan = True 786 787 # check portage files for changes if doRescan is still false 788 portage_dirs_digest = "0" 789 if not doRescan: 790 791 treeupdates_dict = self.ServiceInterface.repository_treeupdate_digests 792 793 if treeupdates_dict.has_key(self.server_repo): 794 portage_dirs_digest = treeupdates_dict.get(self.server_repo) 795 else: 796 797 spm = self.ServiceInterface.SpmService 798 # grab portdir 799 updates_dir = etpConst['systemroot'] + \ 800 spm.get_spm_setting("PORTDIR") + "/profiles/updates" 801 if os.path.isdir(updates_dir): 802 # get checksum 803 mdigest = self.entropyTools.md5sum_directory(updates_dir, 804 get_obj = True) 805 # also checksum etpConst['etpdatabaseupdatefile'] 806 if os.path.isfile(repo_updates_file): 807 f = open(repo_updates_file) 808 block = f.read(1024) 809 while block: 810 mdigest.update(block) 811 block = f.read(1024) 812 f.close() 813 portage_dirs_digest = mdigest.hexdigest() 814 treeupdates_dict[self.server_repo] = portage_dirs_digest 815 del updates_dir 816 817 if doRescan or (str(stored_digest) != str(portage_dirs_digest)): 818 819 # force parameters 820 self.readOnly = False 821 self.noUpload = True 822 823 # reset database tables 824 self.clearTreeupdatesEntries(self.server_repo) 825 826 spm = self.ServiceInterface.SpmService 827 updates_dir = etpConst['systemroot'] + \ 828 spm.get_spm_setting("PORTDIR") + "/profiles/updates" 829 update_files = self.entropyTools.sort_update_files( 830 os.listdir(updates_dir)) 831 update_files = [os.path.join(updates_dir, x) for x in update_files] 832 # now load actions from files 833 update_actions = [] 834 for update_file in update_files: 835 f = open(update_file, "r") 836 mycontent = f.readlines() 837 f.close() 838 lines = [x.strip() for x in mycontent if x.strip()] 839 update_actions.extend(lines) 840 841 # add entropy packages.db.repo_updates content 842 if os.path.isfile(repo_updates_file): 843 f = open(repo_updates_file, "r") 844 mycontent = f.readlines() 845 f.close() 846 lines = [x.strip() for x in mycontent if x.strip() and \ 847 not x.strip().startswith("#")] 848 update_actions.extend(lines) 849 # now filter the required actions 850 update_actions = self.filterTreeUpdatesActions(update_actions) 851 if update_actions: 852 853 mytxt = "%s: %s. %s %s" % ( 854 bold(_("ATTENTION")), 855 red(_("forcing package updates")), 856 red(_("Syncing with")), 857 blue(updates_dir), 858 ) 859 self.updateProgress( 860 mytxt, 861 importance = 1, 862 type = "info", 863 header = brown(" * ") 864 ) 865 # lock database 866 if self.lockRemote: 867 self.ServiceInterface.do_server_repository_sync_lock( 868 self.server_repo, self.noUpload) 869 # now run queue 870 try: 871 self.runTreeUpdatesActions(update_actions) 872 except: 873 # destroy digest 874 self.setRepositoryUpdatesDigest(self.server_repo, "-1") 875 raise 876 877 # store new actions 878 self.addRepositoryUpdatesActions( 879 self.server_repo, update_actions, self.db_branch) 880 881 # store new digest into database 882 self.setRepositoryUpdatesDigest( 883 self.server_repo, portage_dirs_digest) 884 self.commitChanges()
885
886 - def clientUpdatePackagesData(self, clientDbconn, force = False):
887 888 if clientDbconn == None: 889 return 890 891 repository = self.dbname[len(etpConst['dbnamerepoprefix']):] 892 etpConst['client_treeupdatescalled'].add(repository) 893 894 doRescan = False 895 shell_rescan = os.getenv("ETP_TREEUPDATES_RESCAN") 896 if shell_rescan: doRescan = True 897 898 # check database digest 899 stored_digest = self.retrieveRepositoryUpdatesDigest(repository) 900 if stored_digest == -1: 901 doRescan = True 902 903 # check stored value in client database 904 client_digest = "0" 905 if not doRescan: 906 client_digest = clientDbconn.retrieveRepositoryUpdatesDigest( 907 repository) 908 909 if doRescan or (str(stored_digest) != str(client_digest)) or force: 910 911 # reset database tables 912 clientDbconn.clearTreeupdatesEntries(repository) 913 914 # load updates 915 update_actions = self.retrieveTreeUpdatesActions(repository) 916 # now filter the required actions 917 update_actions = clientDbconn.filterTreeUpdatesActions( 918 update_actions) 919 920 if update_actions: 921 922 mytxt = "%s: %s." % ( 923 bold(_("ATTENTION")), 924 red(_("forcing packages metadata update")), 925 ) 926 self.updateProgress( 927 mytxt, 928 importance = 1, 929 type = "info", 930 header = darkred(" * ") 931 ) 932 mytxt = "%s %s." % ( 933 red(_("Updating system database using repository")), 934 blue(repository), 935 ) 936 self.updateProgress( 937 mytxt, 938 importance = 1, 939 type = "info", 940 header = darkred(" * ") 941 ) 942 # run stuff 943 clientDbconn.runTreeUpdatesActions(update_actions) 944 945 # store new digest into database 946 clientDbconn.setRepositoryUpdatesDigest(repository, stored_digest) 947 # store new actions 948 clientDbconn.addRepositoryUpdatesActions(etpConst['clientdbid'], 949 update_actions, self.SystemSettings['repositories']['branch']) 950 clientDbconn.commitChanges() 951 # clear client cache 952 clientDbconn.clearCache() 953 return True
954 955 # this functions will filter either data from /usr/portage/profiles/updates/* 956 # or repository database returning only the needed actions
957 - def filterTreeUpdatesActions(self, actions):
958 new_actions = [] 959 for action in actions: 960 961 if action in new_actions: # skip dupies 962 continue 963 964 doaction = action.split() 965 if doaction[0] == "slotmove": 966 967 # slot move 968 atom = doaction[1] 969 from_slot = doaction[2] 970 to_slot = doaction[3] 971 atom_key = self.entropyTools.dep_getkey(atom) 972 category = atom_key.split("/")[0] 973 matches = self.atomMatch(atom, matchSlot = from_slot, 974 multiMatch = True) 975 found = False 976 # found atoms, check category 977 for idpackage in matches[0]: 978 myslot = self.retrieveSlot(idpackage) 979 mycategory = self.retrieveCategory(idpackage) 980 if mycategory == category: 981 if (myslot != to_slot) and \ 982 (action not in new_actions): 983 new_actions.append(action) 984 found = True 985 break 986 if found: 987 continue 988 # if we get here it means found == False 989 # search into dependencies 990 dep_atoms = self.searchDependency(atom_key, like = True, 991 multi = True, strings = True) 992 dep_atoms = [x for x in dep_atoms if x.endswith(":"+from_slot) \ 993 and self.entropyTools.dep_getkey(x) == atom_key] 994 if dep_atoms: 995 new_actions.append(action) 996 997 elif doaction[0] == "move": 998 atom = doaction[1] # usually a key 999 atom_key = self.entropyTools.dep_getkey(atom) 1000 category = atom_key.split("/")[0] 1001 matches = self.atomMatch(atom, multiMatch = True) 1002 found = False 1003 for idpackage in matches[0]: 1004 mycategory = self.retrieveCategory(idpackage) 1005 if (mycategory == category) and (action \ 1006 not in new_actions): 1007 new_actions.append(action) 1008 found = True 1009 break 1010 if found: 1011 continue 1012 # if we get here it means found == False 1013 # search into dependencies 1014 dep_atoms = self.searchDependency(atom_key, like = True, 1015 multi = True, strings = True) 1016 dep_atoms = [x for x in dep_atoms if \ 1017 self.entropyTools.dep_getkey(x) == atom_key] 1018 if dep_atoms: 1019 new_actions.append(action) 1020 return new_actions
1021 1022 # this is the place to add extra actions support
1023 - def runTreeUpdatesActions(self, actions):
1024 1025 mytxt = "%s: %s, %s." % ( 1026 bold(_("SPM")), 1027 blue(_("Running fixpackages")), 1028 red(_("it could take a while")), 1029 ) 1030 self.updateProgress( 1031 mytxt, 1032 importance = 1, 1033 type = "warning", 1034 header = darkred(" * ") 1035 ) 1036 if self.clientDatabase: 1037 try: 1038 spm = self.ServiceInterface.Spm() 1039 spm.run_fixpackages() 1040 except: 1041 pass 1042 else: 1043 self.ServiceInterface.SpmService.run_fixpackages() 1044 1045 spm_moves = set() 1046 quickpkg_atoms = set() 1047 for action in actions: 1048 command = action.split() 1049 mytxt = "%s: %s: %s." % ( 1050 bold(_("ENTROPY")), 1051 red(_("action")), 1052 blue(action), 1053 ) 1054 self.updateProgress( 1055 mytxt, 1056 importance = 1, 1057 type = "warning", 1058 header = darkred(" * ") 1059 ) 1060 if command[0] == "move": 1061 spm_moves.add(action) 1062 quickpkg_atoms |= self.runTreeUpdatesMoveAction(command[1:], 1063 quickpkg_atoms) 1064 elif command[0] == "slotmove": 1065 quickpkg_atoms |= self.runTreeUpdatesSlotmoveAction(command[1:], 1066 quickpkg_atoms) 1067 1068 mytxt = "%s: %s." % ( 1069 bold(_("ENTROPY")), 1070 blue(_("package move actions complete")), 1071 ) 1072 self.updateProgress( 1073 mytxt, 1074 importance = 1, 1075 type = "info", 1076 header = purple(" @@ ") 1077 ) 1078 1079 if quickpkg_atoms and not self.clientDatabase: 1080 # quickpkg package and packages owning it as a dependency 1081 try: 1082 self.runTreeUpdatesQuickpkgAction(quickpkg_atoms) 1083 except: 1084 self.entropyTools.print_traceback() 1085 mytxt = "%s: %s: %s, %s." % ( 1086 bold(_("WARNING")), 1087 red(_("Cannot complete quickpkg for atoms")), 1088 blue(str(list(quickpkg_atoms))), 1089 _("do it manually"), 1090 ) 1091 self.updateProgress( 1092 mytxt, 1093 importance = 1, 1094 type = "warning", 1095 header = darkred(" * ") 1096 ) 1097 self.commitChanges() 1098 1099 if spm_moves: 1100 try: 1101 self.doTreeupdatesSpmCleanup(spm_moves) 1102 except Exception, e: 1103 mytxt = "%s: %s: %s, %s." % ( 1104 bold(_("WARNING")), 1105 red(_("Cannot run SPM cleanup, error")), 1106 Exception, 1107 e, 1108 ) 1109 self.entropyTools.print_traceback() 1110 1111 mytxt = "%s: %s." % ( 1112 bold(_("ENTROPY")), 1113 blue(_("package moves completed successfully")), 1114 ) 1115 self.updateProgress( 1116 mytxt, 1117 importance = 1, 1118 type = "info", 1119 header = brown(" @@ ") 1120 ) 1121 1122 # discard cache 1123 self.clearCache()
1124 1125 1126 # -- move action: 1127 # 1) move package key to the new name: category + name + atom 1128 # 2) update all the dependencies in dependenciesreference to the new key 1129 # 3) run fixpackages which will update /var/db/pkg files 1130 # 4) automatically run quickpkg() to build the new binary and 1131 # tainted binaries owning tainted iddependency and taint database
1132 - def runTreeUpdatesMoveAction(self, move_command, quickpkg_queue):
1133 1134 dep_from = move_command[0] 1135 key_from = self.entropyTools.dep_getkey(dep_from) 1136 key_to = move_command[1] 1137 cat_to = key_to.split("/")[0] 1138 name_to = key_to.split("/")[1] 1139 matches = self.atomMatch(dep_from, multiMatch = True) 1140 iddependencies = set() 1141 1142 for idpackage in matches[0]: 1143 1144 slot = self.retrieveSlot(idpackage) 1145 old_atom = self.retrieveAtom(idpackage) 1146 new_atom = old_atom.replace(key_from, key_to) 1147 1148 ### UPDATE DATABASE 1149 # update category 1150 self.setCategory(idpackage, cat_to) 1151 # update name 1152 self.setName(idpackage, name_to) 1153 # update atom 1154 self.setAtom(idpackage, new_atom) 1155 1156 # look for packages we need to quickpkg again 1157 # note: quickpkg_queue is simply ignored if self.clientDatabase 1158 quickpkg_queue.add(key_to+":"+str(slot)) 1159 1160 if not self.clientDatabase: 1161 1162 # check for injection and warn the developer 1163 injected = self.isInjected(idpackage) 1164 if injected: 1165 mytxt = "%s: %s %s. %s !!! %s." % ( 1166 bold(_("INJECT")), 1167 blue(str(new_atom)), 1168 red(_("has been injected")), 1169 red(_("quickpkg manually to update embedded db")), 1170 red(_("Repository database updated anyway")), 1171 ) 1172 self.updateProgress( 1173 mytxt, 1174 importance = 1, 1175 type = "warning", 1176 header = darkred(" * ") 1177 ) 1178 1179 iddeps = self.searchDependency(key_from, like = True, multi = True) 1180 for iddep in iddeps: 1181 # update string 1182 mydep = self.retrieveDependencyFromIddependency(iddep) 1183 mydep_key = self.entropyTools.dep_getkey(mydep) 1184 # avoid changing wrong atoms -> dev-python/qscintilla-python would 1185 # become x11-libs/qscintilla if we don't do this check 1186 if mydep_key != key_from: 1187 continue 1188 mydep = mydep.replace(key_from, key_to) 1189 # now update 1190 # dependstable on server is always re-generated 1191 self.setDependency(iddep, mydep) 1192 # we have to repackage also package owning this iddep 1193 iddependencies |= self.searchIdpackageFromIddependency(iddep) 1194 1195 self.commitChanges() 1196 quickpkg_queue = list(quickpkg_queue) 1197 for x in range(len(quickpkg_queue)): 1198 myatom = quickpkg_queue[x] 1199 myatom = myatom.replace(key_from, key_to) 1200 quickpkg_queue[x] = myatom 1201 quickpkg_queue = set(quickpkg_queue) 1202 for idpackage_owner in iddependencies: 1203 myatom = self.retrieveAtom(idpackage_owner) 1204 myatom = myatom.replace(key_from, key_to) 1205 quickpkg_queue.add(myatom) 1206 return quickpkg_queue
1207 1208 1209 # -- slotmove action: 1210 # 1) move package slot 1211 # 2) update all the dependencies in dependenciesreference owning 1212 # same matched atom + slot 1213 # 3) run fixpackages which will update /var/db/pkg files 1214 # 4) automatically run quickpkg() to build the new 1215 # binary and tainted binaries owning tainted iddependency 1216 # and taint database
1217 - def runTreeUpdatesSlotmoveAction(self, slotmove_command, quickpkg_queue):
1218 1219 atom = slotmove_command[0] 1220 atomkey = self.entropyTools.dep_getkey(atom) 1221 slot_from = slotmove_command[1] 1222 slot_to = slotmove_command[2] 1223 matches = self.atomMatch(atom, multiMatch = True) 1224 iddependencies = set() 1225 1226 matched_idpackages = matches[0] 1227 for idpackage in matched_idpackages: 1228 1229 ### UPDATE DATABASE 1230 # update slot 1231 self.setSlot(idpackage, slot_to) 1232 1233 # look for packages we need to quickpkg again 1234 # note: quickpkg_queue is simply ignored if self.clientDatabase 1235 quickpkg_queue.add(atom+":"+str(slot_to)) 1236 1237 if not self.clientDatabase: 1238 1239 # check for injection and warn the developer 1240 injected = self.isInjected(idpackage) 1241 if injected: 1242 mytxt = "%s: %s %s. %s !!! %s." % ( 1243 bold(_("INJECT")), 1244 blue(str(atom)), 1245 red(_("has been injected")), 1246 red(_("quickpkg manually to update embedded db")), 1247 red(_("Repository database updated anyway")), 1248 ) 1249 self.updateProgress( 1250 mytxt, 1251 importance = 1, 1252 type = "warning", 1253 header = darkred(" * ") 1254 ) 1255 1256 # only if we've found VALID matches ! 1257 iddeps = self.searchDependency(atomkey, like = True, multi = True) 1258 for iddep in iddeps: 1259 # update string 1260 mydep = self.retrieveDependencyFromIddependency(iddep) 1261 mydep_key = self.entropyTools.dep_getkey(mydep) 1262 if mydep_key != atomkey: 1263 continue 1264 if not mydep.endswith(":"+slot_from): # probably slotted dep 1265 continue 1266 mydep_match = self.atomMatch(mydep) 1267 if mydep_match not in matched_idpackages: 1268 continue 1269 mydep = mydep.replace(":"+slot_from, ":"+slot_to) 1270 # now update 1271 # dependstable on server is always re-generated 1272 self.setDependency(iddep, mydep) 1273 # we have to repackage also package owning this iddep 1274 iddependencies |= self.searchIdpackageFromIddependency(iddep) 1275 1276 self.commitChanges() 1277 for idpackage_owner in iddependencies: 1278 myatom = self.retrieveAtom(idpackage_owner) 1279 quickpkg_queue.add(myatom) 1280 return quickpkg_queue
1281
1282 - def runTreeUpdatesQuickpkgAction(self, atoms):
1283 1284 self.commitChanges() 1285 1286 package_paths = set() 1287 runatoms = set() 1288 for myatom in atoms: 1289 mymatch = self.atomMatch(myatom) 1290 if mymatch[0] == -1: 1291 continue 1292 myatom = self.retrieveAtom(mymatch[0]) 1293 runatoms.add(myatom) 1294 1295 for myatom in runatoms: 1296 self.updateProgress( 1297 red("%s: " % (_("repackaging"),) )+blue(myatom), 1298 importance = 1, 1299 type = "warning", 1300 header = blue(" # ") 1301 ) 1302 mydest = self.ServiceInterface.get_local_store_directory( 1303 repo = self.server_repo) 1304 try: 1305 mypath = self.ServiceInterface.quickpkg(myatom, mydest) 1306 except: 1307 # remove broken bin before raising 1308 mypath = os.path.join(mydest, 1309 os.path.basename(myatom)+etpConst['packagesext']) 1310 if os.path.isfile(mypath): 1311 os.remove(mypath) 1312 self.entropyTools.print_traceback() 1313 mytxt = "%s: %s: %s, %s." % ( 1314 bold(_("WARNING")), 1315 red(_("Cannot complete quickpkg for atom")), 1316 blue(myatom), 1317 _("do it manually"), 1318 ) 1319 self.updateProgress( 1320 mytxt, 1321 importance = 1, 1322 type = "warning", 1323 header = darkred(" * ") 1324 ) 1325 continue 1326 package_paths.add(mypath) 1327 packages_data = [(x, False,) for x in package_paths] 1328 idpackages = self.ServiceInterface.add_packages_to_repository( 1329 packages_data, repo = self.server_repo) 1330 1331 if not idpackages: 1332 1333 mytxt = "%s: %s. %s." % ( 1334 bold(_("ATTENTION")), 1335 red(_("runTreeUpdatesQuickpkgAction did not run properly")), 1336 red(_("Please update packages manually")), 1337 ) 1338 self.updateProgress( 1339 mytxt, 1340 importance = 1, 1341 type = "warning", 1342 header = darkred(" * ") 1343 )
1344
1345 - def doTreeupdatesSpmCleanup(self, spm_moves):
1346 1347 # now erase Spm entries if necessary 1348 for action in spm_moves: 1349 command = action.split() 1350 if len(command) < 2: 1351 continue 1352 key = command[1] 1353 name = key.split("/")[1] 1354 if self.clientDatabase: 1355 try: 1356 spm = self.ServiceInterface.Spm() 1357 except: 1358 continue 1359 else: 1360 spm = self.ServiceInterface.SpmService 1361 vdb_path = spm.get_vdb_path() 1362 pkg_path = os.path.join(vdb_path, key.split("/")[0]) 1363 try: 1364 mydirs = [os.path.join(pkg_path, x) for x in \ 1365 os.listdir(pkg_path) if x.startswith(name)] 1366 except OSError: # no dir, no party! 1367 continue 1368 mydirs = [x for x in mydirs if os.path.isdir(x)] 1369 # now move these dirs 1370 for mydir in mydirs: 1371 to_path = os.path.join(etpConst['packagestmpdir'], 1372 os.path.basename(mydir)) 1373 mytxt = "%s: %s '%s' %s '%s'" % ( 1374 bold(_("SPM")), 1375 red(_("Moving old entry")), 1376 blue(mydir), 1377 red(_("to")), 1378 blue(to_path), 1379 ) 1380 self.updateProgress( 1381 mytxt, 1382 importance = 1, 1383 type = "warning", 1384 header = darkred(" * ") 1385 ) 1386 if os.path.isdir(to_path): 1387 shutil.rmtree(to_path, True) 1388 try: 1389 os.rmdir(to_path) 1390 except OSError: 1391 pass 1392 shutil.move(mydir, to_path)
1393 1394
1395 - def handlePackage(self, etpData, forcedRevision = -1, 1396 formattedContent = False):
1397 1398 self.checkReadOnly() 1399 1400 if self.clientDatabase: 1401 return self.addPackage(etpData, revision = forcedRevision, 1402 formatted_content = formattedContent) 1403 1404 # build atom string, server side 1405 pkgatom = self.entropyTools.create_package_atom_string( 1406 etpData['category'], etpData['name'], etpData['version'], 1407 etpData['versiontag']) 1408 foundid = self.isPackageAvailable(pkgatom) 1409 if foundid < 0: # same atom doesn't exist in any branch 1410 return self.addPackage(etpData, revision = forcedRevision, 1411 formatted_content = formattedContent) 1412 1413 idpackage = self.getIDPackage(pkgatom) 1414 curRevision = forcedRevision 1415 if forcedRevision == -1: 1416 curRevision = 0 1417 if idpackage != -1: 1418 curRevision = self.retrieveRevision(idpackage) 1419 1420 # remove old package atom, we do it here because othersie 1421 if idpackage != -1: 1422 # injected packages wouldn't be removed by addPackages 1423 self.removePackage(idpackage) 1424 if forcedRevision == -1: curRevision += 1 1425 1426 # add the new one 1427 return self.addPackage(etpData, revision = curRevision, 1428 formatted_content = formattedContent)
1429
1430 - def retrieve_packages_to_remove(self, name, category, slot, injected):
1431 1432 removelist = set() 1433 1434 # support for expiration-based packages handling, also internally 1435 # called Fat Scope. 1436 filter_similar = False 1437 srv_ss_plg = etpConst['system_settings_plugins_ids']['server_plugin'] 1438 srv_ss_fs_plg = \ 1439 etpConst['system_settings_plugins_ids']['server_plugin_fatscope'] 1440 1441 if not self.clientDatabase: # server-side db 1442 srv_plug_settings = self.SystemSettings.get(srv_ss_plg) 1443 if srv_plug_settings != None: 1444 if srv_plug_settings['server']['exp_based_scope']: 1445 # in case support is enabled, return an empty set 1446 filter_similar = True 1447 1448 searchsimilar = self.searchPackagesByNameAndCategory( 1449 name = name, 1450 category = category, 1451 sensitive = True 1452 ) 1453 if filter_similar: 1454 # filter out packages in the same scope that are allowed to stay 1455 idpkgs = self.SystemSettings[srv_ss_fs_plg]['repos'].get( 1456 self.server_repo) 1457 if idpkgs: 1458 if -1 in idpkgs: 1459 del searchsimilar[:] 1460 else: 1461 searchsimilar = [x for x in searchsimilar if x[1] \ 1462 not in idpkgs] 1463 1464 if not injected: 1465 # read: if package has been injected, we'll skip 1466 # the removal of packages in the same slot, 1467 # usually used server side btw 1468 for atom, idpackage in searchsimilar: 1469 # get the package slot 1470 myslot = self.retrieveSlot(idpackage) 1471 # we merely ignore packages with 1472 # negative counters, since they're the injected ones 1473 if self.isInjected(idpackage): continue 1474 if slot == myslot: 1475 # remove! 1476 removelist.add(idpackage) 1477 1478 return removelist
1479
1480 - def addPackage(self, etpData, revision = -1, idpackage = None, 1481 do_remove = True, do_commit = True, formatted_content = False):
1482 1483 self.checkReadOnly() 1484 1485 if revision == -1: 1486 try: 1487 revision = int(etpData['revision']) 1488 except (KeyError, ValueError): 1489 etpData['revision'] = 0 # revision not specified 1490 revision = 0 1491 elif not etpData.has_key('revision'): 1492 etpData['revision'] = revision 1493 1494 manual_deps = set() 1495 if do_remove: 1496 removelist = self.retrieve_packages_to_remove( 1497 etpData['name'], 1498 etpData['category'], 1499 etpData['slot'], 1500 etpData['injected'] 1501 ) 1502 for r_idpackage in removelist: 1503 manual_deps |= self.retrieveManualDependencies(r_idpackage) 1504 self.removePackage(r_idpackage, do_cleanup = False, 1505 do_commit = False) 1506 1507 # create new category if it doesn't exist 1508 catid = self.isCategoryAvailable(etpData['category']) 1509 if catid == -1: catid = self.addCategory(etpData['category']) 1510 1511 # create new license if it doesn't exist 1512 licid = self.isLicenseAvailable(etpData['license']) 1513 if licid == -1: licid = self.addLicense(etpData['license']) 1514 1515 idprotect = self.isProtectAvailable(etpData['config_protect']) 1516 if idprotect == -1: idprotect = self.addProtect( 1517 etpData['config_protect']) 1518 1519 idprotect_mask = self.isProtectAvailable( 1520 etpData['config_protect_mask']) 1521 if idprotect_mask == -1: idprotect_mask = self.addProtect( 1522 etpData['config_protect_mask']) 1523 1524 idflags = self.areCompileFlagsAvailable( 1525 etpData['chost'],etpData['cflags'],etpData['cxxflags']) 1526 if idflags == -1: idflags = self.addCompileFlags( 1527 etpData['chost'],etpData['cflags'],etpData['cxxflags']) 1528 1529 1530 trigger = 0 1531 if etpData['trigger']: 1532 trigger = 1 1533 1534 # baseinfo 1535 pkgatom = self.entropyTools.create_package_atom_string( 1536 etpData['category'], etpData['name'], etpData['version'], 1537 etpData['versiontag']) 1538 # add atom metadatum 1539 etpData['atom'] = pkgatom 1540 1541 mybaseinfo_data = (pkgatom, catid, etpData['name'], etpData['version'], 1542 etpData['versiontag'], revision, etpData['branch'], etpData['slot'], 1543 licid, etpData['etpapi'], trigger,) 1544 1545 myidpackage_string = 'NULL' 1546 if isinstance(idpackage, int): 1547 manual_deps |= self.retrieveManualDependencies(idpackage) 1548 # does it exist? 1549 self.removePackage(idpackage, do_cleanup = False, 1550 do_commit = False, do_rss = False) 1551 myidpackage_string = '?' 1552 mybaseinfo_data = (idpackage,)+mybaseinfo_data 1553 else: 1554 idpackage = None 1555 1556 # merge old manual dependencies 1557 for manual_dep in manual_deps: 1558 if manual_dep in etpData['dependencies']: continue 1559 etpData['dependencies'][manual_dep] = etpConst['spm']['mdepend_id'] 1560 1561 with self.__write_mutex: 1562 1563 self.cursor.execute(""" 1564 INSERT INTO baseinfo VALUES (%s,?,?,?,?,?,?,?,?,?,?,?)""" % ( 1565 myidpackage_string,), mybaseinfo_data) 1566 if idpackage == None: 1567 idpackage = self.cursor.lastrowid 1568 1569 # extrainfo 1570 self.cursor.execute( 1571 'INSERT INTO extrainfo VALUES (?,?,?,?,?,?,?,?)', 1572 ( idpackage, 1573 etpData['description'], 1574 etpData['homepage'], 1575 etpData['download'], 1576 etpData['size'], 1577 idflags, 1578 etpData['digest'], 1579 etpData['datecreation'], 1580 ) 1581 ) 1582 ### other information iserted below are not as critical as these above 1583 1584 # tables using a select 1585 self.insertEclasses(idpackage, etpData['eclasses']) 1586 self.insertNeeded(idpackage, etpData['needed']) 1587 self.insertDependencies(idpackage, etpData['dependencies']) 1588 self.insertSources(idpackage, etpData['sources']) 1589 self.insertUseflags(idpackage, etpData['useflags']) 1590 self.insertKeywords(idpackage, etpData['keywords']) 1591 self.insertLicenses(etpData['licensedata']) 1592 self.insertMirrors(etpData['mirrorlinks']) 1593 # package ChangeLog 1594 if etpData.get('changelog'): 1595 self.insertChangelog(etpData['category'], etpData['name'], 1596 etpData['changelog']) 1597 # package signatures 1598 if etpData.get('signatures'): 1599 self.insertSignatures(idpackage, etpData['signatures']) 1600 # needed libraries paths 1601 if etpData.get('needed_paths'): 1602 for lib in sorted(etpData['needed_paths']): 1603 self.insertNeededPaths(lib, etpData['needed_paths'][lib]) 1604 1605 # spm phases 1606 if etpData.get('spm_phases') != None: 1607 self.insertSpmPhases(idpackage, etpData['spm_phases']) 1608 1609 # not depending on other tables == no select done 1610 self.insertContent(idpackage, etpData['content'], 1611 already_formatted = formatted_content) 1612 etpData['counter'] = int(etpData['counter']) # cast to integer 1613 etpData['counter'] = self.insertPortageCounter( 1614 idpackage, 1615 etpData['counter'], 1616 etpData['branch'], 1617 etpData['injected'] 1618 ) 1619 self.insertOnDiskSize(idpackage, etpData['disksize']) 1620 if etpData['trigger']: 1621 self.insertTrigger(idpackage, etpData['trigger']) 1622 self.insertConflicts(idpackage, etpData['conflicts']) 1623 self.insertProvide(idpackage, etpData['provide']) 1624 self.insertMessages(idpackage, etpData['messages']) 1625 self.insertConfigProtect(idpackage, idprotect) 1626 self.insertConfigProtect(idpackage, idprotect_mask, mask = True) 1627 # injected? 1628 if etpData.get('injected'): 1629 self.setInjected(idpackage, do_commit = False) 1630 # is it a system package? 1631 if etpData.get('systempackage'): 1632 self.setSystemPackage(idpackage, do_commit = False) 1633 1634 self.clearCache() # we do live_cache.clear() here too 1635 if do_commit: 1636 self.commitChanges() 1637 1638 ### RSS Atom support 1639 ### dictionary will be elaborated by activator 1640 if self.SystemSettings.has_key(self.srv_sys_settings_plugin): 1641 if self.SystemSettings[self.srv_sys_settings_plugin]['server']['rss']['enabled'] and \ 1642 not self.clientDatabase: 1643 1644 self._write_rss_for_added_package(pkgatom, revision, 1645 etpData['description'], etpData['homepage']) 1646 1647 # Update category description 1648 if not self.clientDatabase: 1649 mycategory = etpData['category'] 1650 descdata = {} 1651 try: 1652 descdata = self.get_category_description_from_disk(mycategory) 1653 except (IOError, OSError, EOFError,): 1654 pass 1655 if descdata: 1656 self.setCategoryDescription(mycategory, descdata) 1657 1658 return idpackage, revision, etpData
1659
1660 - def _write_rss_for_added_package(self, pkgatom, revision, description, 1661 homepage):
1662 1663 rssAtom = pkgatom+"~"+str(revision) 1664 rssObj = self.dumpTools.loadobj(etpConst['rss-dump-name']) 1665 if rssObj: 1666 self.ServiceInterface.rssMessages = rssObj.copy() 1667 if not isinstance(self.ServiceInterface.rssMessages, dict): 1668 self.ServiceInterface.rssMessages = {} 1669 if not self.ServiceInterface.rssMessages.has_key('added'): 1670 self.ServiceInterface.rssMessages['added'] = {} 1671 if not self.ServiceInterface.rssMessages.has_key('removed'): 1672 self.ServiceInterface.rssMessages['removed'] = {} 1673 if rssAtom in self.ServiceInterface.rssMessages['removed']: 1674 del self.ServiceInterface.rssMessages['removed'][rssAtom] 1675 1676 self.ServiceInterface.rssMessages['added'][rssAtom] = {} 1677 self.ServiceInterface.rssMessages['added'][rssAtom]['description'] = \ 1678 description 1679 self.ServiceInterface.rssMessages['added'][rssAtom]['homepage'] = \ 1680 homepage 1681 self.ServiceInterface.rssMessages['light'][rssAtom] = {} 1682 self.ServiceInterface.rssMessages['light'][rssAtom]['description'] = \ 1683 description 1684 self.dumpTools.dumpobj(etpConst['rss-dump-name'], 1685 self.ServiceInterface.rssMessages)
1686
1687 - def _write_rss_for_removed_package(self, idpackage):
1688 1689 rssObj = self.dumpTools.loadobj(etpConst['rss-dump-name']) 1690 if rssObj: 1691 self.ServiceInterface.rssMessages = rssObj.copy() 1692 rssAtom = self.retrieveAtom(idpackage) 1693 rssRevision = self.retrieveRevision(idpackage) 1694 rssAtom += "~"+str(rssRevision) 1695 if not isinstance(self.ServiceInterface.rssMessages, dict): 1696 self.ServiceInterface.rssMessages = {} 1697 if not self.ServiceInterface.rssMessages.has_key('added'): 1698 self.ServiceInterface.rssMessages['added'] = {} 1699 if not self.ServiceInterface.rssMessages.has_key('removed'): 1700 self.ServiceInterface.rssMessages['removed'] = {} 1701 if rssAtom in self.ServiceInterface.rssMessages['added']: 1702 del self.ServiceInterface.rssMessages['added'][rssAtom] 1703 if rssAtom in self.ServiceInterface.rssMessages.get('light', []): 1704 del self.ServiceInterface.rssMessages['light'][rssAtom] 1705 1706 mydict = {} 1707 try: 1708 mydict['description'] = self.retrieveDescription(idpackage) 1709 except TypeError: 1710 mydict['description'] = "N/A" 1711 try: 1712 mydict['homepage'] = self.retrieveHomepage(idpackage) 1713 except TypeError: 1714 mydict['homepage'] = "" 1715 1716 self.dumpTools.dumpobj(etpConst['rss-dump-name'], 1717 self.ServiceInterface.rssMessages) 1718 1719 self.ServiceInterface.rssMessages['removed'][rssAtom] = mydict
1720
1721 - def removePackage(self, idpackage, do_cleanup = True, do_commit = True, 1722 do_rss = True):
1723 1724 self.checkReadOnly() 1725 # clear caches 1726 self.clearCache() 1727 1728 ### RSS Atom support 1729 ### dictionary will be elaborated by activator 1730 if self.SystemSettings.has_key(self.srv_sys_settings_plugin): 1731 if self.SystemSettings[self.srv_sys_settings_plugin]['server']['rss']['enabled'] and \ 1732 (not self.clientDatabase) and do_rss: 1733 1734 # store addPackage action 1735 self._write_rss_for_removed_package(idpackage) 1736 1737 with self.__write_mutex: 1738 1739 r_tup = (idpackage,)*20 1740 self.cursor.executescript(""" 1741 DELETE FROM baseinfo WHERE idpackage = %d; 1742 DELETE FROM extrainfo WHERE idpackage = %d; 1743 DELETE FROM dependencies WHERE idpackage = %d; 1744 DELETE FROM provide WHERE idpackage = %d; 1745 DELETE FROM conflicts WHERE idpackage = %d; 1746 DELETE FROM configprotect WHERE idpackage = %d; 1747 DELETE FROM configprotectmask WHERE idpackage = %d; 1748 DELETE FROM sources WHERE idpackage = %d; 1749 DELETE FROM useflags WHERE idpackage = %d; 1750 DELETE FROM keywords WHERE idpackage = %d; 1751 DELETE FROM content WHERE idpackage = %d; 1752 DELETE FROM messages WHERE idpackage = %d; 1753 DELETE FROM counters WHERE idpackage = %d; 1754 DELETE FROM sizes WHERE idpackage = %d; 1755 DELETE FROM eclasses WHERE idpackage = %d; 1756 DELETE FROM needed WHERE idpackage = %d; 1757 DELETE FROM triggers WHERE idpackage = %d; 1758 DELETE FROM systempackages WHERE idpackage = %d; 1759 DELETE FROM injected WHERE idpackage = %d; 1760 DELETE FROM installedtable WHERE idpackage = %d; 1761 """ % r_tup) 1762 1763 # not yet possible to add these calls above 1764 try: 1765 self.removeAutomergefiles(idpackage) 1766 except self.dbapi2.OperationalError: 1767 pass 1768 try: 1769 self.removeSignatures(idpackage) 1770 except self.dbapi2.OperationalError: 1771 pass 1772 try: 1773 self.removeSpmPhases(idpackage) 1774 except self.dbapi2.OperationalError: 1775 pass 1776 1777 # Remove from dependstable if exists 1778 self.removePackageFromDependsTable(idpackage) 1779 1780 if do_cleanup: 1781 # Cleanups if at least one package has been removed 1782 self.doCleanups() 1783 1784 if do_commit: 1785 self.commitChanges()
1786
1787 - def removeMirrorEntries(self, mirrorname):
1788 with self.__write_mutex: 1789 self.cursor.execute(""" 1790 DELETE FROM mirrorlinks WHERE mirrorname = (?) 1791 """,(mirrorname,))
1792
1793 - def addMirrors(self, mirrorname, mirrorlist):
1794 with self.__write_mutex: 1795 data = [(mirrorname, x,) for x in mirrorlist] 1796 self.cursor.executemany(""" 1797 INSERT into mirrorlinks VALUES (?,?) 1798 """, data)
1799
1800 - def addCategory(self, category):
1801 with self.__write_mutex: 1802 self.cursor.execute(""" 1803 INSERT into categories VALUES (NULL,?) 1804 """, (category,)) 1805 return self.cursor.lastrowid
1806
1807 - def addProtect(self, protect):
1808 with self.__write_mutex: 1809 self.cursor.execute(""" 1810 INSERT into configprotectreference VALUES (NULL,?) 1811 """, (protect,)) 1812 return self.cursor.lastrowid
1813 1814
1815 - def addSource(self, source):
1816 with self.__write_mutex: 1817 self.cursor.execute(""" 1818 INSERT into sourcesreference VALUES (NULL,?) 1819 """, (source,)) 1820 return self.cursor.lastrowid
1821
1822 - def addDependency(self, dependency):
1823 with self.__write_mutex: 1824 self.cursor.execute('INSERT into dependenciesreference VALUES (NULL,?)', (dependency,)) 1825 return self.cursor.lastrowid
1826
1827 - def addKeyword(self, keyword):
1828 with self.__write_mutex: 1829 self.cursor.execute('INSERT into keywordsreference VALUES (NULL,?)', (keyword,)) 1830 return self.cursor.lastrowid
1831
1832 - def addUseflag(self, useflag):
1833 with self.__write_mutex: 1834 self.cursor.execute('INSERT into useflagsreference VALUES (NULL,?)', (useflag,)) 1835 return self.cursor.lastrowid
1836
1837 - def addEclass(self, eclass):
1838 with self.__write_mutex: 1839 self.cursor.execute('INSERT into eclassesreference VALUES (NULL,?)', (eclass,)) 1840 return self.cursor.lastrowid
1841
1842 - def addNeeded(self, needed):
1843 with self.__write_mutex: 1844 self.cursor.execute('INSERT into neededreference VALUES (NULL,?)', (needed,)) 1845 return self.cursor.lastrowid
1846
1847 - def addLicense(self, pkglicense):
1848 if not self.entropyTools.is_valid_string(pkglicense): 1849 pkglicense = ' ' # workaround for broken license entries 1850 with self.__write_mutex: 1851 self.cursor.execute('INSERT into licenses VALUES (NULL,?)', (pkglicense,)) 1852 return self.cursor.lastrowid
1853
1854 - def addCompileFlags(self, chost, cflags, cxxflags):
1855 with self.__write_mutex: 1856 self.cursor.execute('INSERT into flags VALUES (NULL,?,?,?)', (chost,cflags,cxxflags,)) 1857 return self.cursor.lastrowid
1858
1859 - def setSystemPackage(self, idpackage, do_commit = True):
1860 with self.__write_mutex: 1861 self.cursor.execute('INSERT into systempackages VALUES (?)', (idpackage,)) 1862 if do_commit: 1863 self.commitChanges()
1864
1865 - def setInjected(self, idpackage, do_commit = True):
1866 with self.__write_mutex: 1867 if not self.isInjected(idpackage): 1868 self.cursor.execute('INSERT into injected VALUES (?)', (idpackage,)) 1869 if do_commit: 1870 self.commitChanges()
1871 1872 # date expressed the unix way
1873 - def setDateCreation(self, idpackage, date):
1874 with self.__write_mutex: 1875 self.cursor.execute('UPDATE extrainfo SET datecreation = (?) WHERE idpackage = (?)', (str(date), idpackage,)) 1876 self.commitChanges()
1877
1878 - def setDigest(self, idpackage, digest):
1879 with self.__write_mutex: 1880 self.cursor.execute('UPDATE extrainfo SET digest = (?) WHERE idpackage = (?)', (digest, idpackage,)) 1881 self.commitChanges()
1882
1883 - def setSignatures(self, idpackage, signatures):
1884 with self.__write_mutex: 1885 sha1, sha256, sha512 = signatures['sha1'], signatures['sha256'], \ 1886 signatures['sha512'] 1887 self.cursor.execute(""" 1888 UPDATE packagesignatures SET sha1 = (?), sha256 = (?), sha512 = (?) 1889 WHERE idpackage = (?) 1890 """, (sha1, sha256, sha512, idpackage))
1891
1892 - def setDownloadURL(self, idpackage, url):
1893 with self.__write_mutex: 1894 self.cursor.execute('UPDATE extrainfo SET download = (?) WHERE idpackage = (?)', (url, idpackage,)) 1895 self.commitChanges()
1896
1897 - def setCategory(self, idpackage, category):
1898 # create new category if it doesn't exist 1899 catid = self.isCategoryAvailable(category) 1900 if (catid == -1): 1901 # create category 1902 catid = self.addCategory(category) 1903 with self.__write_mutex: 1904 self.cursor.execute('UPDATE baseinfo SET idcategory = (?) WHERE idpackage = (?)', (catid, idpackage,)) 1905 self.commitChanges()
1906
1907 - def setCategoryDescription(self, category, description_data):
1908 with self.__write_mutex: 1909 self.cursor.execute('DELETE FROM categoriesdescription WHERE category = (?)', (category,)) 1910 for locale in description_data: 1911 mydesc = description_data[locale] 1912 #if type(mydesc) is unicode: 1913 # mydesc = mydesc.encode('raw_unicode_escape') 1914 self.cursor.execute('INSERT INTO categoriesdescription VALUES (?,?,?)', (category, locale, mydesc,)) 1915 self.commitChanges()
1916
1917 - def setName(self, idpackage, name):
1918 with self.__write_mutex: 1919 self.cursor.execute('UPDATE baseinfo SET name = (?) WHERE idpackage = (?)', (name, idpackage,)) 1920 self.commitChanges()
1921
1922 - def setDependency(self, iddependency, dependency):
1923 with self.__write_mutex: 1924 self.cursor.execute('UPDATE dependenciesreference SET dependency = (?) WHERE iddependency = (?)', (dependency, iddependency,)) 1925 self.commitChanges()
1926
1927 - def setAtom(self, idpackage, atom):
1928 with self.__write_mutex: 1929 self.cursor.execute('UPDATE baseinfo SET atom = (?) WHERE idpackage = (?)', (atom, idpackage,)) 1930 self.commitChanges()
1931
1932 - def setSlot(self, idpackage, slot):
1933 with self.__write_mutex: 1934 self.cursor.execute('UPDATE baseinfo SET slot = (?) WHERE idpackage = (?)', (slot, idpackage,)) 1935 self.commitChanges()
1936
1937 - def removeLicensedata(self, license_name):
1938 with self.__write_mutex: 1939 self.cursor.execute('DELETE FROM licensedata WHERE licensename = (?)', (license_name,))
1940
1941 - def removeDependencies(self, idpackage):
1942 with self.__write_mutex: 1943 self.cursor.execute("DELETE FROM dependencies WHERE idpackage = (?)", (idpackage,)) 1944 self.commitChanges()
1945
1946 - def insertDependencies(self, idpackage, depdata):
1947 1948 dcache = set() 1949 add_dep = self.addDependency 1950 is_dep_avail = self.isDependencyAvailable 1951 def mymf(dep): 1952 1953 if dep in dcache: return 0 1954 iddep = is_dep_avail(dep) 1955 if iddep == -1: iddep = add_dep(dep) 1956 1957 deptype = 0 1958 if isinstance(depdata, dict): 1959 deptype = depdata[dep] 1960 1961 dcache.add(dep) 1962 return (idpackage, iddep, deptype,)
1963 1964 # do not place inside the with statement, otherwise there'll be an obvious lockup 1965 deps = [x for x in map(mymf, depdata) if type(x) != int] 1966 with self.__write_mutex: 1967 self.cursor.executemany('INSERT into dependencies VALUES (?,?,?)', deps)
1968
1969 - def insertManualDependencies(self, idpackage, manual_deps):
1970 mydict = {} 1971 for manual_dep in manual_deps: 1972 mydict[manual_dep] = etpConst['spm']['mdepend_id'] 1973 return self.insertDependencies(idpackage, mydict)
1974
1975 - def removeContent(self, idpackage):
1976 with self.__write_mutex: 1977 self.cursor.execute("DELETE FROM content WHERE idpackage = (?)", (idpackage,)) 1978 self.commitChanges()
1979
1980 - def insertContent(self, idpackage, content, already_formatted = False):
1981 1982 with self.__write_mutex: 1983 if already_formatted: 1984 self.cursor.executemany('INSERT INTO content VALUES (?,?,?)',((idpackage, x, y,) for a, x, y in content)) 1985 return 1986 def my_cmap(xfile): 1987 return (idpackage, xfile, content[xfile],)
1988 self.cursor.executemany('INSERT INTO content VALUES (?,?,?)',map(my_cmap, content)) 1989
1990 - def insertNeededPaths(self, library, paths):
1991 with self.__write_mutex: 1992 self.cursor.executemany('INSERT OR IGNORE INTO neededlibrarypaths VALUES (?,?,?)', 1993 ((library, path, elfclass,) for path, elfclass in paths))
1994
1995 - def insertAutomergefiles(self, idpackage, automerge_data):
1996 with self.__write_mutex: 1997 self.cursor.executemany('INSERT INTO automergefiles VALUES (?,?,?)', 1998 ((idpackage, x, y,) for x, y in automerge_data))
1999
2000 - def removeAutomergefiles(self, idpackage):
2001 with self.__write_mutex: 2002 self.cursor.execute('DELETE FROM automergefiles WHERE idpackage = (?)', (idpackage,))
2003
2004 - def removeSignatures(self, idpackage):
2005 with self.__write_mutex: 2006 self.cursor.execute('DELETE FROM packagesignatures WHERE idpackage = (?)', (idpackage,))
2007
2008 - def removeSpmPhases(self, idpackage):
2009 with self.__write_mutex: 2010 self.cursor.execute('DELETE FROM packagespmphases WHERE idpackage = (?)', (idpackage,))
2011
2012 - def insertChangelog(self, category, name, changelog_txt):
2013 with self.__write_mutex: 2014 mytxt = changelog_txt.encode('raw_unicode_escape') 2015 self.cursor.execute('DELETE FROM packagechangelogs WHERE category = (?) AND name = (?)', (category, name,)) 2016 self.cursor.execute('INSERT INTO packagechangelogs VALUES (?,?,?)', (category, name, buffer(mytxt),))
2017
2018 - def removeChangelog(self, category, name):
2019 with self.__write_mutex: 2020 self.cursor.execute('DELETE FROM packagechangelogs WHERE category = (?) AND name = (?)', (category, name,))
2021
2022 - def insertLicenses(self, licenses_data):
2023 2024 mylicenses = licenses_data.keys() 2025 is_lic_avail = self.isLicensedataKeyAvailable 2026 def my_mf(mylicense): 2027 return not is_lic_avail(mylicense)
2028 2029 def my_mm(mylicense): 2030 lic_data = licenses_data.get(mylicense,'') 2031 # support both utf8 and str input 2032 if isinstance(lic_data, unicode): # encode to str 2033 try: 2034 lic_data = lic_data.encode('raw_unicode_escape') 2035 except (UnicodeDecodeError,): 2036 lic_data = lic_data.encode('utf-8') 2037 return (mylicense, buffer(lic_data), 0,) 2038 2039 with self.__write_mutex: 2040 self.cursor.executemany('INSERT into licensedata VALUES (?,?,?)',map(my_mm, list(set(filter(my_mf, mylicenses))))) 2041
2042 - def insertConfigProtect(self, idpackage, idprotect, mask = False):
2043 2044 mytable = 'configprotect' 2045 if mask: mytable += 'mask' 2046 with self.__write_mutex: 2047 self.cursor.execute('INSERT into %s VALUES (?,?)' % (mytable,), (idpackage, idprotect,))
2048
2049 - def insertMirrors(self, mirrors):
2050 2051 for mirrorname, mirrorlist in mirrors: 2052 # remove old 2053 self.removeMirrorEntries(mirrorname) 2054 # add new 2055 self.addMirrors(mirrorname, mirrorlist)
2056
2057 - def insertKeywords(self, idpackage, keywords):
2058 2059 mydata = set() 2060 for key in keywords: 2061 idkeyword = self.isKeywordAvailable(key) 2062 if (idkeyword == -1): 2063 # create category 2064 idkeyword = self.addKeyword(key) 2065 mydata.add((idpackage, idkeyword,)) 2066 2067 with self.__write_mutex: 2068 self.cursor.executemany('INSERT into keywords VALUES (?,?)', mydata)
2069
2070 - def insertUseflags(self, idpackage, useflags):
2071 2072 mydata = set() 2073 for flag in useflags: 2074 iduseflag = self.isUseflagAvailable(flag) 2075 if (iduseflag == -1): 2076 # create category 2077 iduseflag = self.addUseflag(flag) 2078 mydata.add((idpackage, iduseflag,)) 2079 2080 with self.__write_mutex: 2081 self.cursor.executemany('INSERT into useflags VALUES (?,?)', mydata)
2082
2083 - def insertSignatures(self, idpackage, signatures):
2084 with self.__write_mutex: 2085 sha1, sha256, sha512 = signatures['sha1'], signatures['sha256'], \ 2086 signatures['sha512'] 2087 self.cursor.execute(""" 2088 INSERT INTO packagesignatures VALUES (?,?,?,?) 2089 """, (idpackage, sha1, sha256, sha512))
2090
2091 - def insertSpmPhases(self, idpackage, phases):
2092 with self.__write_mutex: 2093 self.cursor.execute(""" 2094 INSERT INTO packagespmphases VALUES (?,?) 2095 """, (idpackage,phases,))
2096
2097 - def insertSources(self, idpackage, sources):
2098 2099 mydata = set() 2100 for source in sources: 2101 if (not source) or (source == "") or (not self.entropyTools.is_valid_string(source)): 2102 continue 2103 idsource = self.isSourceAvailable(source) 2104 if (idsource == -1): 2105 # create category 2106 idsource = self.addSource(source) 2107 mydata.add((idpackage, idsource,)) 2108 2109 with self.__write_mutex: 2110 self.cursor.executemany('INSERT into sources VALUES (?,?)', mydata)
2111
2112 - def insertConflicts(self, idpackage, conflicts):
2113 2114 def myiter(): 2115 for conflict in conflicts: 2116 yield (idpackage, conflict,)
2117 2118 with self.__write_mutex: 2119 self.cursor.executemany('INSERT into conflicts VALUES (?,?)', myiter()) 2120
2121 - def insertMessages(self, idpackage, messages):
2122 2123 def myiter(): 2124 for message in messages: 2125 yield (idpackage, message,)
2126 2127 with self.__write_mutex: 2128 self.cursor.executemany('INSERT into messages VALUES (?,?)', myiter()) 2129
2130 - def insertProvide(self, idpackage, provides):
2131 2132 def myiter(): 2133 for atom in provides: 2134 yield (idpackage, atom,)
2135 2136 with self.__write_mutex: 2137 self.cursor.executemany('INSERT into provide VALUES (?,?)', myiter()) 2138
2139 - def insertNeeded(self, idpackage, neededs):
2140 2141 mydata = set() 2142 for needed, elfclass in neededs: 2143 idneeded = self.isNeededAvailable(needed) 2144 if idneeded == -1: 2145 # create eclass 2146 idneeded = self.addNeeded(needed) 2147 mydata.add((idpackage, idneeded, elfclass)) 2148 2149 with self.__write_mutex: 2150 self.cursor.executemany('INSERT into needed VALUES (?,?,?)', mydata)
2151
2152 - def insertEclasses(self, idpackage, eclasses):
2153 2154 mydata = set() 2155 for eclass in eclasses: 2156 idclass = self.isEclassAvailable(eclass) 2157 if (idclass == -1): 2158 # create eclass 2159 idclass = self.addEclass(eclass) 2160 mydata.add((idpackage, idclass,)) 2161 2162 with self.__write_mutex: 2163 self.cursor.executemany('INSERT into eclasses VALUES (?,?)', mydata)
2164
2165 - def insertOnDiskSize(self, idpackage, mysize):
2166 with self.__write_mutex: 2167 self.cursor.execute('INSERT into sizes VALUES (?,?)', (idpackage, mysize,))
2168
2169 - def insertTrigger(self, idpackage, trigger):
2170 with self.__write_mutex: 2171 self.cursor.execute('INSERT into triggers VALUES (?,?)', (idpackage, buffer(trigger),))
2172
2173 - def insertBranchMigration(self, repository, from_branch, to_branch, 2174 post_migration_md5sum, post_upgrade_md5sum):
2175 with self.__write_mutex: 2176 self.cursor.execute(""" 2177 INSERT OR REPLACE INTO entropy_branch_migration VALUES (?,?,?,?,?) 2178 """, ( 2179 repository, from_branch, 2180 to_branch, post_migration_md5sum, 2181 post_upgrade_md5sum, 2182 ) 2183 )
2184
2185 - def setBranchMigrationPostUpgradeMd5sum(self, repository, from_branch, 2186 to_branch, post_upgrade_md5sum):
2187 with self.__write_mutex: 2188 self.cursor.execute(""" 2189 UPDATE entropy_branch_migration SET post_upgrade_md5sum = (?) WHERE 2190 repository = (?) AND from_branch = (?) AND to_branch = (?) 2191 """, (post_upgrade_md5sum, repository, from_branch, to_branch,))
2192 2193
2194 - def insertPortageCounter(self, idpackage, counter, branch, injected):
2195 2196 if (counter != -1) and not injected: 2197 2198 if counter <= -2: 2199 # special cases 2200 counter = self.getNewNegativeCounter() 2201 2202 with self.__write_mutex: 2203 try: 2204 self.cursor.execute( 2205 'INSERT into counters VALUES ' 2206 '(?,?,?)' 2207 , ( counter, 2208 idpackage, 2209 branch, 2210 ) 2211 ) 2212 except self.dbapi2.IntegrityError: 2213 # we have a PRIMARY KEY we need to remove 2214 self._migrateCountersTable() 2215 self.cursor.execute( 2216 'INSERT into counters VALUES ' 2217 '(?,?,?)' 2218 , ( counter, 2219 idpackage, 2220 branch, 2221 ) 2222 ) 2223 except: 2224 if self.dbname == etpConst['clientdbid']: 2225 # force only for client database 2226 if self.doesTableExist("counters"): 2227 raise 2228 self.cursor.execute( 2229 'INSERT into counters VALUES ' 2230 '(?,?,?)' 2231 , ( counter, 2232 idpackage, 2233 branch, 2234 ) 2235 ) 2236 elif self.dbname.startswith(etpConst['serverdbid']): 2237 raise 2238 2239 return counter
2240
2241 - def insertCounter(self, idpackage, counter, branch = None):
2242 if not branch: branch = self.db_branch 2243 if not branch: branch = self.SystemSettings['repositories']['branch'] 2244 with self.__write_mutex: 2245 self.cursor.execute(""" 2246 DELETE FROM counters 2247 WHERE (counter = (?) OR 2248 idpackage = (?)) AND 2249 branch = (?)""", (counter, idpackage, branch,)) 2250 self.cursor.execute('INSERT INTO counters VALUES (?,?,?)', (counter, idpackage, branch,)) 2251 self.commitChanges()
2252
2253 - def setTrashedCounter(self, counter):
2254 with self.__write_mutex: 2255 self.cursor.execute('DELETE FROM trashedcounters WHERE counter = (?)', (counter,)) 2256 self.cursor.execute('INSERT INTO trashedcounters VALUES (?)', (counter,)) 2257 self.commitChanges()
2258
2259 - def setCounter(self, idpackage, counter, branch = None):
2260 2261 branchstring = '' 2262 insertdata = [counter, idpackage] 2263 if branch: 2264 branchstring = ', branch = (?)' 2265 insertdata.insert(1, branch) 2266 2267 with self.__write_mutex: 2268 try: 2269 self.cursor.execute('UPDATE counters SET counter = (?) '+branchstring+' WHERE idpackage = (?)', insertdata) 2270 self.commitChanges() 2271 except: 2272 if self.dbname == etpConst['clientdbid']: 2273 raise
2274
2275 - def contentDiff(self, idpackage, dbconn, dbconn_idpackage):
2276 self.connection.text_factory = lambda x: unicode(x, "raw_unicode_escape") 2277 # create a random table and fill 2278 randomtable = "cdiff%s" % (self.entropyTools.get_random_number(),) 2279 while self.doesTableExist(randomtable): 2280 randomtable = "cdiff%s" % (self.entropyTools.get_random_number(),) 2281 self.cursor.execute('CREATE TEMPORARY TABLE %s ( file VARCHAR )' % (randomtable,)) 2282 2283 try: 2284 dbconn.connection.text_factory = lambda x: unicode(x, "raw_unicode_escape") 2285 dbconn.cursor.execute('select file from content where idpackage = (?)', (dbconn_idpackage,)) 2286 xfile = dbconn.cursor.fetchone() 2287 while xfile: 2288 self.cursor.execute('INSERT INTO %s VALUES (?)' % (randomtable,), (xfile[0],)) 2289 xfile = dbconn.cursor.fetchone() 2290 2291 # now compare 2292 self.cursor.execute(""" 2293 SELECT file FROM content 2294 WHERE content.idpackage = (?) AND 2295 content.file NOT IN (SELECT file from %s)""" % (randomtable,), (idpackage,)) 2296 diff = self.fetchall2set(self.cursor.fetchall()) 2297 return diff 2298 finally: 2299 self.cursor.execute('DROP TABLE IF EXISTS %s' % (randomtable,))
2300
2301 - def doCleanups(self):
2302 self.cleanupUseflags() 2303 self.cleanupSources() 2304 self.cleanupEclasses() 2305 self.cleanupNeeded() 2306 self.cleanupNeededPaths() 2307 self.cleanupDependencies() 2308 self.cleanupChangelogs()
2309
2310 - def cleanupUseflags(self):
2311 with self.__write_mutex: 2312 self.cursor.execute(""" 2313 DELETE FROM useflagsreference 2314 WHERE idflag NOT IN (SELECT idflag FROM useflags)""")
2315
2316 - def cleanupSources(self):
2317 with self.__write_mutex: 2318 self.cursor.execute(""" 2319 DELETE FROM sourcesreference 2320 WHERE idsource NOT IN (SELECT idsource FROM sources)""")
2321
2322 - def cleanupEclasses(self):
2323 with self.__write_mutex: 2324 self.cursor.execute(""" 2325 DELETE FROM eclassesreference 2326 WHERE idclass NOT IN (SELECT idclass FROM eclasses)""")
2327
2328 - def cleanupNeeded(self):
2329 with self.__write_mutex: 2330 self.cursor.execute(""" 2331 DELETE FROM neededreference 2332 WHERE idneeded NOT IN (SELECT idneeded FROM needed)""")
2333
2334 - def cleanupNeededPaths(self):
2335 with self.__write_mutex: 2336 self.cursor.execute(""" 2337 DELETE FROM neededlibrarypaths 2338 WHERE library NOT IN (SELECT library FROM neededreference)""")
2339
2340 - def cleanupDependencies(self):
2341 with self.__write_mutex: 2342 self.cursor.execute(""" 2343 DELETE FROM dependenciesreference 2344 WHERE iddependency NOT IN (SELECT iddependency FROM dependencies)""")
2345
2346 - def cleanupChangelogs(self):
2347 with self.__write_mutex: 2348 self.cursor.execute(""" 2349 DELETE FROM packagechangelogs 2350 WHERE category || "/" || name NOT IN 2351 (SELECT categories.category || "/" || baseinfo.name FROM baseinfo,categories 2352 WHERE baseinfo.idcategory = categories.idcategory 2353 )""")
2354
2355 - def getNewNegativeCounter(self):
2356 counter = -2 2357 try: 2358 self.cursor.execute('SELECT min(counter) FROM counters') 2359 dbcounter = self.cursor.fetchone() 2360 mycounter = 0 2361 if dbcounter: 2362 mycounter = dbcounter[0] 2363 2364 if mycounter >= -1: 2365 counter = -2 2366 else: 2367 counter = mycounter-1 2368 2369 except: 2370 pass 2371 return counter
2372
2373 - def getApi(self):
2374 self.cursor.execute('SELECT max(etpapi) FROM baseinfo') 2375 api = self.cursor.fetchone() 2376 if api: api = api[0] 2377 else: api = -1 2378 return api
2379
2380 - def getCategory(self, idcategory):
2381 self.cursor.execute('SELECT category from categories WHERE idcategory = (?)', (idcategory,)) 2382 cat = self.cursor.fetchone() 2383 if cat: cat = cat[0] 2384 return cat
2385
2386 - def get_category_description_from_disk(self, category):
2387 if not self.ServiceInterface: 2388 return {} 2389 return self.ServiceInterface.SpmService.get_category_description_data(category)
2390
2391 - def getIDPackage(self, atom, branch = None):
2392 branch_string = '' 2393 params = [atom] 2394 if branch: 2395 branch_string = ' AND branch = (?)' 2396 params.append(branch) 2397 self.cursor.execute('SELECT idpackage FROM baseinfo WHERE atom = (?)'+branch_string, params) 2398 idpackage = self.cursor.fetchone() 2399 if idpackage: return idpackage[0] 2400 return -1
2401
2402 - def getIDPackageFromDownload(self, download_relative_path, endswith = False):
2403 if endswith: 2404 self.cursor.execute(""" 2405 SELECT baseinfo.idpackage FROM baseinfo,extrainfo 2406 WHERE extrainfo.download LIKE (?)""", ("%"+download_relative_path,)) 2407 else: 2408 self.cursor.execute(""" 2409 SELECT baseinfo.idpackage FROM baseinfo,extrainfo 2410 WHERE extrainfo.download = (?)""", (download_relative_path,)) 2411 idpackage = self.cursor.fetchone() 2412 if idpackage: return idpackage[0] 2413 return -1
2414
2415 - def getIDPackagesFromFile(self, file):
2416 self.cursor.execute('SELECT idpackage FROM content WHERE file = (?)', (file,)) 2417 return self.fetchall2list(self.cursor.fetchall())
2418
2419 - def getIDCategory(self, category):
2420 self.cursor.execute('SELECT "idcategory" FROM categories WHERE category = (?)', (category,)) 2421 idcat = self.cursor.fetchone() 2422 if idcat: return idcat[0] 2423 return -1
2424
2425 - def getVersioningData(self, idpackage):
2426 self.cursor.execute('SELECT version,versiontag,revision FROM baseinfo WHERE idpackage = (?)', (idpackage,)) 2427 return self.cursor.fetchone()
2428
2429 - def getStrictData(self, idpackage):
2430 self.cursor.execute(""" 2431 SELECT categories.category || "/" || baseinfo.name, 2432 baseinfo.slot,baseinfo.version,baseinfo.versiontag, 2433 baseinfo.revision,baseinfo.atom FROM baseinfo,categories 2434 WHERE baseinfo.idpackage = (?) AND 2435 baseinfo.idcategory = categories.idcategory""", (idpackage,)) 2436 return self.cursor.fetchone()
2437
2438 - def getStrictScopeData(self, idpackage):
2439 self.cursor.execute(""" 2440 SELECT atom,slot,revision FROM baseinfo 2441 WHERE idpackage = (?)""", (idpackage,)) 2442 rslt = self.cursor.fetchone() 2443 return rslt
2444
2445 - def getScopeData(self, idpackage):
2446 self.cursor.execute(""" 2447 SELECT 2448 baseinfo.atom, 2449 categories.category, 2450 baseinfo.name, 2451 baseinfo.version, 2452 baseinfo.slot, 2453 baseinfo.versiontag, 2454 baseinfo.revision, 2455 baseinfo.branch, 2456 baseinfo.etpapi 2457 FROM 2458 baseinfo, 2459 categories 2460 WHERE 2461 baseinfo.idpackage = (?) 2462 and baseinfo.idcategory = categories.idcategory 2463 """, (idpackage,)) 2464 return self.cursor.fetchone()
2465
2466 - def getBaseData(self, idpackage):
2467 2468 sql = """ 2469 SELECT 2470 baseinfo.atom, 2471 baseinfo.name, 2472 baseinfo.version, 2473 baseinfo.versiontag, 2474 extrainfo.description, 2475 categories.category, 2476 flags.chost, 2477 flags.cflags, 2478 flags.cxxflags, 2479 extrainfo.homepage, 2480 licenses.license, 2481 baseinfo.branch, 2482 extrainfo.download, 2483 extrainfo.digest, 2484 baseinfo.slot, 2485 baseinfo.etpapi, 2486 extrainfo.datecreation, 2487 extrainfo.size, 2488 baseinfo.revision 2489 FROM 2490 baseinfo, 2491 extrainfo, 2492 categories, 2493 flags, 2494 licenses 2495 WHERE 2496 baseinfo.idpackage = (?) 2497 and baseinfo.idpackage = extrainfo.idpackage 2498 and baseinfo.idcategory = categories.idcategory 2499 and extrainfo.idflags = flags.idflags 2500 and baseinfo.idlicense = licenses.idlicense 2501 """ 2502 self.cursor.execute(sql, (idpackage,)) 2503 return self.cursor.fetchone()
2504
2505 - def getTriggerInfo(self, idpackage, content = True):
2506 2507 atom, category, name, \ 2508 version, slot, versiontag, \ 2509 revision, branch, etpapi = self.getScopeData(idpackage) 2510 chost, cflags, cxxflags = self.retrieveCompileFlags(idpackage) 2511 2512 pkg_content = set() 2513 if content: 2514 pkg_content = self.retrieveContent(idpackage) 2515 2516 data = { 2517 'atom': atom, 2518 'category': category, 2519 'name': name, 2520 'version': version, 2521 'versiontag': versiontag, 2522 'revision': revision, 2523 'branch': branch, 2524 'chost': chost, 2525 'cflags': cflags, 2526 'cxxflags': cxxflags, 2527 'etpapi': etpapi, 2528 'trigger': self.retrieveTrigger(idpackage), 2529 'eclasses': self.retrieveEclasses(idpackage), 2530 'content': pkg_content, 2531 'spm_phases': self.retrieveSpmPhases(idpackage), 2532 } 2533 return data
2534
2535 - def getPackageData(self, idpackage, get_content = True, 2536 content_insert_formatted = False, trigger_unicode = True):
2537 data = {} 2538 2539 try: 2540 atom, name, version, versiontag, \ 2541 description, category, chost, \ 2542 cflags, cxxflags,homepage, \ 2543 mylicense, branch, download, \ 2544 digest, slot, etpapi, \ 2545 datecreation, size, revision = self.getBaseData(idpackage) 2546 except TypeError: 2547 return None 2548 2549 content = {} 2550 if get_content: 2551 content = self.retrieveContent( 2552 idpackage, extended = True, 2553 formatted = True, insert_formatted = content_insert_formatted 2554 ) 2555 2556 sources = self.retrieveSources(idpackage) 2557 mirrornames = set() 2558 for x in sources: 2559 if x.startswith("mirror://"): 2560 mirrornames.add(x.split("/")[2]) 2561 2562 data = { 2563 'atom': atom, 2564 'name': name, 2565 'version': version, 2566 'versiontag':versiontag, 2567 'description': description, 2568 'category': category, 2569 'chost': chost, 2570 'cflags': cflags, 2571 'cxxflags': cxxflags, 2572 'homepage': homepage, 2573 'license': mylicense, 2574 'branch': branch, 2575 'download': download, 2576 'digest': digest, 2577 'slot': slot, 2578 'etpapi': etpapi, 2579 'datecreation': datecreation, 2580 'size': size, 2581 'revision': revision, 2582 # risky to add to the sql above, still 2583 'counter': self.retrieveCounter(idpackage), 2584 'messages': self.retrieveMessages(idpackage), 2585 'trigger': self.retrieveTrigger(idpackage, get_unicode = trigger_unicode), 2586 'disksize': self.retrieveOnDiskSize(idpackage), 2587 'changelog': self.retrieveChangelog(idpackage), 2588 'injected': self.isInjected(idpackage), 2589 'systempackage': self.isSystemPackage(idpackage), 2590 'config_protect': self.retrieveProtect(idpackage), 2591 'config_protect_mask': self.retrieveProtectMask(idpackage), 2592 'useflags': self.retrieveUseflags(idpackage), 2593 'keywords': self.retrieveKeywords(idpackage), 2594 'sources': sources, 2595 'eclasses': self.retrieveEclasses(idpackage), 2596 'needed': self.retrieveNeeded(idpackage, extended = True), 2597 'needed_paths': self.retrieveNeededPaths(idpackage), 2598 'provide': self.retrieveProvide(idpackage), 2599 'conflicts': self.retrieveConflicts(idpackage), 2600 'licensedata': self.retrieveLicensedata(idpackage), 2601 'content': content, 2602 'dependencies': dict((x, y,) for x, y in \ 2603 self.retrieveDependencies(idpackage, extended = True)), 2604 'mirrorlinks': [[x,self.retrieveMirrorInfo(x)] for x in mirrornames], 2605 'signatures': self.retrieveSignatures(idpackage), 2606 'spm_phases': self.retrieveSpmPhases(idpackage), 2607 } 2608 2609 return data
2610
2611 - def fetchall2set(self, item):
2612 mycontent = set() 2613 for x in item: 2614 mycontent |= set(x) 2615 return mycontent
2616
2617 - def fetchall2list(self, item):
2618 content = [] 2619 for x in item: 2620 content += list(x) 2621 return content
2622
2623 - def fetchone2list(self, item):
2624 return list(item)
2625
2626 - def fetchone2set(self, item):
2627 return set(item)
2628
2629 - def clearCache(self, depends = False):
2630 2631 self.live_cache.clear() 2632 def do_clear(name): 2633 dump_path = os.path.join(etpConst['dumpstoragedir'], name) 2634 dump_dir = os.path.dirname(dump_path) 2635 if os.path.isdir(dump_dir): 2636 for item in os.listdir(dump_dir): 2637 try: os.remove(os.path.join(dump_dir, item)) 2638 except OSError: pass
2639 2640 do_clear("%s/%s/" % (self.dbMatchCacheKey, self.dbname,)) 2641 if depends: 2642 do_clear(etpCache['depends_tree']) 2643 do_clear(etpCache['dep_tree']) 2644 do_clear(etpCache['filter_satisfied_deps']) 2645
2646 - def retrieveRepositoryUpdatesDigest(self, repository):
2647 if not self.doesTableExist("treeupdates"): 2648 return -1 2649 self.cursor.execute('SELECT digest FROM treeupdates WHERE repository = (?)', (repository,)) 2650 mydigest = self.cursor.fetchone() 2651 if mydigest: 2652 return mydigest[0] 2653 else: 2654 return -1
2655
2656 - def listAllTreeUpdatesActions(self, no_ids_repos = False):
2657 if no_ids_repos: 2658 self.cursor.execute('SELECT command,branch,date FROM treeupdatesactions') 2659 else: 2660 self.cursor.execute('SELECT * FROM treeupdatesactions') 2661 return self.cursor.fetchall()
2662
2663 - def retrieveTreeUpdatesActions(self, repository, forbranch = None):
2664 2665 if not self.doesTableExist("treeupdatesactions"): return [] 2666 if forbranch == None: forbranch = self.db_branch 2667 params = [repository] 2668 branch_string = '' 2669 if forbranch: 2670 branch_string = 'and branch = (?)' 2671 params.append(forbranch) 2672 2673 self.cursor.execute(""" 2674 SELECT command FROM treeupdatesactions WHERE 2675 repository = (?) %s order by date""" % (branch_string,), params) 2676 return self.fetchall2list(self.cursor.fetchall())
2677 2678 # mainly used to restore a previous table, used by reagent in --initialize
2679 - def bumpTreeUpdatesActions(self, updates):
2680 with self.__write_mutex: 2681 self.cursor.execute('DELETE FROM treeupdatesactions') 2682 self.cursor.executemany('INSERT INTO treeupdatesactions VALUES (?,?,?,?,?)', updates) 2683 self.commitChanges()
2684
2685 - def removeTreeUpdatesActions(self, repository):
2686 with self.__write_mutex: 2687 self.cursor.execute('DELETE FROM treeupdatesactions WHERE repository = (?)', (repository,)) 2688 self.commitChanges()
2689
2690 - def insertTreeUpdatesActions(self, updates, repository):
2691 with self.__write_mutex: 2692 myupdates = [[repository]+list(x) for x in updates] 2693 self.cursor.executemany('INSERT INTO treeupdatesactions VALUES (NULL,?,?,?,?)', myupdates) 2694 self.commitChanges()
2695
2696 - def setRepositoryUpdatesDigest(self, repository, digest):
2697 with self.__write_mutex: 2698 self.cursor.execute('DELETE FROM treeupdates where repository = (?)', (repository,)) # doing it for safety 2699 self.cursor.execute('INSERT INTO treeupdates VALUES (?,?)', (repository, digest,))
2700
2701 - def addRepositoryUpdatesActions(self, repository, actions, branch):
2702 2703 mytime = str(self.entropyTools.get_current_unix_time()) 2704 with self.__write_mutex: 2705 myupdates = [ 2706 (repository, x, branch, mytime,) for x in actions \ 2707 if not self.doesTreeupdatesActionExist(repository, x, branch) 2708 ] 2709 self.cursor.executemany('INSERT INTO treeupdatesactions VALUES (NULL,?,?,?,?)', myupdates)
2710
2711 - def doesTreeupdatesActionExist(self, repository, command, branch):
2712 self.cursor.execute(""" 2713 SELECT * FROM treeupdatesactions 2714 WHERE repository = (?) and command = (?) and branch = (?)""", (repository, command, branch,)) 2715 result = self.cursor.fetchone() 2716 if result: 2717 return True 2718 return False
2719
2720 - def clearPackageSets(self):
2721 self.cursor.execute('DELETE FROM packagesets')
2722
2723 - def insertPackageSets(self, sets_data):
2724 2725 mysets = [] 2726 for setname in sorted(sets_data.keys()): 2727 for dependency in sorted(sets_data[setname]): 2728 try: 2729 mysets.append((unicode(setname), unicode(dependency),)) 2730 except (UnicodeDecodeError, UnicodeEncodeError,): 2731 continue 2732 2733 with self.__write_mutex: 2734 self.cursor.executemany('INSERT INTO packagesets VALUES (?,?)', mysets)
2735
2736 - def retrievePackageSets(self):
2737 if not self.doesTableExist("packagesets"): return {} 2738 self.cursor.execute('SELECT setname,dependency FROM packagesets') 2739 data = self.cursor.fetchall() 2740 sets = {} 2741 for setname, dependency in data: 2742 if not sets.has_key(setname): 2743 sets[setname] = set() 2744 sets[setname].add(dependency) 2745 return sets
2746
2747 - def retrievePackageSet(self, setname):
2748 self.cursor.execute('SELECT dependency FROM packagesets WHERE setname = (?)', (setname,)) 2749 return self.fetchall2set(self.cursor.fetchall())
2750
2751 - def retrieveSystemPackages(self):
2752 self.cursor.execute('SELECT idpackage FROM systempackages') 2753 return self.fetchall2set(self.cursor.fetchall())
2754
2755 - def retrieveAtom(self, idpackage):
2756 self.cursor.execute('SELECT atom FROM baseinfo WHERE idpackage = (?)', (idpackage,)) 2757 atom = self.cursor.fetchone() 2758 if atom: return atom[0]
2759
2760 - def retrieveBranch(self, idpackage):
2761 self.cursor.execute('SELECT branch FROM baseinfo WHERE idpackage = (?)', (idpackage,)) 2762 br = self.cursor.fetchone() 2763 if br: return br[0]
2764
2765 - def retrieveTrigger(self, idpackage, get_unicode = False):
2766 self.cursor.execute('SELECT data FROM triggers WHERE idpackage = (?)', (idpackage,)) 2767 trigger = self.cursor.fetchone() 2768 if not trigger: 2769 return '' # FIXME backward compatibility with <=0.52.x 2770 if not get_unicode: 2771 return trigger[0] 2772 return unicode(trigger[0], 'raw_unicode_escape')
2773
2774 - def retrieveDownloadURL(self, idpackage):
2775 self.cursor.execute('SELECT download FROM extrainfo WHERE idpackage = (?)', (idpackage,)) 2776 download = self.cursor.fetchone() 2777 if download: return download[0]
2778
2779 - def retrieveDescription(self, idpackage):
2780 self.cursor.execute('SELECT description FROM extrainfo WHERE idpackage = (?)', (idpackage,)) 2781 description = self.cursor.fetchone() 2782 if description: return description[0]
2783
2784 - def retrieveHomepage(self, idpackage):
2785 self.cursor.execute('SELECT homepage FROM extrainfo WHERE idpackage = (?)', (idpackage,)) 2786 home = self.cursor.fetchone() 2787 if home: return home[0]
2788
2789 - def retrieveCounter(self, idpackage):
2790 self.cursor.execute(""" 2791 SELECT counters.counter FROM counters,baseinfo 2792 WHERE counters.idpackage = (?) AND 2793 baseinfo.idpackage = counters.idpackage AND 2794 baseinfo.branch = counters.branch""", (idpackage,)) 2795 mycounter = self.cursor.fetchone() 2796 if mycounter: return mycounter[0] 2797 return -1
2798
2799 - def retrieveMessages(self, idpackage):
2800 self.cursor.execute('SELECT message FROM messages WHERE idpackage = (?)', (idpackage,)) 2801 return self.fetchall2list(self.cursor.fetchall())
2802 2803 # in bytes
2804 - def retrieveSize(self, idpackage):
2805 self.cursor.execute('SELECT size FROM extrainfo WHERE idpackage = (?)', (idpackage,)) 2806 size = self.cursor.fetchone() 2807 if size: return size[0]
2808 2809 # in bytes
2810 - def retrieveOnDiskSize(self, idpackage):
2811 self.cursor.execute('SELECT size FROM sizes WHERE idpackage = (?)', (idpackage,)) 2812 size = self.cursor.fetchone() # do not use [0]! 2813 if not size: size = 0 2814 else: size = size[0] 2815 return size
2816
2817 - def retrieveDigest(self, idpackage):
2818 self.cursor.execute('SELECT digest FROM extrainfo WHERE idpackage = (?)', (idpackage,)) 2819 digest = self.cursor.fetchone() 2820 if digest: return digest[0]
2821
2822 - def retrieveSignatures(self, idpackage):
2823 mydict = { 2824 'sha1': None, 2825 'sha256': None, 2826 'sha512': None, 2827 } 2828 # FIXME: remove this check in future 2829 if self.doesTableExist('packagesignatures'): 2830 self.cursor.execute(""" 2831 SELECT sha1, sha256, sha512 FROM packagesignatures 2832 WHERE idpackage = (?)""", (idpackage,)) 2833 data = self.cursor.fetchone() 2834 if data: 2835 mydict['sha1'], mydict['sha256'], mydict['sha512'] = data 2836 return mydict
2837
2838 - def retrieveName(self, idpackage):
2839 self.cursor.execute('SELECT name FROM baseinfo WHERE idpackage = (?)', (idpackage,)) 2840 name = self.cursor.fetchone() 2841 if name: return name[0]
2842
2843 - def retrieveKeySlot(self, idpackage):
2844 self.cursor.execute(""" 2845 SELECT categories.category || "/" || baseinfo.name,baseinfo.slot FROM baseinfo,categories 2846 WHERE baseinfo.idpackage = (?) and baseinfo.idcategory = categories.idcategory""", (idpackage,)) 2847 data = self.cursor.fetchone() 2848 return data
2849
2850 - def retrieveKeySlotAggregated(self, idpackage):
2851 self.cursor.execute(""" 2852 SELECT categories.category || "/" || baseinfo.name || ":" || baseinfo.slot FROM baseinfo,categories 2853 WHERE baseinfo.idpackage = (?) and baseinfo.idcategory = categories.idcategory""", (idpackage,)) 2854 data = self.cursor.fetchone() 2855 if data: return data[0]
2856
2857 - def retrieveKeySlotTag(self, idpackage):
2858 self.cursor.execute(""" 2859 SELECT categories.category || "/" || baseinfo.name,baseinfo.slot,baseinfo.versiontag FROM baseinfo,categories 2860 WHERE baseinfo.idpackage = (?) and baseinfo.idcategory = categories.idcategory""", (idpackage,)) 2861 data = self.cursor.fetchone() 2862 return data
2863
2864 - def retrieveVersion(self, idpackage):
2865 self.cursor.execute('SELECT version FROM baseinfo WHERE idpackage = (?)', (idpackage,)) 2866 ver = self.cursor.fetchone() 2867 if ver: return ver[0]
2868
2869 - def retrieveRevision(self, idpackage):
2870 self.cursor.execute('SELECT revision FROM baseinfo WHERE idpackage = (?)', (idpackage,)) 2871 rev = self.cursor.fetchone() 2872 if rev: return rev[0]
2873
2874 - def retrieveDateCreation(self, idpackage):
2875 self.cursor.execute('SELECT datecreation FROM extrainfo WHERE idpackage = (?)', (idpackage,)) 2876 date = self.cursor.fetchone() 2877 if date: return date[0]
2878
2879 - def retrieveApi(self, idpackage):
2880 self.cursor.execute('SELECT etpapi FROM baseinfo WHERE idpackage = (?)', (idpackage,)) 2881 api = self.cursor.fetchone() 2882 if api: return api[0]
2883
2884 - def retrieveUseflags(self, idpackage):
2885 self.cursor.execute(""" 2886 SELECT flagname FROM useflags,useflagsreference 2887 WHERE useflags.idpackage = (?) AND 2888 useflags.idflag = useflagsreference.idflag""", (idpackage,)) 2889 return self.fetchall2set(self.cursor.fetchall())
2890
2891 - def retrieveEclasses(self, idpackage):
2892 self.cursor.execute(""" 2893 SELECT classname FROM eclasses,eclassesreference 2894 WHERE eclasses.idpackage = (?) AND 2895 eclasses.idclass = eclassesreference.idclass""", (idpackage,)) 2896 return self.fetchall2set(self.cursor.fetchall())
2897
2898 - def retrieveSpmPhases(self, idpackage):
2899 # FIXME: remove this check in future: 2900 if not self.doesTableExist('packagespmphases'): 2901 return None 2902 self.cursor.execute(""" 2903 SELECT phases FROM packagespmphases 2904 WHERE idpackage = (?) 2905 """, (idpackage,)) 2906 rslt = self.cursor.fetchone() 2907 if rslt: return rslt[0]
2908
2909 - def retrieveNeededRaw(self, idpackage):
2910 self.cursor.execute(""" 2911 SELECT library FROM needed,neededreference 2912 WHERE needed.idpackage = (?) AND 2913 needed.idneeded = neededreference.idneeded""", (idpackage,)) 2914 return self.fetchall2set(self.cursor.fetchall())
2915
2916 - def retrieveNeeded(self, idpackage, extended = False, format = False):
2917 2918 if extended: 2919 self.cursor.execute(""" 2920 SELECT library,elfclass FROM needed,neededreference 2921 WHERE needed.idpackage = (?) AND 2922 needed.idneeded = neededreference.idneeded order by library""", (idpackage,)) 2923 needed = self.cursor.fetchall() 2924 else: 2925 self.cursor.execute(""" 2926 SELECT library FROM needed,neededreference 2927 WHERE needed.idpackage = (?) AND 2928 needed.idneeded = neededreference.idneeded ORDER BY library""", (idpackage,)) 2929 needed = self.fetchall2list(self.cursor.fetchall()) 2930 2931 if extended and format: 2932 data = {} 2933 for lib, elfclass in needed: 2934 data[lib] = elfclass 2935 needed = data 2936 2937 return needed
2938
2939 - def retrieveNeededPaths(self, idpackage):
2940 if not self.doesTableExist('neededlibrarypaths'): 2941 return {} 2942 self.cursor.execute(""" 2943 SELECT neededlibrarypaths.library, neededlibrarypaths.path, 2944 neededlibrarypaths.elfclass FROM 2945 neededlibrarypaths, neededreference, needed WHERE 2946 needed.idpackage = (?) AND needed.idneeded = neededreference.idneeded 2947 AND neededreference.library = neededlibrarypaths.library 2948 """, (idpackage,)) 2949 data = {} 2950 for lib, path, elfclass in self.cursor.fetchall(): 2951 obj = data.setdefault(lib, set()) 2952 obj.add((path, elfclass)) 2953 return data
2954
2955 - def retrieveNeededLibraryPaths(self, needed_library_name, elfclass):
2956 if not self.doesTableExist('neededlibrarypaths'): 2957 return set() 2958 self.cursor.execute(""" 2959 SELECT path FROM neededlibrarypaths, neededreference, needed 2960 WHERE neededlibrarypaths.library = (?) AND 2961 neededlibrarypaths.elfclass = (?) AND 2962 neededreference.library = neededlibrarypaths.library AND 2963 needed.elfclass = neededlibrarypaths.elfclass AND 2964 needed.idneeded = neededreference.idneeded 2965 """, (needed_library_name, elfclass,)) 2966 return self.fetchall2set(self.cursor.fetchall())
2967
2968 - def retrieveNeededLibraryIdpackages(self):
2969 if not self.doesTableExist('neededlibraryidpackages'): 2970 return [] 2971 self.cursor.execute('SELECT idpackage, library, elfclass FROM neededlibraryidpackages') 2972 return self.cursor.fetchall()
2973
2974 - def clearNeededLibraryIdpackages(self):
2975 if not self.doesTableExist('neededlibraryidpackages'): 2976 return 2977 self.cursor.execute('DELETE FROM neededlibraryidpackages')
2978
2979 - def setNeededLibraryIdpackages(self, library_map):
2980 if not self.doesTableExist('neededlibraryidpackages'): 2981 return 2982 self.cursor.executemany('INSERT INTO neededlibraryidpackages VALUES (?,?,?)', library_map)
2983
2984 - def retrieveConflicts(self, idpackage):
2985 self.cursor.execute('SELECT conflict FROM conflicts WHERE idpackage = (?)', (idpackage,)) 2986 return self.fetchall2set(self.cursor.fetchall())
2987
2988 - def retrieveProvide(self, idpackage):
2989 self.cursor.execute('SELECT atom FROM provide WHERE idpackage = (?)', (idpackage,)) 2990 return self.fetchall2set(self.cursor.fetchall())
2991
2992 - def retrieveDependenciesList(self, idpackage):
2993 self.cursor.execute(""" 2994 SELECT dependenciesreference.dependency FROM dependencies,dependenciesreference 2995 WHERE dependencies.idpackage = (?) AND 2996 dependencies.iddependency = dependenciesreference.iddependency 2997 UNION SELECT "!" || conflict FROM conflicts 2998 WHERE idpackage = (?)""", (idpackage, idpackage,)) 2999 return self.fetchall2set(self.cursor.fetchall())
3000
3001 - def retrievePostDependencies(self, idpackage, extended = False):
3002 return self.retrieveDependencies(idpackage, extended = extended, deptype = etpConst['spm']['pdepend_id'])
3003
3004 - def retrieveManualDependencies(self, idpackage, extended = False):
3005 return self.retrieveDependencies(idpackage, extended = extended, deptype = etpConst['spm']['mdepend_id'])
3006
3007 - def retrieveDependencies(self, idpackage, extended = False, deptype = None, 3008 exclude_deptypes = None):
3009 3010 searchdata = [idpackage] 3011 3012 depstring = '' 3013 if deptype != None: 3014 depstring = ' and dependencies.type = (?)' 3015 searchdata.append(deptype) 3016 3017 excluded_deptypes_query = "" 3018 if exclude_deptypes != None: 3019 for dep_type in exclude_deptypes: 3020 excluded_deptypes_query += " AND dependencies.type != %s" % ( 3021 dep_type,) 3022 3023 if extended: 3024 self.cursor.execute(""" 3025 SELECT dependenciesreference.dependency,dependencies.type 3026 FROM dependencies,dependenciesreference 3027 WHERE dependencies.idpackage = (?) AND 3028 dependencies.iddependency = dependenciesreference.iddependency %s %s""" % ( 3029 depstring,excluded_deptypes_query,), searchdata) 3030 deps = self.cursor.fetchall() 3031 else: 3032 self.cursor.execute(""" 3033 SELECT dependenciesreference.dependency 3034 FROM dependencies,dependenciesreference 3035 WHERE dependencies.idpackage = (?) AND 3036 dependencies.iddependency = dependenciesreference.iddependency %s %s""" % ( 3037 depstring,excluded_deptypes_query,), searchdata) 3038 deps = self.fetchall2set(self.cursor.fetchall()) 3039 3040 return deps
3041
3042 - def retrieveIdDependencies(self, idpackage):
3043 self.cursor.execute('SELECT iddependency FROM dependencies WHERE idpackage = (?)', (idpackage,)) 3044 return self.fetchall2set(self.cursor.fetchall())
3045
3046 - def retrieveDependencyFromIddependency(self, iddependency):
3047 self.cursor.execute('SELECT dependency FROM dependenciesreference WHERE iddependency = (?)', (iddependency,)) 3048 dep = self.cursor.fetchone() 3049 if dep: dep = dep[0] 3050 return dep
3051
3052 - def retrieveKeywords(self, idpackage):
3053 self.cursor.execute(""" 3054 SELECT keywordname FROM keywords,keywordsreference 3055 WHERE keywords.idpackage = (?) AND 3056 keywords.idkeyword = keywordsreference.idkeyword""", (idpackage,)) 3057 return self.fetchall2set(self.cursor.fetchall())
3058
3059 - def retrieveProtect(self, idpackage):
3060 self.cursor.execute(""" 3061 SELECT protect FROM configprotect,configprotectreference 3062 WHERE configprotect.idpackage = (?) AND 3063 configprotect.idprotect = configprotectreference.idprotect""", (idpackage,)) 3064 protect = self.cursor.fetchone() 3065 if not protect: protect = '' 3066 else: protect = protect[0] 3067 return protect
3068
3069 - def retrieveProtectMask(self, idpackage):
3070 self.cursor.execute(""" 3071 SELECT protect FROM configprotectmask,configprotectreference 3072 WHERE idpackage = (?) AND 3073 configprotectmask.idprotect = configprotectreference.idprotect""", (idpackage,)) 3074 protect = self.cursor.fetchone() 3075 if not protect: protect = '' 3076 else: protect = protect[0] 3077 return protect
3078
3079 - def retrieveSources(self, idpackage, extended = False):
3080 self.cursor.execute(""" 3081 SELECT sourcesreference.source FROM sources,sourcesreference 3082 WHERE idpackage = (?) AND 3083 sources.idsource = sourcesreference.idsource""", (idpackage,)) 3084 sources = self.fetchall2set(self.cursor.fetchall()) 3085 if not extended: 3086 return sources 3087 3088 source_data = {} 3089 mirror_str = "mirror://" 3090 for source in sources: 3091 source_data[source] = set() 3092 if source.startswith(mirror_str): 3093 mirrorname = source.split("/")[2] 3094 mirror_url = source.split("/", 3)[3:][0] 3095 source_data[source] |= set([os.path.join(url, mirror_url) for url in self.retrieveMirrorInfo(mirrorname)]) 3096 else: 3097 source_data[source].add(source) 3098 3099 return source_data
3100
3101 - def retrieveAutomergefiles(self, idpackage, get_dict = False):
3102 if not self.doesTableExist('automergefiles'): 3103 self.createAutomergefilesTable() 3104 # like portage does 3105 self.connection.text_factory = lambda x: unicode(x, "raw_unicode_escape") 3106 self.cursor.execute('SELECT configfile, md5 FROM automergefiles WHERE idpackage = (?)', (idpackage,)) 3107 data = self.cursor.fetchall() 3108 if get_dict: 3109 data = dict(((x, y,) for x, y in data)) 3110 return data
3111
3112 - def retrieveContent(self, idpackage, extended = False, contentType = None, 3113 formatted = False, insert_formatted = False, order_by = ''):
3114 3115 extstring = '' 3116 if extended: 3117 extstring = ",type" 3118 extstring_idpackage = '' 3119 if insert_formatted: 3120 extstring_idpackage = 'idpackage,' 3121 3122 searchkeywords = [idpackage] 3123 contentstring = '' 3124 if contentType: 3125 searchkeywords.append(contentType) 3126 contentstring = ' and type = (?)' 3127 3128 order_by_string = '' 3129 if order_by: 3130 order_by_string = ' order by %s' % (order_by,) 3131 3132 did_try = False 3133 while 1: 3134 try: 3135 3136 self.cursor.execute('SELECT %s file%s FROM content WHERE idpackage = (?) %s%s' % ( 3137 extstring_idpackage, extstring, contentstring, order_by_string,), 3138 searchkeywords) 3139 3140 if extended and insert_formatted: 3141 fl = self.cursor.fetchall() 3142 elif extended and formatted: 3143 fl = {} 3144 items = self.cursor.fetchone() 3145 while items: 3146 fl[items[0]] = items[1] 3147 items = self.cursor.fetchone() 3148 elif extended: 3149 fl = self.cursor.fetchall() 3150 else: 3151 if order_by: 3152 fl = self.fetchall2list(self.cursor.fetchall()) 3153 else: 3154 fl = self.fetchall2set(self.cursor.fetchall()) 3155 break 3156 except (self.dbapi2.OperationalError,): 3157 if did_try: 3158 raise 3159 did_try = True 3160 # XXX support for old entropy db entries, which were 3161 # not inserted in utf-8 3162 self.connection.text_factory = lambda x: unicode(x, "raw_unicode_escape") 3163 continue 3164 return fl
3165
3166 - def retrieveChangelog(self, idpackage):
3167 if not self.doesTableExist('packagechangelogs'): 3168 return None 3169 self.cursor.execute(""" 3170 SELECT packagechangelogs.changelog FROM packagechangelogs,baseinfo,categories 3171 WHERE baseinfo.idpackage = (?) AND 3172 baseinfo.idcategory = categories.idcategory AND 3173 packagechangelogs.name = baseinfo.name AND 3174 packagechangelogs.category = categories.category""", (idpackage,)) 3175 changelog = self.cursor.fetchone() 3176 if changelog: 3177 changelog = changelog[0] 3178 try: 3179 return unicode(changelog, 'raw_unicode_escape') 3180 except UnicodeDecodeError: 3181 return unicode(changelog, 'utf-8')
3182
3183 - def retrieveChangelogByKey(self, category, name):
3184 if not self.doesTableExist('packagechangelogs'): 3185 return None 3186 self.connection.text_factory = lambda x: unicode(x, "raw_unicode_escape") 3187 self.cursor.execute('SELECT changelog FROM packagechangelogs WHERE category = (?) AND name = (?)', (category, name,)) 3188 changelog = self.cursor.fetchone() 3189 if changelog: return unicode(changelog[0], 'raw_unicode_escape')
3190
3191 - def retrieveSlot(self, idpackage):
3192 self.cursor.execute('SELECT slot FROM baseinfo WHERE idpackage = (?)', (idpackage,)) 3193 slot = self.cursor.fetchone() 3194 if slot: return slot[0]
3195
3196 - def retrieveVersionTag(self, idpackage):
3197 self.cursor.execute('SELECT versiontag FROM baseinfo WHERE idpackage = (?)', (idpackage,)) 3198 vtag = self.cursor.fetchone() 3199 if vtag: return vtag[0]
3200
3201 - def retrieveMirrorInfo(self, mirrorname):
3202 self.cursor.execute('SELECT mirrorlink FROM mirrorlinks WHERE mirrorname = (?)', (mirrorname,)) 3203 mirrorlist = self.fetchall2set(self.cursor.fetchall()) 3204 return mirrorlist
3205
3206 - def retrieveCategory(self, idpackage):
3207 self.cursor.execute(""" 3208 SELECT category FROM baseinfo,categories 3209 WHERE baseinfo.idpackage = (?) AND 3210 baseinfo.idcategory = categories.idcategory""", (idpackage,)) 3211 cat = self.cursor.fetchone() 3212 if cat: return cat[0]
3213
3214 - def retrieveCategoryDescription(self, category):
3215 data = {} 3216 self.cursor.execute('SELECT description,locale FROM categoriesdescription WHERE category = (?)', (category,)) 3217 description_data = self.cursor.fetchall() 3218 for description, locale in description_data: 3219 data[locale] = description 3220 return data
3221
3222 - def retrieveLicensedata(self, idpackage):
3223 3224 # insert license information 3225 licenses = self.retrieveLicense(idpackage) 3226 if licenses == None: 3227 return {} 3228 licenses = licenses.split() 3229 licdata = {} 3230 for licname in licenses: 3231 licname = licname.strip() 3232 if not self.entropyTools.is_valid_string(licname): 3233 continue 3234 3235 self.cursor.execute('SELECT text FROM licensedata WHERE licensename = (?)', (licname,)) 3236 lictext = self.cursor.fetchone() 3237 if lictext != None: 3238 lictext = lictext[0] 3239 try: 3240 licdata[licname] = unicode(lictext, 'raw_unicode_escape') 3241 except UnicodeDecodeError: 3242 licdata[licname] = unicode(lictext, 'utf-8') 3243 3244 return licdata
3245
3246 - def retrieveLicensedataKeys(self, idpackage):
3247 3248 licenses = self.retrieveLicense(idpackage) 3249 if licenses == None: 3250 return set() 3251 licenses = licenses.split() 3252 licdata = set() 3253 for licname in licenses: 3254 licname = licname.strip() 3255 if not self.entropyTools.is_valid_string(licname): 3256 continue 3257 self.cursor.execute('SELECT licensename FROM licensedata WHERE licensename = (?)', (licname,)) 3258 licidentifier = self.cursor.fetchone() 3259 if licidentifier: 3260 licdata.add(licidentifier[0]) 3261 3262 return licdata
3263
3264 - def retrieveLicenseText(self, license_name):
3265 3266 self.connection.text_factory = lambda x: unicode(x, "raw_unicode_escape") 3267 3268 self.cursor.execute('SELECT text FROM licensedata WHERE licensename = (?)', (license_name,)) 3269 text = self.cursor.fetchone() 3270 if not text: 3271 return None 3272 return str(text[0])
3273
3274 - def retrieveLicense(self, idpackage):
3275 self.cursor.execute(""" 3276 SELECT license FROM baseinfo,licenses 3277 WHERE baseinfo.idpackage = (?) AND 3278 baseinfo.idlicense = licenses.idlicense""", (idpackage,)) 3279 licname = self.cursor.fetchone() 3280 if licname: return licname[0]
3281
3282 - def retrieveCompileFlags(self, idpackage):
3283 self.cursor.execute(""" 3284 SELECT chost,cflags,cxxflags FROM flags,extrainfo 3285 WHERE extrainfo.idpackage = (?) AND 3286 extrainfo.idflags = flags.idflags""", (idpackage,)) 3287 flags = self.cursor.fetchone() 3288 if not flags: 3289 flags = ("N/A", "N/A", "N/A",) 3290 return flags
3291
3292 - def retrieveDepends(self, idpackage, atoms = False, key_slot = False, 3293 exclude_deptypes = None):
3294 3295 # WARNING: never remove this, otherwise equo.db 3296 # (client database) dependstable will be always broken (trust me) 3297 # sanity check on the table 3298 if not self.isDependsTableSane(): # is empty, need generation 3299 self.regenerateDependsTable(output = False) 3300 3301 excluded_deptypes_query = "" 3302 if exclude_deptypes != None: 3303 for dep_type in exclude_deptypes: 3304 excluded_deptypes_query += " AND dependencies.type != %s" % ( 3305 dep_type,) 3306 3307 if atoms: 3308 self.cursor.execute(""" 3309 SELECT baseinfo.atom FROM dependstable,dependencies,baseinfo 3310 WHERE dependstable.idpackage = (?) AND 3311 dependstable.iddependency = dependencies.iddependency AND 3312 baseinfo.idpackage = dependencies.idpackage %s""" % ( 3313 excluded_deptypes_query,), (idpackage,)) 3314 result = self.fetchall2set(self.cursor.fetchall()) 3315 elif key_slot: 3316 self.cursor.execute(""" 3317 SELECT categories.category || "/" || baseinfo.name,baseinfo.slot 3318 FROM baseinfo,categories,dependstable,dependencies 3319 WHERE dependstable.idpackage = (?) AND 3320 dependstable.iddependency = dependencies.iddependency AND 3321 baseinfo.idpackage = dependencies.idpackage AND 3322 categories.idcategory = baseinfo.idcategory %s""" % ( 3323 excluded_deptypes_query,), (idpackage,)) 3324 result = self.cursor.fetchall() 3325 else: 3326 self.cursor.execute(""" 3327 SELECT dependencies.idpackage FROM dependstable,dependencies 3328 WHERE dependstable.idpackage = (?) AND 3329 dependstable.iddependency = dependencies.iddependency %s""" % ( 3330 excluded_deptypes_query,), (idpackage,)) 3331 result = self.fetchall2set(self.cursor.fetchall()) 3332 3333 return result
3334
3335 - def retrieveUnusedIdpackages(self):
3336 3337 # WARNING: never remove this, otherwise equo.db (client database) 3338 # dependstable will be always broken (trust me) 3339 # sanity check on the table 3340 if not self.isDependsTableSane(): # is empty, need generation 3341 self.regenerateDependsTable(output = False) 3342 3343 self.cursor.execute(""" 3344 SELECT idpackage FROM baseinfo 3345 WHERE idpackage NOT IN (SELECT idpackage FROM dependstable) ORDER BY atom 3346 """) 3347 return self.fetchall2list(self.cursor.fetchall())
3348
3349 - def isPackageAvailable(self, pkgatom):
3350 # You must provide the full atom to this function 3351 # WARNING: this function does not support branches 3352 pkgatom = self.entropyTools.remove_package_operators(pkgatom) 3353 self.cursor.execute('SELECT idpackage FROM baseinfo WHERE atom = (?)', (pkgatom,)) 3354 result = self.cursor.fetchone() 3355 if result: return result[0] 3356 return -1
3357
3358 - def isIDPackageAvailable(self, idpackage):
3359 self.cursor.execute('SELECT idpackage FROM baseinfo WHERE idpackage = (?)', (idpackage,)) 3360 result = self.cursor.fetchone() 3361 if not result: 3362 return False 3363 return True
3364
3365 - def areIDPackagesAvailable(self, idpackages):
3366 sql = 'SELECT count(idpackage) FROM baseinfo WHERE idpackage IN (%s)' % (','.join([str(x) for x in set(idpackages)]),) 3367 self.cursor.execute(sql) 3368 count = self.cursor.fetchone()[0] 3369 if count != len(idpackages): 3370 return False 3371 return True
3372
3373 - def isCategoryAvailable(self, category):
3374 self.cursor.execute('SELECT idcategory FROM categories WHERE category = (?)', (category,)) 3375 result = self.cursor.fetchone() 3376 if result: return result[0] 3377 return -1
3378
3379 - def isProtectAvailable(self, protect):
3380 self.cursor.execute('SELECT idprotect FROM configprotectreference WHERE protect = (?)', (protect,)) 3381 result = self.cursor.fetchone() 3382 if result: return result[0] 3383 return -1
3384
3385 - def isFileAvailable(self, myfile, get_id = False):
3386 self.cursor.execute('SELECT idpackage FROM content WHERE file = (?)', (myfile,)) 3387 result = self.cursor.fetchall() 3388 if get_id: 3389 return self.fetchall2set(result) 3390 elif result: 3391 return True 3392 return False
3393
3394 - def resolveNeeded(self, needed, elfclass = -1, extended = False):
3395 3396 args = [needed] 3397 elfclass_txt = '' 3398 3399 if extended: 3400 if elfclass != -1: 3401 elfclass_txt = ' AND neededlibraryidpackages.elfclass = (?)' 3402 args.append(elfclass) 3403 self.cursor.execute(""" 3404 SELECT neededlibraryidpackages.idpackage, 3405 neededlibrarypaths.path 3406 FROM neededlibraryidpackages, neededlibrarypaths 3407 WHERE neededlibraryidpackages.library = (?) AND 3408 neededlibraryidpackages.library = neededlibrarypaths.library AND 3409 neededlibraryidpackages.elfclass = neededlibrarypaths.elfclass 3410 """ + elfclass_txt, args) 3411 return self.cursor.fetchall() 3412 else: 3413 if elfclass != -1: 3414 elfclass_txt = ' AND elfclass = (?)' 3415 args.append(elfclass) 3416 self.cursor.execute(""" 3417 SELECT idpackage FROM neededlibraryidpackages 3418 WHERE library = (?) 3419 """ + elfclass_txt, args) 3420 return self.fetchall2set(self.cursor.fetchall())
3421
3422 - def isSourceAvailable(self, source):
3423 self.cursor.execute('SELECT idsource FROM sourcesreference WHERE source = (?)', (source,)) 3424 result = self.cursor.fetchone() 3425 if result: return result[0] 3426 return -1
3427
3428 - def isDependencyAvailable(self, dependency):
3429 self.cursor.execute('SELECT iddependency FROM dependenciesreference WHERE dependency = (?)', (dependency,)) 3430 result = self.cursor.fetchone() 3431 if result: return result[0] 3432 return -1
3433
3434 - def isKeywordAvailable(self, keyword):
3435 self.cursor.execute('SELECT idkeyword FROM keywordsreference WHERE keywordname = (?)', (keyword,)) 3436 result = self.cursor.fetchone() 3437 if result: return result[0] 3438 return -1
3439
3440 - def isUseflagAvailable(self, useflag):
3441 self.cursor.execute('SELECT idflag FROM useflagsreference WHERE flagname = (?)', (useflag,)) 3442 result = self.cursor.fetchone() 3443 if result: return result[0] 3444 return -1
3445
3446 - def isEclassAvailable(self, eclass):
3447 self.cursor.execute('SELECT idclass FROM eclassesreference WHERE classname = (?)', (eclass,)) 3448 result = self.cursor.fetchone() 3449 if result: return result[0] 3450 return -1
3451
3452 - def isNeededAvailable(self, needed):
3453 self.cursor.execute('SELECT idneeded FROM neededreference WHERE library = (?)', (needed,)) 3454 result = self.cursor.fetchone() 3455 if result: return result[0] 3456 return -1
3457
3458 - def isCounterAvailable(self, counter, branch = None, branch_operator = "="):
3459 params = [counter] 3460 branch_string = '' 3461 if branch: 3462 branch_string = ' and branch '+branch_operator+' (?)' 3463 params = [counter, branch] 3464 3465 self.cursor.execute('SELECT counter FROM counters WHERE counter = (?)'+branch_string, params) 3466 result = self.cursor.fetchone() 3467 if result: return True 3468 return False
3469
3470 - def isCounterTrashed(self, counter):
3471 self.cursor.execute('SELECT counter FROM trashedcounters WHERE counter = (?)', (counter,)) 3472 result = self.cursor.fetchone() 3473 if result: return True 3474 return False
3475
3476 - def isLicensedataKeyAvailable(self, license_name):
3477 self.cursor.execute('SELECT licensename FROM licensedata WHERE licensename = (?)', (license_name,)) 3478 result = self.cursor.fetchone() 3479 if not result: 3480 return False 3481 return True
3482
3483 - def isLicenseAccepted(self, license_name):
3484 self.cursor.execute('SELECT licensename FROM licenses_accepted WHERE licensename = (?)', (license_name,)) 3485 result = self.cursor.fetchone() 3486 if not result: 3487 return False 3488 return True
3489
3490 - def acceptLicense(self, license_name):
3491 if self.readOnly or (not self.entropyTools.is_user_in_entropy_group()): 3492 return 3493 if self.isLicenseAccepted(license_name): 3494 return 3495 with self.__write_mutex: 3496 self.cursor.execute('INSERT INTO licenses_accepted VALUES (?)', (license_name,)) 3497 self.commitChanges()
3498
3499 - def isLicenseAvailable(self, pkglicense):
3500 if not self.entropyTools.is_valid_string(pkglicense): 3501 pkglicense = ' ' 3502 self.cursor.execute('SELECT idlicense FROM licenses WHERE license = (?)', (pkglicense,)) 3503 result = self.cursor.fetchone() 3504 if result: return result[0] 3505 return -1
3506
3507 - def isSystemPackage(self, idpackage):
3508 self.cursor.execute('SELECT idpackage FROM systempackages WHERE idpackage = (?)', (idpackage,)) 3509 result = self.cursor.fetchone() 3510 if result: 3511 return True 3512 return False
3513
3514 - def isInjected(self, idpackage):
3515 self.cursor.execute('SELECT idpackage FROM injected WHERE idpackage = (?)', (idpackage,)) 3516 result = self.cursor.fetchone() 3517 if result: 3518 return True 3519 return False
3520
3521 - def areCompileFlagsAvailable(self, chost, cflags, cxxflags):
3522 3523 self.cursor.execute('SELECT idflags FROM flags WHERE chost = (?) AND cflags = (?) AND cxxflags = (?)', 3524 (chost, cflags, cxxflags,) 3525 ) 3526 result = self.cursor.fetchone() 3527 if result: return result[0] 3528 return -1
3529
3530 - def searchBelongs(self, file, like = False, branch = None, branch_operator = "="):
3531 3532 branchstring = '' 3533 searchkeywords = [file] 3534 if branch: 3535 searchkeywords.append(branch) 3536 branchstring = ' and baseinfo.branch '+branch_operator+' (?)' 3537 3538 if like: 3539 self.cursor.execute(""" 3540 SELECT content.idpackage FROM content,baseinfo 3541 WHERE file LIKE (?) AND 3542 content.idpackage = baseinfo.idpackage %s""" % (branchstring,), searchkeywords) 3543 else: 3544 self.cursor.execute("""SELECT content.idpackage FROM content,baseinfo 3545 WHERE file = (?) AND 3546 content.idpackage = baseinfo.idpackage %s""" % (branchstring,), searchkeywords) 3547 3548 return self.fetchall2set(self.cursor.fetchall())
3549 3550 ''' search packages that uses the eclass provided '''
3551 - def searchEclassedPackages(self, eclass, atoms = False): # atoms = return atoms directly
3552 if atoms: 3553 self.cursor.execute(""" 3554 SELECT baseinfo.atom,eclasses.idpackage FROM baseinfo,eclasses,eclassesreference 3555 WHERE eclassesreference.classname = (?) AND 3556 eclassesreference.idclass = eclasses.idclass AND 3557 eclasses.idpackage = baseinfo.idpackage""", (eclass,)) 3558 return self.cursor.fetchall() 3559 else: 3560 self.cursor.execute('SELECT idpackage FROM baseinfo WHERE versiontag = (?)', (eclass,)) 3561 return self.fetchall2set(self.cursor.fetchall()) 3562 3563 ''' search packages whose versiontag matches the one provided '''
3564 - def searchTaggedPackages(self, tag, atoms = False): # atoms = return atoms directly
3565 if atoms: 3566 self.cursor.execute('SELECT atom,idpackage FROM baseinfo WHERE versiontag = (?)', (tag,)) 3567 return self.cursor.fetchall() 3568 else: 3569 self.cursor.execute('SELECT idpackage FROM baseinfo WHERE versiontag = (?)', (tag,)) 3570 return self.fetchall2set(self.cursor.fetchall()) 3571
3572 - def searchLicenses(self, mylicense, caseSensitive = False, atoms = False):
3573 3574 if not self.entropyTools.is_valid_string(mylicense): 3575 return [] 3576 3577 request = "baseinfo.idpackage" 3578 if atoms: 3579 request = "baseinfo.atom,baseinfo.idpackage" 3580 3581 if caseSensitive: 3582 self.cursor.execute(""" 3583 SELECT %s FROM baseinfo,licenses 3584 WHERE licenses.license LIKE (?) AND 3585 licenses.idlicense = baseinfo.idlicense""" % (request,), ("%"+mylicense+"%",)) 3586 else: 3587 self.cursor.execute(""" 3588 SELECT %s FROM baseinfo,licenses 3589 WHERE LOWER(licenses.license) LIKE (?) AND 3590 licenses.idlicense = baseinfo.idlicense""" % (request,), ("%"+mylicense+"%".lower(),)) 3591 if atoms: 3592 return self.cursor.fetchall() 3593 return self.fetchall2set(self.cursor.fetchall())
3594 3595 ''' search packages whose slot matches the one provided '''
3596 - def searchSlottedPackages(self, slot, atoms = False): # atoms = return atoms directly
3597 if atoms: 3598 self.cursor.execute('SELECT atom,idpackage FROM baseinfo WHERE slot = (?)', (slot,)) 3599 return self.cursor.fetchall() 3600 else: 3601 self.cursor.execute('SELECT idpackage FROM baseinfo WHERE slot = (?)', (slot,)) 3602 return self.fetchall2set(self.cursor.fetchall()) 3603
3604 - def searchKeySlot(self, key, slot, branch = None):
3605 3606 branchstring = '' 3607 cat, name = key.split("/") 3608 params = [cat, name, slot] 3609 if branch: 3610 params.append(branch) 3611 branchstring = 'and baseinfo.branch = (?)' 3612 3613 self.cursor.execute(""" 3614 SELECT idpackage FROM baseinfo,categories 3615 WHERE baseinfo.idcategory = categories.idcategory AND 3616 categories.category = (?) AND 3617 baseinfo.name = (?) AND 3618 baseinfo.slot = (?) %s""" % (branchstring,), params) 3619 return self.cursor.fetchall()
3620 3621 ''' search packages that need the specified library (in neededreference table) specified by keyword '''
3622 - def searchNeeded(self, keyword, like = False):
3623 if like: 3624 self.cursor.execute(""" 3625 SELECT needed.idpackage FROM needed,neededreference 3626 WHERE library LIKE (?) AND 3627 needed.idneeded = neededreference.idneeded""", (keyword,)) 3628 else: 3629 self.cursor.execute(""" 3630 SELECT needed.idpackage FROM needed,neededreference 3631 WHERE library = (?) AND 3632 needed.idneeded = neededreference.idneeded""", (keyword,)) 3633 return self.fetchall2set(self.cursor.fetchall())
3634 3635 ''' search dependency string inside dependenciesreference table and retrieve iddependency '''
3636 - def searchDependency(self, dep, like = False, multi = False, strings = False):
3637 sign = "=" 3638 if like: 3639 sign = "LIKE" 3640 dep = "%"+dep+"%" 3641 item = 'iddependency' 3642 if strings: 3643 item = 'dependency' 3644 self.cursor.execute('SELECT %s FROM dependenciesreference WHERE dependency %s (?)' % (item, sign,), (dep,)) 3645 if multi: 3646 return self.fetchall2set(self.cursor.fetchall()) 3647 else: 3648 iddep = self.cursor.fetchone() 3649 if iddep: 3650 iddep = iddep[0] 3651 else: 3652 iddep = -1 3653 return iddep
3654 3655 ''' search iddependency inside dependencies table and retrieve idpackages '''
3656 - def searchIdpackageFromIddependency(self, iddep):
3657 self.cursor.execute('SELECT idpackage FROM dependencies WHERE iddependency = (?)', (iddep,)) 3658 return self.fetchall2set(self.cursor.fetchall())
3659
3660 - def searchSets(self, keyword):
3661 self.cursor.execute('SELECT DISTINCT(setname) FROM packagesets WHERE setname LIKE (?)', ("%"+keyword+"%",)) 3662 return self.fetchall2set(self.cursor.fetchall())
3663
3664 - def searchSimilarPackages(self, mystring, atom = False):
3665 s_item = 'name' 3666 if atom: s_item = 'atom' 3667 self.cursor.execute(""" 3668 SELECT idpackage FROM baseinfo 3669 WHERE soundex(%s) = soundex((?)) ORDER BY %s""" % (s_item, s_item,), (mystring,)) 3670 return self.fetchall2list(self.cursor.fetchall())
3671
3672 - def searchPackages(self, keyword, sensitive = False, slot = None, tag = None, branch = None, order_by = 'atom', just_id = False):
3673 3674 searchkeywords = ["%"+keyword+"%"] 3675 slotstring = '' 3676 if slot: 3677 searchkeywords.append(slot) 3678 slotstring = ' and slot = (?)' 3679 tagstring = '' 3680 if tag: 3681 searchkeywords.append(tag) 3682 tagstring = ' and versiontag = (?)' 3683 branchstring = '' 3684 if branch: 3685 searchkeywords.append(branch) 3686 branchstring = ' and branch = (?)' 3687 order_by_string = '' 3688 if order_by in ("atom", "idpackage", "branch",): 3689 order_by_string = ' order by %s' % (order_by,) 3690 3691 search_elements = 'atom,idpackage,branch' 3692 if just_id: search_elements = 'idpackage' 3693 3694 if sensitive: 3695 self.cursor.execute(""" 3696 SELECT %s FROM baseinfo WHERE atom LIKE (?) %s %s %s %s""" % ( 3697 search_elements,slotstring,tagstring,branchstring,order_by_string,), 3698 searchkeywords 3699 ) 3700 else: 3701 self.cursor.execute(""" 3702 SELECT %s FROM baseinfo WHERE 3703 LOWER(atom) LIKE (?) %s %s %s %s""" % ( 3704 search_elements,slotstring,tagstring,branchstring,order_by_string,), 3705 searchkeywords 3706 ) 3707 if just_id: 3708 return self.fetchall2list(self.cursor.fetchall()) 3709 return self.cursor.fetchall()
3710
3711 - def searchProvide(self, keyword, slot = None, tag = None, branch = None, justid = False):
3712 3713 slotstring = '' 3714 searchkeywords = [keyword] 3715 if slot: 3716 searchkeywords.append(slot) 3717 slotstring = ' and baseinfo.slot = (?)' 3718 tagstring = '' 3719 if tag: 3720 searchkeywords.append(tag) 3721 tagstring = ' and baseinfo.versiontag = (?)' 3722 branchstring = '' 3723 if branch: 3724 searchkeywords.append(branch) 3725 branchstring = ' and baseinfo.branch = (?)' 3726 atomstring = '' 3727 if not justid: 3728 atomstring = 'baseinfo.atom,' 3729 3730 self.cursor.execute(""" 3731 SELECT %s baseinfo.idpackage FROM baseinfo,provide 3732 WHERE provide.atom = (?) AND 3733 provide.idpackage = baseinfo.idpackage %s %s %s""" % ( 3734 atomstring,slotstring,tagstring,branchstring,), 3735 searchkeywords 3736 ) 3737 3738 if justid: 3739 results = self.fetchall2list(self.cursor.fetchall()) 3740 else: 3741 results = self.cursor.fetchall() 3742 return results
3743
3744 - def searchPackagesByDescription(self, keyword):
3745 self.cursor.execute(""" 3746 SELECT baseinfo.atom,baseinfo.idpackage FROM extrainfo,baseinfo 3747 WHERE LOWER(extrainfo.description) LIKE (?) AND 3748 baseinfo.idpackage = extrainfo.idpackage""", ("%"+keyword.lower()+"%",)) 3749 return self.cursor.fetchall()
3750
3751 - def searchPackagesByName(self, keyword, sensitive = False, branch = None, justid = False):
3752 3753 if sensitive: 3754 searchkeywords = [keyword] 3755 else: 3756 searchkeywords = [keyword.lower()] 3757 branchstring = '' 3758 atomstring = '' 3759 if not justid: 3760 atomstring = 'atom,' 3761 if branch: 3762 searchkeywords.append(branch) 3763 branchstring = ' and branch = (?)' 3764 3765 if sensitive: 3766 self.cursor.execute(""" 3767 SELECT %s idpackage FROM baseinfo 3768 WHERE name = (?) %s""" % (atomstring, branchstring,), searchkeywords) 3769 else: 3770 self.cursor.execute(""" 3771 SELECT %s idpackage FROM baseinfo 3772 WHERE LOWER(name) = (?) %s""" % (atomstring, branchstring,), searchkeywords) 3773 3774 if justid: 3775 results = self.fetchall2list(self.cursor.fetchall()) 3776 else: 3777 results = self.cursor.fetchall() 3778 return results
3779 3780
3781 - def searchPackagesByCategory(self, keyword, like = False, branch = None):
3782 3783 searchkeywords = [keyword] 3784 branchstring = '' 3785 if branch: 3786 searchkeywords.append(branch) 3787 branchstring = 'and branch = (?)' 3788 3789 if like: 3790 self.cursor.execute(""" 3791 SELECT baseinfo.atom,baseinfo.idpackage FROM baseinfo,categories 3792 WHERE categories.category LIKE (?) AND 3793 baseinfo.idcategory = categories.idcategory %s""" % (branchstring,), searchkeywords) 3794 else: 3795 self.cursor.execute(""" 3796 SELECT baseinfo.atom,baseinfo.idpackage FROM baseinfo,categories 3797 WHERE categories.category = (?) AND 3798 baseinfo.idcategory = categories.idcategory %s""" % (branchstring,), searchkeywords) 3799 3800 return self.cursor.fetchall()
3801
3802 - def searchPackagesByNameAndCategory(self, name, category, sensitive = False, branch = None, justid = False):
3803 3804 myname = name 3805 mycat = category 3806 if not sensitive: 3807 myname = name.lower() 3808 mycat = category.lower() 3809 3810 searchkeywords = [myname, mycat] 3811 branchstring = '' 3812 if branch: 3813 searchkeywords.append(branch) 3814 branchstring = ' and branch = (?)' 3815 atomstring = '' 3816 if not justid: 3817 atomstring = 'atom,' 3818 3819 if sensitive: 3820 self.cursor.execute(""" 3821 SELECT %s idpackage FROM baseinfo 3822 WHERE name = (?) AND 3823 idcategory IN ( 3824 SELECT idcategory FROM categories 3825 WHERE category = (?) 3826 ) %s""" % (atomstring, branchstring,), searchkeywords) 3827 else: 3828 self.cursor.execute(""" 3829 SELECT %s idpackage FROM baseinfo 3830 WHERE LOWER(name) = (?) AND 3831 idcategory IN ( 3832 SELECT idcategory FROM categories 3833 WHERE LOWER(category) = (?) 3834 ) %s""" % (atomstring, branchstring,), searchkeywords) 3835 3836 if justid: 3837 results = self.fetchall2list(self.cursor.fetchall()) 3838 else: 3839 results = self.cursor.fetchall() 3840 return results
3841
3842 - def isPackageScopeAvailable(self, atom, slot, revision):
3843 searchdata = (atom, slot, revision,) 3844 self.cursor.execute('SELECT idpackage FROM baseinfo where atom = (?) and slot = (?) and revision = (?)', searchdata) 3845 rslt = self.cursor.fetchone() 3846 idreason = 0 3847 idpackage = -1 3848 if rslt: 3849 # check if it's masked 3850 idpackage, idreason = self.idpackageValidator(rslt[0]) 3851 return idpackage, idreason
3852
3853 - def isBranchMigrationAvailable(self, repository, from_branch, to_branch):
3854 """ 3855 Returns whether branch migration metadata given by the provided key 3856 (repository, from_branch, to_branch,) is available. 3857 3858 @param repository: repository identifier 3859 @type repository: string 3860 @param from_branch: original branch 3861 @type from_branch: string 3862 @param to_branch: destination branch 3863 @type to_branch: string 3864 @return: tuple composed by (1)post migration script md5sum and 3865 (2)post upgrade script md5sum 3866 @rtype: tuple 3867 """ 3868 self.cursor.execute(""" 3869 SELECT post_migration_md5sum, post_upgrade_md5sum 3870 FROM entropy_branch_migration 3871 WHERE repository = (?) AND from_branch = (?) AND to_branch = (?) 3872 """, (repository, from_branch, to_branch,)) 3873 return self.cursor.fetchone()
3874
3875 - def listAllPackages(self, get_scope = False, order_by = None, branch = None, branch_operator = "="):
3876 3877 branchstring = '' 3878 searchkeywords = [] 3879 if branch: 3880 searchkeywords = [branch] 3881 branchstring = ' where branch %s (?)' % (branch_operator,) 3882 3883 order_txt = '' 3884 if order_by: 3885 order_txt = ' order by %s' % (order_by,) 3886 if get_scope: 3887 self.cursor.execute('SELECT idpackage,atom,slot,revision FROM baseinfo'+order_txt+branchstring, searchkeywords) 3888 else: 3889 self.cursor.execute('SELECT atom,idpackage,branch FROM baseinfo'+order_txt+branchstring, searchkeywords) 3890 return self.cursor.fetchall()
3891
3892 - def listAllInjectedPackages(self, justFiles = False):
3893 self.cursor.execute('SELECT idpackage FROM injected') 3894 injecteds = self.fetchall2set(self.cursor.fetchall()) 3895 results = set() 3896 # get download 3897 for injected in injecteds: 3898 download = self.retrieveDownloadURL(injected) 3899 if justFiles: 3900 results.add(download) 3901 else: 3902 results.add((download, injected)) 3903 return results
3904
3905 - def listAllCounters(self, onlycounters = False, branch = None, branch_operator = "="):
3906 3907 branchstring = '' 3908 if branch: 3909 branchstring = ' WHERE branch '+branch_operator+' "'+str(branch)+'"' 3910 if onlycounters: 3911 self.cursor.execute('SELECT counter FROM counters'+branchstring) 3912 return self.fetchall2set(self.cursor.fetchall()) 3913 else: 3914 self.cursor.execute('SELECT counter,idpackage FROM counters'+branchstring) 3915 return self.cursor.fetchall()
3916
3917 - def listAllIdpackages(self, branch = None, branch_operator = "=", order_by = None):
3918 3919 branchstring = '' 3920 orderbystring = '' 3921 searchkeywords = [] 3922 if branch: 3923 searchkeywords.append(branch) 3924 branchstring = ' where branch %s (?)' % (str(branch_operator),) 3925 if order_by: 3926 orderbystring = ' order by '+order_by 3927 3928 self.cursor.execute('SELECT idpackage FROM baseinfo'+branchstring+orderbystring, searchkeywords) 3929 3930 try: 3931 if order_by: 3932 results = self.fetchall2list(self.cursor.fetchall()) 3933 else: 3934 results = self.fetchall2set(self.cursor.fetchall()) 3935 return results 3936 except self.dbapi2.OperationalError: 3937 if order_by: 3938 return [] 3939 return set()
3940
3941 - def listAllDependencies(self, only_deps = False):
3942 if only_deps: 3943 self.cursor.execute('SELECT dependency FROM dependenciesreference') 3944 return self.fetchall2set(self.cursor.fetchall()) 3945 else: 3946 self.cursor.execute('SELECT * FROM dependenciesreference') 3947 return self.cursor.fetchall()
3948
3949 - def listAllBranches(self):
3950 3951 cache = self.live_cache.get('listAllBranches') 3952 if cache != None: 3953 return cache 3954 3955 self.cursor.execute('SELECT distinct branch FROM baseinfo') 3956 results = self.fetchall2set(self.cursor.fetchall()) 3957 3958 self.live_cache['listAllBranches'] = results.copy() 3959 return results
3960
3961 - def listIdPackagesInIdcategory(self, idcategory, order_by = 'atom'):
3962 order_by_string = '' 3963 if order_by in ("atom", "name", "version",): 3964 order_by_string = ' ORDER BY %s' % (order_by,) 3965 self.cursor.execute('SELECT idpackage FROM baseinfo where idcategory = (?)'+order_by_string, (idcategory,)) 3966 return self.fetchall2set(self.cursor.fetchall())
3967
3968 - def listIdpackageDependencies(self, idpackage):
3969 self.cursor.execute(""" 3970 SELECT dependenciesreference.iddependency,dependenciesreference.dependency FROM dependenciesreference,dependencies 3971 WHERE dependencies.idpackage = (?) AND 3972 dependenciesreference.iddependency = dependencies.iddependency""", (idpackage,)) 3973 return set(self.cursor.fetchall())
3974
3975 - def listAllDownloads(self, do_sort = True, full_path = False):
3976 3977 order_string = '' 3978 if do_sort: 3979 order_string = 'ORDER BY extrainfo.download' 3980 self.cursor.execute(""" 3981 SELECT extrainfo.download FROM baseinfo,extrainfo 3982 WHERE baseinfo.idpackage = extrainfo.idpackage %s""" % (order_string,)) 3983 3984 if do_sort: 3985 results = self.fetchall2list(self.cursor.fetchall()) 3986 else: 3987 results = self.fetchall2set(self.cursor.fetchall()) 3988 3989 if not full_path: 3990 results = [os.path.basename(x) for x in results] 3991 3992 return results
3993
3994 - def listAllFiles(self, clean = False, count = False):
3995 self.connection.text_factory = lambda x: unicode(x, "raw_unicode_escape") 3996 if count: 3997 self.cursor.execute('SELECT count(file) FROM content') 3998 else: 3999 self.cursor.execute('SELECT file FROM content') 4000 if count: 4001 return self.cursor.fetchone()[0] 4002 else: 4003 if clean: 4004 return self.fetchall2set(self.cursor.fetchall()) 4005 else: 4006 return self.fetchall2list(self.cursor.fetchall())
4007
4008 - def listAllCategories(self, order_by = ''):
4009 order_by_string = '' 4010 if order_by: order_by_string = ' order by %s' % (order_by,) 4011 self.cursor.execute('SELECT idcategory,category FROM categories %s' % ( 4012 order_by_string,)) 4013 return self.cursor.fetchall()
4014
4015 - def listConfigProtectDirectories(self, mask = False):
4016 mask_t = '' 4017 if mask: mask_t = 'mask' 4018 self.cursor.execute(""" 4019 SELECT DISTINCT(protect) FROM configprotectreference 4020 WHERE idprotect >= 1 AND 4021 idprotect <= (SELECT max(idprotect) FROM configprotect%s) 4022 ORDER BY protect""" % (mask_t,)) 4023 results = self.fetchall2set(self.cursor.fetchall()) 4024 dirs = set() 4025 for mystr in results: 4026 dirs |= set(map(unicode, mystr.split())) 4027 return sorted(list(dirs))
4028
4029 - def switchBranch(self, idpackage, tobranch):
4030 with self.__write_mutex: 4031 self.cursor.execute(""" 4032 UPDATE baseinfo SET branch = (?) 4033 WHERE idpackage = (?)""", (tobranch, idpackage,)) 4034 self.commitChanges() 4035 self.clearCache() 4036
4037 - def databaseStructureUpdates(self):
4038 4039 old_readonly = self.readOnly 4040 self.readOnly = False 4041 4042 if not self.doesTableExist("licenses_accepted"): 4043 self.createLicensesAcceptedTable() 4044 4045 if not self.doesTableExist("installedtable"): 4046 self.createInstalledTable() 4047 4048 if not self.doesColumnInTableExist("installedtable", "source"): 4049 self.createInstalledTableSource() 4050 4051 if not self.doesTableExist('packagesets'): 4052 self.createPackagesetsTable() 4053 4054 if not self.doesTableExist('packagechangelogs'): 4055 self.createPackagechangelogsTable() 4056 4057 if not self.doesTableExist('automergefiles'): 4058 self.createAutomergefilesTable() 4059 4060 if not self.doesTableExist('packagesignatures'): 4061 self.createPackagesignaturesTable() 4062 4063 if not self.doesTableExist('packagespmphases'): 4064 self.createPackagespmphases() 4065 4066 if not self.doesTableExist('entropy_branch_migration'): 4067 self.createEntropyBranchMigrationTable() 4068 4069 if not self.doesTableExist('neededlibrarypaths'): 4070 self.createNeededlibrarypathsTable() 4071 if not self.doesColumnInTableExist("neededlibrarypaths", "elfclass"): 4072 self.createNeededlibrarypathsTable() 4073 4074 if not self.doesTableExist('neededlibraryidpackages'): 4075 self.createNeededlibraryidpackagesTable() 4076 elif not self.doesColumnInTableExist("neededlibraryidpackages", "elfclass"): 4077 self.createNeededlibraryidpackagesTable() 4078 4079 if not self.doesTableExist('dependstable'): 4080 self.createDependsTable() 4081 4082 self.readOnly = old_readonly 4083 self.connection.commit()
4084
4085 - def validateDatabase(self):
4086 self.cursor.execute('select name from SQLITE_MASTER where type = (?) and name = (?)', ("table", "baseinfo")) 4087 rslt = self.cursor.fetchone() 4088 if rslt == None: 4089 mytxt = _("baseinfo table not found. Either does not exist or corrupted.") 4090 raise SystemDatabaseError("SystemDatabaseError: %s" % (mytxt,)) 4091 self.cursor.execute('select name from SQLITE_MASTER where type = (?) and name = (?)', ("table", "extrainfo")) 4092 rslt = self.cursor.fetchone() 4093 if rslt == None: 4094 mytxt = _("extrainfo table not found. Either does not exist or corrupted.") 4095 raise SystemDatabaseError("SystemDatabaseError: %s" % (mytxt,))
4096
4097 - def getIdpackagesDifferences(self, foreign_idpackages):
4098 myids = self.listAllIdpackages() 4099 if isinstance(foreign_idpackages, (list, tuple,)): 4100 outids = set(foreign_idpackages) 4101 else: 4102 outids = foreign_idpackages 4103 added_ids = outids - myids 4104 removed_ids = myids - outids 4105 return added_ids, removed_ids
4106
4107 - def uniformBranch(self, branch):
4108 with self.__write_mutex: 4109 self.cursor.execute('UPDATE baseinfo SET branch = (?)', (branch,)) 4110 self.commitChanges() 4111 self.clearCache()
4112
4113 - def alignDatabases(self, dbconn, force = False, output_header = " ", align_limit = 300):
4114 4115 added_ids, removed_ids = self.getIdpackagesDifferences(dbconn.listAllIdpackages()) 4116 4117 if not force: 4118 if len(added_ids) > align_limit: # too much hassle 4119 return 0 4120 if len(removed_ids) > align_limit: # too much hassle 4121 return 0 4122 4123 if not added_ids and not removed_ids: 4124 return -1 4125 4126 mytxt = red("%s, %s ...") % (_("Syncing current database"), _("please wait"),) 4127 self.updateProgress( 4128 mytxt, 4129 importance = 1, 4130 type = "info", 4131 header = output_header, 4132 back = True 4133 ) 4134 maxcount = len(removed_ids) 4135 mycount = 0 4136 for idpackage in removed_ids: 4137 mycount += 1 4138 mytxt = "%s: %s" % (red(_("Removing entry")), blue(str(self.retrieveAtom(idpackage))),) 4139 self.updateProgress( 4140 mytxt, 4141 importance = 0, 4142 type = "info", 4143 header = output_header, 4144 back = True, 4145 count = (mycount, maxcount) 4146 ) 4147 self.removePackage(idpackage, do_cleanup = False, do_commit = False) 4148 4149 maxcount = len(added_ids) 4150 mycount = 0 4151 for idpackage in added_ids: 4152 mycount += 1 4153 mytxt = "%s: %s" % (red(_("Adding entry")), blue(str(dbconn.retrieveAtom(idpackage))),) 4154 self.updateProgress( 4155 mytxt, 4156 importance = 0, 4157 type = "info", 4158 header = output_header, 4159 back = True, 4160 count = (mycount, maxcount) 4161 ) 4162 mydata = dbconn.getPackageData(idpackage, get_content = True, content_insert_formatted = True) 4163 self.addPackage( 4164 mydata, 4165 revision = mydata['revision'], 4166 idpackage = idpackage, 4167 do_remove = False, 4168 do_commit = False, 4169 formatted_content = True 4170 ) 4171 4172 # do some cleanups 4173 self.doCleanups() 4174 # clear caches 4175 self.clearCache() 4176 self.commitChanges() 4177 self.regenerateDependsTable(output = False) 4178 dbconn.clearCache() 4179 4180 # verify both checksums, if they don't match, bomb out 4181 mycheck = self.database_checksum(do_order = True, strict = False) 4182 outcheck = dbconn.database_checksum(do_order = True, strict = False) 4183 if mycheck == outcheck: 4184 return 1 4185 return 0
4186
4187 - def checkDatabaseApi(self):
4188 4189 dbapi = self.getApi() 4190 if int(dbapi) > int(etpConst['etpapi']): 4191 self.updateProgress( 4192 red(_("Repository EAPI > Entropy EAPI. Please update Equo/Entropy as soon as possible !")), 4193 importance = 1, 4194 type = "warning", 4195 header = " * ! * ! * ! * " 4196 )
4197
4198 - def doDatabaseImport(self, dumpfile, dbfile):
4199 import subprocess 4200 sqlite3_exec = "/usr/bin/sqlite3 %s < %s" % (dbfile, dumpfile,) 4201 retcode = subprocess.call(sqlite3_exec, shell = True) 4202 return retcode
4203
4204 - def doDatabaseExport(self, dumpfile, gentle_with_tables = True, 4205 exclude_tables = None):
4206 4207 if not exclude_tables: 4208 exclude_tables = [] 4209 4210 dumpfile.write("BEGIN TRANSACTION;\n") 4211 self.cursor.execute("SELECT name, type, sql FROM sqlite_master WHERE sql NOT NULL AND type=='table'") 4212 for name, x, sql in self.cursor.fetchall(): 4213 4214 self.updateProgress( 4215 red("%s " % (_("Exporting database table"),) )+"["+blue(str(name))+"]", 4216 importance = 0, 4217 type = "info", 4218 back = True, 4219 header = " " 4220 ) 4221 4222 if name == "sqlite_sequence": 4223 dumpfile.write("DELETE FROM sqlite_sequence;\n") 4224 elif name == "sqlite_stat1": 4225 dumpfile.write("ANALYZE sqlite_master;\n") 4226 elif name.startswith("sqlite_"): 4227 continue 4228 else: 4229 t_cmd = "CREATE TABLE" 4230 if sql.startswith(t_cmd) and gentle_with_tables: 4231 sql = "CREATE TABLE IF NOT EXISTS"+sql[len(t_cmd):] 4232 dumpfile.write("%s;\n" % sql) 4233 4234 if name in exclude_tables: 4235 continue 4236 4237 self.cursor.execute("PRAGMA table_info('%s')" % name) 4238 cols = [str(r[1]) for r in self.cursor.fetchall()] 4239 q = "SELECT 'INSERT INTO \"%(tbl_name)s\" VALUES(" 4240 q += ", ".join(["'||quote(" + x + ")||'" for x in cols]) 4241 q += ")' FROM '%(tbl_name)s'" 4242 self.cursor.execute(q % {'tbl_name': name}) 4243 self.connection.text_factory = lambda x: unicode(x, "raw_unicode_escape") 4244 for row in self.cursor: 4245 dumpfile.write("%s;\n" % str(row[0].encode('raw_unicode_escape'))) 4246 4247 self.cursor.execute("SELECT name, type, sql FROM sqlite_master WHERE sql NOT NULL AND type!='table' AND type!='meta'") 4248 for name, x, sql in self.cursor.fetchall(): 4249 dumpfile.write("%s;\n" % sql) 4250 4251 dumpfile.write("COMMIT;\n") 4252 try: 4253 dumpfile.flush() 4254 except: 4255 pass 4256 self.updateProgress( 4257 red(_("Database Export completed.")), 4258 importance = 0, 4259 type = "info", 4260 header = " " 4261 )
4262 # remember to close the file 4263
4264 - def listAllTables(self):
4265 self.cursor.execute(""" 4266 SELECT name FROM SQLITE_MASTER WHERE type = "table" 4267 """) 4268 return self.fetchall2list(self.cursor.fetchall())
4269
4270 - def doesTableExist(self, table):
4271 self.cursor.execute('select name from SQLITE_MASTER where type = "table" and name = (?)', (table,)) 4272 rslt = self.cursor.fetchone() 4273 if rslt == None: 4274 return False 4275 return True
4276
4277 - def doesColumnInTableExist(self, table, column):
4278 self.cursor.execute('PRAGMA table_info( %s )' % (table,)) 4279 rslt = (x[1] for x in self.cursor.fetchall()) 4280 if column in rslt: 4281 return True 4282 return False
4283
4284 - def database_checksum(self, do_order = False, strict = True, strings = False):
4285 4286 c_tup = ("database_checksum", do_order, strict, strings,) 4287 cache = self.live_cache.get(c_tup) 4288 if cache != None: return cache 4289 4290 idpackage_order = '' 4291 category_order = '' 4292 license_order = '' 4293 flags_order = '' 4294 if do_order: 4295 idpackage_order = 'order by idpackage' 4296 category_order = 'order by category' 4297 license_order = 'order by license' 4298 flags_order = 'order by chost' 4299 4300 def do_update_md5(m, cursor): 4301 mydata = cursor.fetchall() 4302 for record in mydata: 4303 for item in record: 4304 m.update(str(item))
4305 4306 if strings: 4307 import hashlib 4308 m = hashlib.md5() 4309 4310 self.cursor.execute(""" 4311 SELECT idpackage,atom,name,version,versiontag, 4312 revision,branch,slot,etpapi,trigger FROM 4313 baseinfo %s""" % (idpackage_order,)) 4314 if strings: 4315 do_update_md5(m, self.cursor) 4316 else: 4317 a_hash = hash(tuple(self.cursor.fetchall())) 4318 self.cursor.execute(""" 4319 SELECT idpackage,description,homepage, 4320 download,size,digest,datecreation FROM 4321 extrainfo %s""" % (idpackage_order,)) 4322 if strings: 4323 do_update_md5(m, self.cursor) 4324 else: 4325 b_hash = hash(tuple(self.cursor.fetchall())) 4326 self.cursor.execute('select category from categories %s' % (category_order,)) 4327 if strings: 4328 do_update_md5(m, self.cursor) 4329 else: 4330 c_hash = hash(tuple(self.cursor.fetchall())) 4331 d_hash = '0' 4332 e_hash = '0' 4333 if strict: 4334 self.cursor.execute('select * from licenses %s' % (license_order,)) 4335 if strings: 4336 do_update_md5(m, self.cursor) 4337 else: 4338 d_hash = hash(tuple(self.cursor.fetchall())) 4339 self.cursor.execute('select * from flags %s' % (flags_order,)) 4340 if strings: 4341 do_update_md5(m, self.cursor) 4342 else: 4343 e_hash = hash(tuple(self.cursor.fetchall())) 4344 4345 if strings: 4346 result = m.hexdigest() 4347 else: 4348 result = "%s:%s:%s:%s:%s" % (a_hash, b_hash, c_hash, d_hash, e_hash,) 4349 4350 self.live_cache[c_tup] = result[:] 4351 return result 4352 4353 4354 ######################################################## 4355 #### 4356 ## Client Database API / but also used by server part 4357 # 4358
4359 - def updateInstalledTableSource(self, idpackage, source):
4360 with self.__write_mutex: 4361 self.cursor.execute(""" 4362 UPDATE installedtable SET source = (?) WHERE idpackage = (?) 4363 """, (source, idpackage,))
4364
4365 - def addPackageToInstalledTable(self, idpackage, repoid, source = 0):
4366 with self.__write_mutex: 4367 self.cursor.execute('INSERT into installedtable VALUES (?,?,?)', 4368 (idpackage, repoid, source,))
4369 # self.commitChanges() 4370
4371 - def retrievePackageFromInstalledTable(self, idpackage):
4372 with self.__write_mutex: 4373 try: 4374 self.cursor.execute(""" 4375 SELECT repositoryname FROM installedtable 4376 WHERE idpackage = (?)""", (idpackage,)) 4377 return self.cursor.fetchone()[0] 4378 except (self.dbapi2.OperationalError,TypeError,): 4379 return 'Not available'
4380
4381 - def removePackageFromInstalledTable(self, idpackage):
4382 with self.__write_mutex: 4383 self.cursor.execute(""" 4384 DELETE FROM installedtable 4385 WHERE idpackage = (?)""", (idpackage,))
4386
4387 - def removePackageFromDependsTable(self, idpackage):
4388 with self.__write_mutex: 4389 try: 4390 self.cursor.execute('DELETE FROM dependstable WHERE idpackage = (?)', (idpackage,)) 4391 return 0 4392 except (self.dbapi2.OperationalError,): 4393 return 1 # need reinit
4394
4395 - def createDependsTable(self):
4396 with self.__write_mutex: 4397 self.cursor.executescript(""" 4398 CREATE TABLE IF NOT EXISTS dependstable ( iddependency INTEGER PRIMARY KEY, idpackage INTEGER ); 4399 INSERT INTO dependstable VALUES (-1,-1); 4400 """) 4401 if self.indexing: 4402 self.cursor.execute('CREATE INDEX IF NOT EXISTS dependsindex_idpackage ON dependstable ( idpackage )') 4403 self.commitChanges()
4404
4405 - def sanitizeDependsTable(self):
4406 with self.__write_mutex: 4407 self.cursor.execute('DELETE FROM dependstable where iddependency = -1') 4408 self.commitChanges()
4409
4410 - def isDependsTableSane(self):
4411 try: 4412 self.cursor.execute('SELECT iddependency FROM dependstable WHERE iddependency = -1') 4413 except (self.dbapi2.OperationalError,): 4414 return False # table does not exist, please regenerate and re-run 4415 status = self.cursor.fetchone() 4416 if status: return False 4417 4418 self.cursor.execute('select count(*) from dependstable') 4419 dependstable_count = self.cursor.fetchone() 4420 if dependstable_count < 2: 4421 return False 4422 return True
4423
4424 - def createXpakTable(self):
4425 with self.__write_mutex: 4426 self.cursor.execute('CREATE TABLE xpakdata ( idpackage INTEGER PRIMARY KEY, data BLOB );') 4427 self.commitChanges()
4428
4429 - def storeXpakMetadata(self, idpackage, blob):
4430 with self.__write_mutex: 4431 self.cursor.execute('INSERT into xpakdata VALUES (?,?)', (int(idpackage), buffer(blob),)) 4432 self.commitChanges()
4433
4434 - def retrieveXpakMetadata(self, idpackage):
4435 try: 4436 self.cursor.execute('SELECT data from xpakdata where idpackage = (?)', (idpackage,)) 4437 mydata = self.cursor.fetchone() 4438 if not mydata: 4439 return "" 4440 return mydata[0] 4441 except: 4442 return ""
4443
4444 - def retrieveBranchMigration(self, to_branch):
4445 """ 4446 This method returns branch migration metadata stored in Entropy 4447 Client database (installed packages database). It is used to 4448 determine whether to run per-repository branch migration scripts. 4449 4450 @param to_branch: usually the current branch string 4451 @type to_branch: string 4452 @return: branch migration metadata contained in database 4453 @rtype: dict 4454 """ 4455 if not self.doesTableExist('entropy_branch_migration'): 4456 return None 4457 4458 self.cursor.execute(""" 4459 SELECT repository, from_branch, post_migration_md5sum, 4460 post_upgrade_md5sum FROM entropy_branch_migration WHERE to_branch = (?) 4461 """, (to_branch,)) 4462 4463 data = self.cursor.fetchall() 4464 meta = {} 4465 for repo, from_branch, post_migration_md5, post_upgrade_md5 in data: 4466 obj = meta.setdefault(repo, {}) 4467 obj[from_branch] = (post_migration_md5, post_upgrade_md5,) 4468 return meta
4469
4470 - def dropContent(self):
4471 with self.__write_mutex: 4472 self.cursor.execute('DELETE FROM content')
4473
4474 - def dropAllIndexes(self):
4475 self.cursor.execute('SELECT name FROM SQLITE_MASTER WHERE type = "index"') 4476 indexes = self.fetchall2set(self.cursor.fetchall()) 4477 with self.__write_mutex: 4478 for index in indexes: 4479 if not index.startswith("sqlite"): 4480 self.cursor.execute('DROP INDEX IF EXISTS %s' % (index,))
4481
4482 - def listAllIndexes(self, only_entropy = True):
4483 self.cursor.execute('SELECT name FROM SQLITE_MASTER WHERE type = "index"') 4484 indexes = self.fetchall2set(self.cursor.fetchall()) 4485 if not only_entropy: 4486 return indexes 4487 myindexes = set() 4488 for index in indexes: 4489 if index.startswith("sqlite"): 4490 continue 4491 myindexes.add(index) 4492 return myindexes
4493 4494
4495 - def createAllIndexes(self):
4496 self.createContentIndex() 4497 self.createBaseinfoIndex() 4498 self.createKeywordsIndex() 4499 self.createDependenciesIndex() 4500 self.createProvideIndex() 4501 self.createConflictsIndex() 4502 self.createExtrainfoIndex() 4503 self.createNeededIndex() 4504 self.createUseflagsIndex() 4505 self.createLicensedataIndex() 4506 self.createLicensesIndex() 4507 self.createConfigProtectReferenceIndex() 4508 self.createMessagesIndex() 4509 self.createSourcesIndex() 4510 self.createCountersIndex() 4511 self.createEclassesIndex() 4512 self.createCategoriesIndex() 4513 self.createCompileFlagsIndex() 4514 self.createPackagesetsIndex() 4515 self.createAutomergefilesIndex() 4516 self.createNeededlibrarypathsIndex() 4517 self.createNeededlibraryidpackagesIndex()
4518
4519 - def createPackagesetsIndex(self):
4520 if self.indexing: 4521 with self.__write_mutex: 4522 try: 4523 self.cursor.execute('CREATE INDEX IF NOT EXISTS packagesetsindex ON packagesets ( setname )') 4524 self.commitChanges() 4525 except self.dbapi2.OperationalError: 4526 pass
4527
4528 - def createNeededlibraryidpackagesIndex(self):
4529 if self.indexing: 4530 with self.__write_mutex: 4531 try: 4532 self.cursor.executescript(""" 4533 CREATE INDEX IF NOT EXISTS neededlibidpackages_library 4534 ON neededlibraryidpackages ( library ); 4535 CREATE INDEX IF NOT EXISTS neededlibidpackages_idpackage 4536 ON neededlibraryidpackages ( idpackage ); 4537 CREATE INDEX IF NOT EXISTS neededlibidpackages_lib_elf 4538 ON neededlibraryidpackages ( library, elfclass ); 4539 """) 4540 except self.dbapi2.OperationalError: 4541 pass
4542
4543 - def createNeededlibrarypathsIndex(self):
4544 if self.indexing: 4545 with self.__write_mutex: 4546 try: 4547 self.cursor.executescript(""" 4548 CREATE INDEX IF NOT EXISTS neededlibpaths_library 4549 ON neededlibrarypaths ( library ); 4550 CREATE INDEX IF NOT EXISTS neededlibpaths_elf 4551 ON neededlibrarypaths ( elfclass ); 4552 CREATE INDEX IF NOT EXISTS neededlibpaths_path 4553 ON neededlibrarypaths ( path ); 4554 CREATE INDEX IF NOT EXISTS neededlibpaths_library_elf 4555 ON neededlibrarypaths ( library, elfclass ); 4556 """) 4557 except self.dbapi2.OperationalError: 4558 pass
4559
4560 - def createAutomergefilesIndex(self):
4561 if self.indexing: 4562 with self.__write_mutex: 4563 try: 4564 self.cursor.executescript(""" 4565 CREATE INDEX IF NOT EXISTS automergefiles_idpackage 4566 ON automergefiles ( idpackage ); 4567 CREATE INDEX IF NOT EXISTS automergefiles_file_md5 4568 ON automergefiles ( configfile, md5 ); 4569 """) 4570 except self.dbapi2.OperationalError: 4571 pass
4572
4573 - def createNeededIndex(self):
4574 if self.indexing: 4575 with self.__write_mutex: 4576 self.cursor.executescript(""" 4577 CREATE INDEX IF NOT EXISTS neededindex ON neededreference ( library ); 4578 CREATE INDEX IF NOT EXISTS neededindex_idneeded ON needed ( idneeded ); 4579 CREATE INDEX IF NOT EXISTS neededindex_idpackage ON needed ( idpackage ); 4580 CREATE INDEX IF NOT EXISTS neededindex_elfclass ON needed ( elfclass ); 4581 """)
4582
4583 - def createMessagesIndex(self):
4584 if self.indexing: 4585 with self.__write_mutex: 4586 self.cursor.execute('CREATE INDEX IF NOT EXISTS messagesindex ON messages ( idpackage )')
4587
4588 - def createCompileFlagsIndex(self):
4589 if self.indexing: 4590 with self.__write_mutex: 4591 self.cursor.execute('CREATE INDEX IF NOT EXISTS flagsindex ON flags ( chost,cflags,cxxflags )')
4592
4593 - def createUseflagsIndex(self):
4594 if self.indexing: 4595 with self.__write_mutex: 4596 self.cursor.executescript(""" 4597 CREATE INDEX IF NOT EXISTS useflagsindex_useflags_idpackage ON useflags ( idpackage ); 4598 CREATE INDEX IF NOT EXISTS useflagsindex_useflags_idflag ON useflags ( idflag ); 4599 CREATE INDEX IF NOT EXISTS useflagsindex ON useflagsreference ( flagname ); 4600 """)
4601
4602 - def dropContentIndex(self, only_file = False):
4603 with self.__write_mutex: 4604 self.cursor.execute("DROP INDEX IF EXISTS contentindex_file") 4605 if not only_file: 4606 self.cursor.executescript("DROP INDEX IF EXISTS contentindex_couple;")
4607
4608 - def createContentIndex(self):
4609 if self.indexing: 4610 with self.__write_mutex: 4611 if self.doesTableExist("content"): 4612 self.cursor.executescript(""" 4613 CREATE INDEX IF NOT EXISTS contentindex_couple ON content ( idpackage ); 4614 CREATE INDEX IF NOT EXISTS contentindex_file ON content ( file ); 4615 """)
4616
4617 - def createConfigProtectReferenceIndex(self):
4618 if self.indexing: 4619 with self.__write_mutex: 4620 self.cursor.execute('CREATE INDEX IF NOT EXISTS configprotectreferenceindex ON configprotectreference ( protect )')
4621
4622 - def createBaseinfoIndex(self):
4623 if self.indexing: 4624 with self.__write_mutex: 4625 self.cursor.executescript(""" 4626 CREATE INDEX IF NOT EXISTS baseindex_atom ON baseinfo ( atom ); 4627 CREATE INDEX IF NOT EXISTS baseindex_branch_name ON baseinfo ( name,branch ); 4628 CREATE INDEX IF NOT EXISTS baseindex_branch_name_idcategory ON baseinfo ( name,idcategory,branch ); 4629 CREATE INDEX IF NOT EXISTS baseindex_idcategory ON baseinfo ( idcategory ); 4630 """)
4631
4632 - def createLicensedataIndex(self):
4633 if self.indexing: 4634 with self.__write_mutex: 4635 self.cursor.execute('CREATE INDEX IF NOT EXISTS licensedataindex ON licensedata ( licensename )')
4636
4637 - def createLicensesIndex(self):
4638 if self.indexing: 4639 with self.__write_mutex: 4640 self.cursor.execute('CREATE INDEX IF NOT EXISTS licensesindex ON licenses ( license )')
4641
4642 - def createCategoriesIndex(self):
4643 if self.indexing: 4644 with self.__write_mutex: 4645 self.cursor.execute('CREATE INDEX IF NOT EXISTS categoriesindex_category ON categories ( category )')
4646
4647 - def createKeywordsIndex(self):
4648 if self.indexing: 4649 with self.__write_mutex: 4650 self.cursor.executescript(""" 4651 CREATE INDEX IF NOT EXISTS keywordsreferenceindex ON keywordsreference ( keywordname ); 4652 CREATE INDEX IF NOT EXISTS keywordsindex_idpackage ON keywords ( idpackage ); 4653 CREATE INDEX IF NOT EXISTS keywordsindex_idkeyword ON keywords ( idkeyword ); 4654 """)
4655
4656 - def createDependenciesIndex(self):
4657 if self.indexing: 4658 with self.__write_mutex: 4659 self.cursor.executescript(""" 4660 CREATE INDEX IF NOT EXISTS dependenciesindex_idpackage ON dependencies ( idpackage ); 4661 CREATE INDEX IF NOT EXISTS dependenciesindex_iddependency ON dependencies ( iddependency ); 4662 CREATE INDEX IF NOT EXISTS dependenciesreferenceindex_dependency ON dependenciesreference ( dependency ); 4663 """)
4664
4665 - def createCountersIndex(self):
4666 if self.indexing: 4667 with self.__write_mutex: 4668 self.cursor.executescript(""" 4669 CREATE INDEX IF NOT EXISTS countersindex_idpackage ON counters ( idpackage ); 4670 CREATE INDEX IF NOT EXISTS countersindex_counter ON counters ( counter ); 4671 """)
4672
4673 - def createSourcesIndex(self):
4674 if self.indexing: 4675 with self.__write_mutex: 4676 self.cursor.executescript(""" 4677 CREATE INDEX IF NOT EXISTS sourcesindex_idpackage ON sources ( idpackage ); 4678 CREATE INDEX IF NOT EXISTS sourcesindex_idsource ON sources ( idsource ); 4679 CREATE INDEX IF NOT EXISTS sourcesreferenceindex_source ON sourcesreference ( source ); 4680 """)
4681
4682 - def createProvideIndex(self):
4683 if self.indexing: 4684 with self.__write_mutex: 4685 self.cursor.executescript(""" 4686 CREATE INDEX IF NOT EXISTS provideindex_idpackage ON provide ( idpackage ); 4687 CREATE INDEX IF NOT EXISTS provideindex_atom ON provide ( atom ); 4688 """)
4689
4690 - def createConflictsIndex(self):
4691 if self.indexing: 4692 with self.__write_mutex: 4693 self.cursor.executescript(""" 4694 CREATE INDEX IF NOT EXISTS conflictsindex_idpackage ON conflicts ( idpackage ); 4695 CREATE INDEX IF NOT EXISTS conflictsindex_atom ON conflicts ( conflict ); 4696 """)
4697
4698 - def createExtrainfoIndex(self):
4699 if self.indexing: 4700 with self.__write_mutex: 4701 self.cursor.execute('CREATE INDEX IF NOT EXISTS extrainfoindex ON extrainfo ( description )') 4702 self.cursor.execute('CREATE INDEX IF NOT EXISTS extrainfoindex_pkgindex ON extrainfo ( idpackage )')
4703
4704 - def createEclassesIndex(self):
4705 if self.indexing: 4706 with self.__write_mutex: 4707 self.cursor.executescript(""" 4708 CREATE INDEX IF NOT EXISTS eclassesindex_idpackage ON eclasses ( idpackage ); 4709 CREATE INDEX IF NOT EXISTS eclassesindex_idclass ON eclasses ( idclass ); 4710 CREATE INDEX IF NOT EXISTS eclassesreferenceindex_classname ON eclassesreference ( classname ); 4711 """)
4712
4713 - def regenerateCountersTable(self, vdb_path, output = False):
4714 4715 # this is necessary now, counters table should be empty 4716 self.cursor.execute("DELETE FROM counters;") 4717 # assign a counter to an idpackage 4718 myids = self.listAllIdpackages() 4719 counter_path = etpConst['spm']['xpak_entries']['counter'] 4720 for myid in myids: 4721 # get atom 4722 myatom = self.retrieveAtom(myid) 4723 mybranch = self.retrieveBranch(myid) 4724 myatom = self.entropyTools.remove_tag(myatom) 4725 myatomcounterpath = "%s%s/%s" % (vdb_path, myatom, counter_path,) 4726 if os.path.isfile(myatomcounterpath): 4727 try: 4728 with open(myatomcounterpath, "r") as f: 4729 counter = int(f.readline().strip()) 4730 except: 4731 if output: 4732 mytxt = "%s: %s: %s" % ( 4733 bold(_("ATTENTION")), 4734 red(_("cannot open Spm counter file for")), 4735 bold(myatom), 4736 ) 4737 self.updateProgress( 4738 mytxt, 4739 importance = 1, 4740 type = "warning" 4741 ) 4742 continue 4743 # insert id+counter 4744 with self.__write_mutex: 4745 try: 4746 self.cursor.execute( 4747 'INSERT into counters VALUES ' 4748 '(?,?,?)', ( counter, myid, mybranch ) 4749 ) 4750 except self.dbapi2.IntegrityError: 4751 if output: 4752 mytxt = "%s: %s: %s" % ( 4753 bold(_("ATTENTION")), 4754 red(_("counter for atom is duplicated, ignoring")), 4755 bold(myatom), 4756 ) 4757 self.updateProgress( 4758 mytxt, 4759 importance = 1, 4760 type = "warning" 4761 ) 4762 continue 4763 # don't trust counters, they might not be unique 4764 4765 self.commitChanges()
4766
4767 - def clearTreeupdatesEntries(self, repository):
4768 if not self.doesTableExist("treeupdates"): 4769 self.createTreeupdatesTable() 4770 # treeupdates 4771 with self.__write_mutex: 4772 self.cursor.execute("DELETE FROM treeupdates WHERE repository = (?)", (repository,)) 4773 self.commitChanges()
4774
4775 - def resetTreeupdatesDigests(self):
4776 with self.__write_mutex: 4777 self.cursor.execute('UPDATE treeupdates SET digest = "-1"') 4778 self.commitChanges()
4779
4780 - def migrateCountersTable(self):
4781 with self.__write_mutex: 4782 self._migrateCountersTable()
4783
4784 - def _migrateCountersTable(self):
4785 self.cursor.executescript(""" 4786 DROP TABLE IF EXISTS counterstemp; 4787 CREATE TABLE counterstemp ( 4788 counter INTEGER, idpackage INTEGER, branch VARCHAR, 4789 PRIMARY KEY(idpackage,branch) 4790 ); 4791 INSERT INTO counterstemp (counter, idpackage, branch) 4792 SELECT counter, idpackage, branch FROM counters; 4793 DROP TABLE counters; 4794 ALTER TABLE counterstemp RENAME TO counters; 4795 """) 4796 self.commitChanges()
4797
4798 - def createNeededlibrarypathsTable(self):
4799 with self.__write_mutex: 4800 self.cursor.executescript(""" 4801 DROP TABLE IF EXISTS neededlibrarypaths; 4802 CREATE TABLE neededlibrarypaths ( 4803 library VARCHAR, 4804 path VARCHAR, 4805 elfclass INTEGER, 4806 PRIMARY KEY(library, path, elfclass) 4807 ); 4808 """)
4809
4810 - def createNeededlibraryidpackagesTable(self):
4811 with self.__write_mutex: 4812 self.cursor.executescript(""" 4813 DROP TABLE IF EXISTS neededlibraryidpackages; 4814 CREATE TABLE neededlibraryidpackages ( 4815 idpackage INTEGER, 4816 library VARCHAR, 4817 elfclass INTEGER 4818 ); 4819 """)
4820
4821 - def createInstalledTableSource(self):
4822 with self.__write_mutex: 4823 self.cursor.execute('ALTER TABLE installedtable ADD source INTEGER;') 4824 self.cursor.execute(""" 4825 UPDATE installedtable SET source = (?) 4826 """, (etpConst['install_sources']['unknown'],))
4827
4828 - def createPackagechangelogsTable(self):
4829 with self.__write_mutex: 4830 self.cursor.execute('CREATE TABLE packagechangelogs ( category VARCHAR, name VARCHAR, changelog BLOB, PRIMARY KEY (category, name));')
4831
4832 - def createAutomergefilesTable(self):
4833 with self.__write_mutex: 4834 self.cursor.execute('CREATE TABLE automergefiles ( idpackage INTEGER, configfile VARCHAR, md5 VARCHAR );')
4835
4836 - def createPackagesignaturesTable(self):
4837 with self.__write_mutex: 4838 self.cursor.execute('CREATE TABLE packagesignatures ( idpackage INTEGER PRIMARY KEY, sha1 VARCHAR, sha256 VARCHAR, sha512 VARCHAR );')
4839
4840 - def createPackagespmphases(self):
4841 with self.__write_mutex: 4842 self.cursor.execute(""" 4843 CREATE TABLE packagespmphases ( 4844 idpackage INTEGER PRIMARY KEY, 4845 phases VARCHAR 4846 ); 4847 """)
4848
4849 - def createEntropyBranchMigrationTable(self):
4850 with self.__write_mutex: 4851 self.cursor.execute(""" 4852 CREATE TABLE entropy_branch_migration ( 4853 repository VARCHAR, 4854 from_branch VARCHAR, 4855 to_branch VARCHAR, 4856 post_migration_md5sum VARCHAR, 4857 post_upgrade_md5sum VARCHAR, 4858 PRIMARY KEY (repository, from_branch, to_branch) 4859 ); 4860 """)
4861
4862 - def createPackagesetsTable(self):
4863 with self.__write_mutex: 4864 self.cursor.execute('CREATE TABLE packagesets ( setname VARCHAR, dependency VARCHAR );')
4865
4866 - def createCategoriesdescriptionTable(self):
4867 with self.__write_mutex: 4868 self.cursor.execute('CREATE TABLE categoriesdescription ( category VARCHAR, locale VARCHAR, description VARCHAR );')
4869
4870 - def createTreeupdatesTable(self):
4871 with self.__write_mutex: 4872 self.cursor.execute('CREATE TABLE treeupdates ( repository VARCHAR PRIMARY KEY, digest VARCHAR );')
4873
4874 - def createLicensedataTable(self):
4875 with self.__write_mutex: 4876 self.cursor.execute('CREATE TABLE licensedata ( licensename VARCHAR UNIQUE, text BLOB, compressed INTEGER );')
4877
4878 - def createLicensesAcceptedTable(self):
4879 with self.__write_mutex: 4880 self.cursor.execute('CREATE TABLE licenses_accepted ( licensename VARCHAR UNIQUE );')
4881
4882 - def createInstalledTable(self):
4883 with self.__write_mutex: 4884 self.cursor.execute('DROP TABLE IF EXISTS installedtable;') 4885 self.cursor.execute('CREATE TABLE installedtable ( idpackage INTEGER PRIMARY KEY, repositoryname VARCHAR, source INTEGER );')
4886
4887 - def addDependsRelationToDependsTable(self, iterable):
4888 with self.__write_mutex: 4889 self.cursor.executemany('INSERT into dependstable VALUES (?,?)', iterable) 4890 if (self.entropyTools.is_user_in_entropy_group()) and \ 4891 (self.dbname.startswith(etpConst['serverdbid'])): 4892 # force commit even if readonly, this will allow to automagically fix dependstable server side 4893 self.connection.commit() # we don't care much about syncing the database since it's quite trivial
4894
4895 - def clearDependsTable(self):
4896 if not self.doesTableExist("dependstable"): 4897 return 4898 self.cursor.executescript(""" 4899 DELETE FROM dependstable; 4900 INSERT INTO dependstable VALUES (-1,-1); 4901 """)
4902
4903 - def regenerateDependsTable(self, output = True):
4904 4905 depends = self.listAllDependencies() 4906 count = 0 4907 total = len(depends) 4908 mydata = set() 4909 am = self.atomMatch 4910 up = self.updateProgress 4911 self.clearDependsTable() 4912 for iddep, atom in depends: 4913 count += 1 4914 4915 if output and ((count == 0) or (count % 150 == 0) or \ 4916 (count == total)): 4917 up( red("Resolving %s") % (atom,), importance = 0, 4918 type = "info", back = True, count = (count, total) 4919 ) 4920 4921 idpackage, rc = am(atom) 4922 if idpackage == -1: 4923 continue 4924 mydata.add((iddep, idpackage)) 4925 4926 if mydata: 4927 self.addDependsRelationToDependsTable(mydata) 4928 4929 # now validate dependstable 4930 self.sanitizeDependsTable()
4931
4932 - def regenerateLibrarypathsidpackageTable(self, output = True):
4933 4934 if output: 4935 self.updateProgress( 4936 "%s ..." % ( 4937 purple(_("Resolving libraries, please wait")), 4938 ), 4939 importance = 0, type = "info", back = True 4940 ) 4941 self.cursor.executescript(""" 4942 DELETE FROM neededlibraryidpackages; 4943 INSERT INTO neededlibraryidpackages (idpackage, library, elfclass) 4944 SELECT 4945 baseinfo.idpackage as idpackage, 4946 neededreference.library as library, 4947 neededlibrarypaths.elfclass as elfclass 4948 FROM 4949 baseinfo, neededlibrarypaths, needed, neededreference, content 4950 WHERE 4951 neededreference.idneeded = needed.idneeded AND 4952 needed.idpackage = content.idpackage AND 4953 baseinfo.idpackage = needed.idpackage AND 4954 neededlibrarypaths.library = neededreference.library AND 4955 neededlibrarypaths.elfclass = needed.elfclass AND 4956 content.file = neededlibrarypaths.path 4957 GROUP BY idpackage, library; 4958 4959 """) 4960 if output: 4961 self.updateProgress( 4962 "%s" % ( 4963 purple(_("Libraries solved, all fine")), 4964 ), 4965 importance = 0, type = "info" 4966 )
4967
4968 - def moveCountersToBranch(self, to_branch, from_branch = None):
4969 with self.__write_mutex: 4970 if from_branch is not None: 4971 self.cursor.execute('UPDATE counters SET branch = (?) WHERE branch = (?)', (to_branch, from_branch,)) 4972 else: 4973 self.cursor.execute('UPDATE counters SET branch = (?)', (to_branch,)) 4974 self.commitChanges() 4975 self.clearCache()
4976
4977 - def atomMatchFetchCache(self, *args):
4978 if self.xcache: 4979 cached = self.dumpTools.loadobj("%s/%s/%s" % (self.dbMatchCacheKey, self.dbname, hash(tuple(args)),)) 4980 if cached != None: return cached
4981
4982 - def atomMatchStoreCache(self, *args, **kwargs):
4983 if self.xcache: 4984 self.Cacher.push("%s/%s/%s" % ( 4985 self.dbMatchCacheKey,self.dbname,hash(tuple(args)),), 4986 kwargs.get('result') 4987 )
4988
4989 - def atomMatchValidateCache(self, cached_obj, multiMatch, extendedResults):
4990 4991 # time wasted for a reason 4992 data, rc = cached_obj 4993 if rc != 0: return cached_obj 4994 4995 if (not extendedResults) and (not multiMatch): 4996 if not self.isIDPackageAvailable(data): return None 4997 elif extendedResults and (not multiMatch): 4998 # ((idpackage,0,version,versiontag,revision,),0) 4999 if not self.isIDPackageAvailable(data[0]): return None 5000 elif extendedResults and multiMatch: 5001 # (set([(idpackage,0,version,version_tag,revision) for x in dbpkginfo]),0) 5002 idpackages = set([x[0] for x in data]) 5003 if not self.areIDPackagesAvailable(idpackages): return None 5004 elif (not extendedResults) and multiMatch: 5005 # (set([x[0] for x in dbpkginfo]),0) 5006 idpackages = set(data) 5007 if not self.areIDPackagesAvailable(idpackages): return None 5008 5009 return cached_obj
5010
5011 - def _idpackageValidator_live(self, idpackage, reponame):
5012 if (idpackage, reponame) in self.SystemSettings['live_packagemasking']['mask_matches']: 5013 # do not cache this 5014 return -1, self.SystemSettings['pkg_masking_reference']['user_live_mask'] 5015 elif (idpackage, reponame) in self.SystemSettings['live_packagemasking']['unmask_matches']: 5016 return idpackage, self.SystemSettings['pkg_masking_reference']['user_live_unmask']
5017
5018 - def _idpackageValidator_user_package_mask(self, idpackage, reponame, live):
5019 # check if user package.mask needs it masked 5020 5021 mykw = "%smask_ids" % (reponame,) 5022 user_package_mask_ids = self.SystemSettings.get(mykw) 5023 if not isinstance(user_package_mask_ids, (list, set,)): 5024 user_package_mask_ids = set() 5025 for atom in self.SystemSettings['mask']: 5026 matches, r = self.atomMatch(atom, multiMatch = True, packagesFilter = False) 5027 if r != 0: 5028 continue 5029 user_package_mask_ids |= set(matches) 5030 self.SystemSettings[mykw] = user_package_mask_ids 5031 if idpackage in user_package_mask_ids: 5032 # sorry, masked 5033 myr = self.SystemSettings['pkg_masking_reference']['user_package_mask'] 5034 try: 5035 validator_cache = self.SystemSettings[self.client_settings_plugin_id]['masking_validation']['cache'] 5036 validator_cache[(idpackage, reponame, live)] = -1, myr 5037 except KeyError: # system settings client plugin not found 5038 pass 5039 return -1, myr
5040
5041 - def _idpackageValidator_user_package_unmask(self, idpackage, reponame, live):
5042 # see if we can unmask by just lookin into user package.unmask stuff -> self.SystemSettings['unmask'] 5043 mykw = "%sunmask_ids" % (reponame,) 5044 user_package_unmask_ids = self.SystemSettings.get(mykw) 5045 if not isinstance(user_package_unmask_ids, (list, set,)): 5046 user_package_unmask_ids = set() 5047 for atom in self.SystemSettings['unmask']: 5048 matches, r = self.atomMatch(atom, multiMatch = True, packagesFilter = False) 5049 if r != 0: 5050 continue 5051 user_package_unmask_ids |= set(matches) 5052 self.SystemSettings[mykw] = user_package_unmask_ids 5053 if idpackage in user_package_unmask_ids: 5054 myr = self.SystemSettings['pkg_masking_reference']['user_package_unmask'] 5055 try: 5056 validator_cache = self.SystemSettings[self.client_settings_plugin_id]['masking_validation']['cache'] 5057 validator_cache[(idpackage, reponame, live)] = idpackage, myr 5058 except KeyError: # system settings client plugin not found 5059 pass 5060 return idpackage, myr
5061
5062 - def _idpackageValidator_packages_db_mask(self, idpackage, reponame, live):
5063 # check if repository packages.db.mask needs it masked 5064 repos_mask = {} 5065 client_plg_id = etpConst['system_settings_plugins_ids']['client_plugin'] 5066 client_settings = self.SystemSettings.get(client_plg_id, {}) 5067 if client_settings: 5068 repos_mask = client_settings['repositories']['mask'] 5069 repomask = repos_mask.get(reponame) 5070 if isinstance(repomask, (list, set,)): 5071 # first, seek into generic masking, all branches 5072 mask_repo_id = "%s_ids@@:of:%s" % (reponame, reponame,) # avoid issues with repository names 5073 repomask_ids = repos_mask.get(mask_repo_id) 5074 if not isinstance(repomask_ids, set): 5075 repomask_ids = set() 5076 for atom in repomask: 5077 matches, r = self.atomMatch(atom, multiMatch = True, packagesFilter = False) 5078 if r != 0: 5079 continue 5080 repomask_ids |= set(matches) 5081 repos_mask[mask_repo_id] = repomask_ids 5082 if idpackage in repomask_ids: 5083 myr = self.SystemSettings['pkg_masking_reference']['repository_packages_db_mask'] 5084 try: 5085 validator_cache = self.SystemSettings[self.client_settings_plugin_id]['masking_validation']['cache'] 5086 validator_cache[(idpackage, reponame, live)] = -1, myr 5087 except KeyError: # system settings client plugin not found 5088 pass 5089 return -1, myr
5090
5091 - def _idpackageValidator_package_license_mask(self, idpackage, reponame, live):
5092 if self.SystemSettings['license_mask']: 5093 mylicenses = self.retrieveLicense(idpackage) 5094 mylicenses = mylicenses.strip().split() 5095 lic_mask = self.SystemSettings['license_mask'] 5096 for mylicense in mylicenses: 5097 if mylicense not in lic_mask: continue 5098 myr = self.SystemSettings['pkg_masking_reference']['user_license_mask'] 5099 try: 5100 validator_cache = self.SystemSettings[self.client_settings_plugin_id]['masking_validation']['cache'] 5101 validator_cache[(idpackage, reponame, live)] = -1, myr 5102 except KeyError: # system settings client plugin not found 5103 pass 5104 return -1, myr
5105
5106 - def _idpackageValidator_keyword_mask(self, idpackage, reponame, live):
5107 5108 mykeywords = self.retrieveKeywords(idpackage) 5109 # WORKAROUND for buggy entries 5110 if not mykeywords: mykeywords = [''] # ** is fine then 5111 # firstly, check if package keywords are in etpConst['keywords'] 5112 # (universal keywords have been merged from package.mask) 5113 for key in etpConst['keywords']: 5114 if key not in mykeywords: continue 5115 myr = self.SystemSettings['pkg_masking_reference']['system_keyword'] 5116 try: 5117 validator_cache = self.SystemSettings[self.client_settings_plugin_id]['masking_validation']['cache'] 5118 validator_cache[(idpackage, reponame, live)] = idpackage, myr 5119 except KeyError: # system settings client plugin not found 5120 pass 5121 return idpackage, myr 5122 5123 # if we get here, it means we didn't find mykeywords in etpConst['keywords'] 5124 # we need to seek self.SystemSettings['keywords'] 5125 # seek in repository first 5126 if reponame in self.SystemSettings['keywords']['repositories']: 5127 for keyword in self.SystemSettings['keywords']['repositories'][reponame]: 5128 if keyword not in mykeywords: continue 5129 keyword_data = self.SystemSettings['keywords']['repositories'][reponame].get(keyword) 5130 if not keyword_data: continue 5131 if "*" in keyword_data: # all packages in this repo with keyword "keyword" are ok 5132 myr = self.SystemSettings['pkg_masking_reference']['user_repo_package_keywords_all'] 5133 try: 5134 validator_cache = self.SystemSettings[self.client_settings_plugin_id]['masking_validation']['cache'] 5135 validator_cache[(idpackage, reponame, live)] = idpackage, myr 5136 except KeyError: # system settings client plugin not found 5137 pass 5138 return idpackage, myr 5139 kwd_key = "%s_ids" % (keyword,) 5140 keyword_data_ids = self.SystemSettings['keywords']['repositories'][reponame].get(kwd_key) 5141 if not isinstance(keyword_data_ids, set): 5142 keyword_data_ids = set() 5143 for atom in keyword_data: 5144 matches, r = self.atomMatch(atom, multiMatch = True, packagesFilter = False) 5145 if r != 0: 5146 continue 5147 keyword_data_ids |= matches 5148 self.SystemSettings['keywords']['repositories'][reponame][kwd_key] = keyword_data_ids 5149 if idpackage in keyword_data_ids: 5150 myr = self.SystemSettings['pkg_masking_reference']['user_repo_package_keywords'] 5151 try: 5152 validator_cache = self.SystemSettings[self.client_settings_plugin_id]['masking_validation']['cache'] 5153 validator_cache[(idpackage, reponame, live)] = idpackage, myr 5154 except KeyError: # system settings client plugin not found 5155 pass 5156 return idpackage, myr 5157 5158 # if we get here, it means we didn't find a match in repositories 5159 # so we scan packages, last chance 5160 for keyword in self.SystemSettings['keywords']['packages']: 5161 # first of all check if keyword is in mykeywords 5162 if keyword not in mykeywords: continue 5163 keyword_data = self.SystemSettings['keywords']['packages'].get(keyword) 5164 if not keyword_data: continue 5165 kwd_key = "%s_ids" % (keyword,) 5166 keyword_data_ids = self.SystemSettings['keywords']['packages'].get(reponame+kwd_key) 5167 if not isinstance(keyword_data_ids, (list, set,)): 5168 keyword_data_ids = set() 5169 for atom in keyword_data: 5170 # match atom 5171 matches, r = self.atomMatch(atom, multiMatch = True, packagesFilter = False) 5172 if r != 0: 5173 continue 5174 keyword_data_ids |= matches 5175 self.SystemSettings['keywords']['packages'][reponame+kwd_key] = keyword_data_ids 5176 if idpackage in keyword_data_ids: 5177 # valid! 5178 myr = self.SystemSettings['pkg_masking_reference']['user_package_keywords'] 5179 try: 5180 validator_cache = self.SystemSettings[self.client_settings_plugin_id]['masking_validation']['cache'] 5181 validator_cache[(idpackage, reponame, live)] = idpackage, myr 5182 except KeyError: # system settings client plugin not found 5183 pass 5184 return idpackage, myr
5185 5186 5187 5188 # function that validate one atom by reading keywords settings 5189 # validator_cache = self.SystemSettings[self.client_settings_plugin_id]['masking_validation']['cache']
5190 - def idpackageValidator(self, idpackage, live = True):
5191 5192 if self.dbname == etpConst['clientdbid']: 5193 return idpackage, 0 5194 elif self.dbname.startswith(etpConst['serverdbid']): 5195 return idpackage, 0 5196 5197 reponame = self.dbname[len(etpConst['dbnamerepoprefix']):] 5198 try: 5199 validator_cache = self.SystemSettings[self.client_settings_plugin_id]['masking_validation']['cache'] 5200 cached = validator_cache.get((idpackage, reponame, live)) 5201 if cached != None: 5202 return cached 5203 # avoid memleaks 5204 if len(validator_cache) > 10000: 5205 validator_cache.clear() 5206 except KeyError: # plugin does not exist 5207 pass 5208 5209 if live: 5210 data = self._idpackageValidator_live(idpackage, reponame) 5211 if data: return data 5212 5213 data = self._idpackageValidator_user_package_mask(idpackage, reponame, live) 5214 if data: return data 5215 5216 data = self._idpackageValidator_user_package_unmask(idpackage, reponame, live) 5217 if data: return data 5218 5219 data = self._idpackageValidator_packages_db_mask(idpackage, reponame, live) 5220 if data: return data 5221 5222 data = self._idpackageValidator_package_license_mask(idpackage, reponame, live) 5223 if data: return data 5224 5225 data = self._idpackageValidator_keyword_mask(idpackage, reponame, live) 5226 if data: return data 5227 5228 # holy crap, can't validate 5229 myr = self.SystemSettings['pkg_masking_reference']['completely_masked'] 5230 validator_cache[(idpackage, reponame, live)] = -1, myr 5231 return -1, myr
5232 5233 # packages filter used by atomMatch, input must me foundIDs, a list like this: 5234 # [608,1867]
5235 - def packagesFilter(self, results):
5236 # keywordsFilter ONLY FILTERS results if 5237 # self.dbname.startswith(etpConst['dbnamerepoprefix']) => repository database is open 5238 if not self.dbname.startswith(etpConst['dbnamerepoprefix']): 5239 return results 5240 5241 newresults = set() 5242 for idpackage in results: 5243 idpackage, reason = self.idpackageValidator(idpackage) 5244 if idpackage == -1: continue 5245 newresults.add(idpackage) 5246 return newresults
5247
5248 - def __filterSlot(self, idpackage, slot):
5249 if slot == None: 5250 return idpackage 5251 dbslot = self.retrieveSlot(idpackage) 5252 if str(dbslot) == str(slot): 5253 return idpackage
5254
5255 - def __filterTag(self, idpackage, tag, operators):
5256 if tag == None: 5257 return idpackage 5258 dbtag = self.retrieveVersionTag(idpackage) 5259 compare = cmp(tag, dbtag) 5260 if not operators or operators == "=": 5261 if compare == 0: 5262 return idpackage 5263 else: 5264 return self.__do_operator_compare(idpackage, operators, compare)
5265
5266 - def __filterUse(self, idpackage, use):
5267 if not use: 5268 return idpackage 5269 pkguse = self.retrieveUseflags(idpackage) 5270 disabled = set([x[1:] for x in use if x.startswith("-")]) 5271 enabled = set([x for x in use if not x.startswith("-")]) 5272 enabled_not_satisfied = enabled - pkguse 5273 # check enabled 5274 if enabled_not_satisfied: 5275 return None 5276 # check disabled 5277 disabled_not_satisfied = disabled - pkguse 5278 if len(disabled_not_satisfied) != len(disabled): 5279 return None 5280 return idpackage
5281
5282 - def __do_operator_compare(self, token, operators, compare):
5283 if operators == ">" and compare == -1: 5284 return token 5285 elif operators == ">=" and compare < 1: 5286 return token 5287 elif operators == "<" and compare == 1: 5288 return token 5289 elif operators == "<=" and compare > -1: 5290 return token
5291
5292 - def __filterSlotTagUse(self, foundIDs, slot, tag, use, operators):
5293 5294 def myfilter(idpackage): 5295 5296 idpackage = self.__filterSlot(idpackage, slot) 5297 if not idpackage: 5298 return False 5299 5300 idpackage = self.__filterUse(idpackage, use) 5301 if not idpackage: 5302 return False 5303 5304 idpackage = self.__filterTag(idpackage, tag, operators) 5305 if not idpackage: 5306 return False 5307 5308 return True
5309 5310 return set(filter(myfilter, foundIDs)) 5311
5312 - def atomMatch(self, atom, caseSensitive = True, matchSlot = None, multiMatch = False, 5313 matchBranches = (), matchTag = None, matchUse = (), packagesFilter = True, 5314 matchRevision = None, extendedResults = False, useCache = True ):
5315 5316 """ 5317 5318 @description: matches the user chosen package name+ver, if possibile, in a single repository 5319 @input atom: string, atom to match 5320 @input caseSensitive: bool, should the atom be parsed case sensitive? 5321 @input matchSlot: string, match atoms with the provided slot 5322 @input multiMatch: bool, return all the available atoms 5323 @input matchBranches: tuple or list, match packages only in the specified branches 5324 @input matchTag: match packages only for the specified tag 5325 @input matchUse: match packages only if it owns the specified use flags 5326 @input packagesFilter: enable/disable package.mask/.keywords/.unmask filter 5327 @output: the package id, if found, otherwise -1 plus the status, 0 = ok, 1 = error 5328 5329 """ 5330 5331 if not atom: 5332 return -1, 1 5333 5334 if useCache: 5335 cached = self.atomMatchFetchCache( 5336 atom, caseSensitive, matchSlot, 5337 multiMatch, matchBranches, matchTag, 5338 matchUse, packagesFilter, matchRevision, 5339 extendedResults 5340 ) 5341 if isinstance(cached, tuple): 5342 try: 5343 cached = self.atomMatchValidateCache(cached, multiMatch, extendedResults) 5344 except (TypeError, ValueError, IndexError, KeyError,): 5345 cached = None 5346 if isinstance(cached, tuple): 5347 return cached 5348 5349 atomTag = self.entropyTools.dep_gettag(atom) 5350 try: 5351 atomUse = self.entropyTools.dep_getusedeps(atom) 5352 except InvalidAtom: 5353 atomUse = () 5354 atomSlot = self.entropyTools.dep_getslot(atom) 5355 atomRev = self.entropyTools.dep_get_entropy_revision(atom) 5356 if isinstance(atomRev, (int, long,)): 5357 if atomRev < 0: atomRev = None 5358 5359 # use match 5360 scan_atom = self.entropyTools.remove_usedeps(atom) 5361 if (not matchUse) and (atomUse): 5362 matchUse = atomUse 5363 5364 # tag match 5365 scan_atom = self.entropyTools.remove_tag(scan_atom) 5366 if (matchTag == None) and (atomTag != None): 5367 matchTag = atomTag 5368 5369 # slot match 5370 scan_atom = self.entropyTools.remove_slot(scan_atom) 5371 if (matchSlot == None) and (atomSlot != None): 5372 matchSlot = atomSlot 5373 5374 # revision match 5375 scan_atom = self.entropyTools.remove_entropy_revision(scan_atom) 5376 if (matchRevision == None) and (atomRev != None): 5377 matchRevision = atomRev 5378 5379 branch_list = () 5380 direction = '' 5381 justname = True 5382 pkgkey = '' 5383 strippedAtom = '' 5384 foundIDs = [] 5385 dbpkginfo = set() 5386 5387 if scan_atom: 5388 5389 while 1: 5390 pkgversion = '' 5391 # check for direction 5392 strippedAtom = self.entropyTools.dep_getcpv(scan_atom) 5393 if scan_atom[-1] == "*": 5394 strippedAtom += "*" 5395 direction = scan_atom[0:len(scan_atom)-len(strippedAtom)] 5396 5397 justname = self.entropyTools.isjustname(strippedAtom) 5398 pkgkey = strippedAtom 5399 if justname == 0: 5400 # get version 5401 data = self.entropyTools.catpkgsplit(strippedAtom) 5402 if data == None: break # badly formatted 5403 pkgversion = data[2]+"-"+data[3] 5404 pkgkey = self.entropyTools.dep_getkey(strippedAtom) 5405 5406 splitkey = pkgkey.split("/") 5407 if (len(splitkey) == 2): 5408 pkgname = splitkey[1] 5409 pkgcat = splitkey[0] 5410 else: 5411 pkgname = splitkey[0] 5412 pkgcat = "null" 5413 5414 branch_list = (self.db_branch,) 5415 if matchBranches: 5416 # force to tuple for security 5417 branch_list = tuple(matchBranches) 5418 break 5419 5420 5421 if branch_list: 5422 # IDs found in the database that match our search 5423 foundIDs = self.__generate_found_ids_match(branch_list, pkgkey, pkgname, pkgcat, caseSensitive, multiMatch) 5424 5425 ### FILTERING 5426 # filter slot and tag 5427 if foundIDs: 5428 foundIDs = self.__filterSlotTagUse(foundIDs, matchSlot, matchTag, matchUse, direction) 5429 if packagesFilter: 5430 foundIDs = self.packagesFilter(foundIDs) 5431 ### END FILTERING 5432 5433 if foundIDs: 5434 dbpkginfo = self.__handle_found_ids_match(foundIDs, direction, matchTag, matchRevision, justname, strippedAtom, pkgversion) 5435 5436 if not dbpkginfo: 5437 if extendedResults: 5438 if multiMatch: 5439 x = set() 5440 else: 5441 x = (-1, 1, None, None, None,) 5442 self.atomMatchStoreCache( 5443 atom, caseSensitive, matchSlot, 5444 multiMatch, matchBranches, matchTag, 5445 matchUse, packagesFilter, matchRevision, 5446 extendedResults, result = (x, 1) 5447 ) 5448 return x, 1 5449 else: 5450 if multiMatch: 5451 x = set() 5452 else: 5453 x = -1 5454 self.atomMatchStoreCache( 5455 atom, caseSensitive, matchSlot, 5456 multiMatch, matchBranches, matchTag, 5457 matchUse, packagesFilter, matchRevision, 5458 extendedResults, result = (x, 1) 5459 ) 5460 return x, 1 5461 5462 if multiMatch: 5463 if extendedResults: 5464 x = set([(x[0], 0, x[1], self.retrieveVersionTag(x[0]), self.retrieveRevision(x[0])) for x in dbpkginfo]) 5465 self.atomMatchStoreCache( 5466 atom, caseSensitive, matchSlot, 5467 multiMatch, matchBranches, matchTag, 5468 matchUse, packagesFilter, matchRevision, 5469 extendedResults, result = (x, 0) 5470 ) 5471 return x, 0 5472 else: 5473 x = set([x[0] for x in dbpkginfo]) 5474 self.atomMatchStoreCache( 5475 atom, caseSensitive, matchSlot, 5476 multiMatch, matchBranches, matchTag, 5477 matchUse, packagesFilter, matchRevision, 5478 extendedResults, result = (x, 0) 5479 ) 5480 return x, 0 5481 5482 if len(dbpkginfo) == 1: 5483 x = dbpkginfo.pop() 5484 if extendedResults: 5485 x = (x[0], 0, x[1], self.retrieveVersionTag(x[0]), self.retrieveRevision(x[0])) 5486 self.atomMatchStoreCache( 5487 atom, caseSensitive, matchSlot, 5488 multiMatch, matchBranches, matchTag, 5489 matchUse, packagesFilter, matchRevision, 5490 extendedResults, result = (x, 0) 5491 ) 5492 return x, 0 5493 else: 5494 self.atomMatchStoreCache( 5495 atom, caseSensitive, matchSlot, 5496 multiMatch, matchBranches, matchTag, 5497 matchUse, packagesFilter, matchRevision, 5498 extendedResults, result = (x[0], 0) 5499 ) 5500 return x[0], 0 5501 5502 dbpkginfo = list(dbpkginfo) 5503 pkgdata = {} 5504 versions = set() 5505 for x in dbpkginfo: 5506 info_tuple = (x[1], self.retrieveVersionTag(x[0]), self.retrieveRevision(x[0])) 5507 versions.add(info_tuple) 5508 pkgdata[info_tuple] = x[0] 5509 newer = self.entropyTools.get_entropy_newer_version(list(versions))[0] 5510 x = pkgdata[newer] 5511 if extendedResults: 5512 x = (x, 0, newer[0], newer[1], newer[2]) 5513 self.atomMatchStoreCache( 5514 atom, caseSensitive, matchSlot, 5515 multiMatch, matchBranches, matchTag, 5516 matchUse, packagesFilter, matchRevision, 5517 extendedResults, result = (x, 0) 5518 ) 5519 return x, 0 5520 else: 5521 self.atomMatchStoreCache( 5522 atom, caseSensitive, matchSlot, 5523 multiMatch, matchBranches, matchTag, 5524 matchUse, packagesFilter, matchRevision, 5525 extendedResults, result = (x, 0) 5526 ) 5527 return x, 0
5528
5529 - def __generate_found_ids_match(self, branch_list, pkgkey, pkgname, pkgcat, caseSensitive, multiMatch):
5530 foundIDs = set() 5531 for idx in branch_list: 5532 5533 if pkgcat == "null": 5534 results = self.searchPackagesByName( 5535 pkgname, sensitive = caseSensitive, 5536 branch = idx, justid = True 5537 ) 5538 else: 5539 results = self.searchPackagesByNameAndCategory( 5540 name = pkgname, category = pkgcat, branch = idx, 5541 sensitive = caseSensitive, justid = True 5542 ) 5543 5544 mypkgcat = pkgcat 5545 mypkgname = pkgname 5546 virtual = False 5547 # if it's a PROVIDE, search with searchProvide 5548 # there's no package with that name 5549 if (not results) and (mypkgcat == "virtual"): 5550 virtuals = self.searchProvide(pkgkey, branch = idx, justid = True) 5551 if virtuals: 5552 virtual = True 5553 mypkgname = self.retrieveName(virtuals[0]) 5554 mypkgcat = self.retrieveCategory(virtuals[0]) 5555 results = virtuals 5556 5557 # now validate 5558 if not results: 5559 continue # search into a stabler branch 5560 5561 elif (len(results) > 1): 5562 5563 # if it's because category differs, it's a problem 5564 foundCat = None 5565 cats = set() 5566 for idpackage in results: 5567 cat = self.retrieveCategory(idpackage) 5568 cats.add(cat) 5569 if (cat == mypkgcat) or ((not virtual) and (mypkgcat == "virtual") and (cat == mypkgcat)): 5570 # in case of virtual packages only (that they're not stored as provide) 5571 foundCat = cat 5572 5573 # if we found something at least... 5574 if (not foundCat) and (len(cats) == 1) and (mypkgcat in ("virtual", "null")): 5575 foundCat = sorted(cats)[0] 5576 5577 if not foundCat: 5578 # got the issue 5579 continue 5580 5581 # we can use foundCat 5582 mypkgcat = foundCat 5583 5584 # we need to search using the category 5585 if (not multiMatch) and (pkgcat == "null" or virtual): 5586 # we searched by name, we need to search using category 5587 results = self.searchPackagesByNameAndCategory( 5588 name = mypkgname, category = mypkgcat, 5589 branch = idx, sensitive = caseSensitive, justid = True 5590 ) 5591 5592 # validate again 5593 if not results: 5594 continue # search into another branch 5595 5596 # if we get here, we have found the needed IDs 5597 foundIDs |= set(results) 5598 break 5599 5600 else: 5601 5602 idpackage = results[0] 5603 # if mypkgcat is virtual, we can force 5604 if (mypkgcat == "virtual") and (not virtual): 5605 # in case of virtual packages only (that they're not stored as provide) 5606 mypkgcat = self.retrieveCategory(idpackage) 5607 5608 # check if category matches 5609 if mypkgcat != "null": 5610 foundCat = self.retrieveCategory(idpackage) 5611 if mypkgcat == foundCat: 5612 foundIDs.add(idpackage) 5613 continue 5614 foundIDs.add(idpackage) 5615 break 5616 5617 return foundIDs
5618 5619
5620 - def __handle_found_ids_match(self, foundIDs, direction, matchTag, matchRevision, justname, strippedAtom, pkgversion):
5621 5622 dbpkginfo = set() 5623 # now we have to handle direction 5624 if ((direction) or ((not direction) and (not justname)) or ((not direction) and (not justname) and strippedAtom.endswith("*"))) and foundIDs: 5625 5626 if (not justname) and \ 5627 ((direction == "~") or (direction == "=") or \ 5628 (direction == '' and not justname) or (direction == '' and not justname and strippedAtom.endswith("*"))): 5629 # any revision within the version specified OR the specified version 5630 5631 if (direction == '' and not justname): 5632 direction = "=" 5633 5634 # remove gentoo revision (-r0 if none) 5635 if (direction == "="): 5636 if (pkgversion.split("-")[-1] == "r0"): 5637 pkgversion = self.entropyTools.remove_revision(pkgversion) 5638 if (direction == "~"): 5639 pkgrevision = self.entropyTools.dep_get_portage_revision(pkgversion) 5640 pkgversion = self.entropyTools.remove_revision(pkgversion) 5641 5642 for idpackage in foundIDs: 5643 5644 dbver = self.retrieveVersion(idpackage) 5645 if (direction == "~"): 5646 myrev = self.entropyTools.dep_get_portage_revision(dbver) 5647 myver = self.entropyTools.remove_revision(dbver) 5648 if myver == pkgversion and pkgrevision <= myrev: 5649 # found 5650 dbpkginfo.add((idpackage, dbver)) 5651 else: 5652 # media-libs/test-1.2* support 5653 if pkgversion[-1] == "*": 5654 if dbver.startswith(pkgversion[:-1]): 5655 dbpkginfo.add((idpackage, dbver)) 5656 elif (matchRevision != None) and (pkgversion == dbver): 5657 dbrev = self.retrieveRevision(idpackage) 5658 if dbrev == matchRevision: 5659 dbpkginfo.add((idpackage, dbver)) 5660 elif (pkgversion == dbver) and (matchRevision == None): 5661 dbpkginfo.add((idpackage, dbver)) 5662 5663 elif (direction.find(">") != -1) or (direction.find("<") != -1): 5664 5665 if not justname: 5666 5667 # remove revision (-r0 if none) 5668 if pkgversion.endswith("r0"): 5669 # remove 5670 self.entropyTools.remove_revision(pkgversion) 5671 5672 for idpackage in foundIDs: 5673 5674 revcmp = 0 5675 tagcmp = 0 5676 if matchRevision != None: 5677 dbrev = self.retrieveRevision(idpackage) 5678 revcmp = cmp(matchRevision, dbrev) 5679 if matchTag != None: 5680 dbtag = self.retrieveVersionTag(idpackage) 5681 tagcmp = cmp(matchTag, dbtag) 5682 dbver = self.retrieveVersion(idpackage) 5683 pkgcmp = self.entropyTools.compare_versions(pkgversion, dbver) 5684 if pkgcmp == None: 5685 import warnings 5686 warnings.warn("WARNING, invalid version string stored in %s: %s <-> %s" % (self.dbname, pkgversion, dbver,)) 5687 continue 5688 if direction == ">": 5689 if pkgcmp < 0: 5690 dbpkginfo.add((idpackage, dbver)) 5691 elif (matchRevision != None) and pkgcmp <= 0 and revcmp < 0: 5692 dbpkginfo.add((idpackage, dbver)) 5693 elif (matchTag != None) and tagcmp < 0: 5694 dbpkginfo.add((idpackage, dbver)) 5695 elif direction == "<": 5696 if pkgcmp > 0: 5697 dbpkginfo.add((idpackage, dbver)) 5698 elif (matchRevision != None) and pkgcmp >= 0 and revcmp > 0: 5699 dbpkginfo.add((idpackage, dbver)) 5700 elif (matchTag != None) and tagcmp > 0: 5701 dbpkginfo.add((idpackage, dbver)) 5702 elif direction == ">=": 5703 if (matchRevision != None) and pkgcmp <= 0: 5704 if pkgcmp == 0: 5705 if revcmp <= 0: 5706 dbpkginfo.add((idpackage, dbver)) 5707 else: 5708 dbpkginfo.add((idpackage, dbver)) 5709 elif pkgcmp <= 0 and matchRevision == None: 5710 dbpkginfo.add((idpackage, dbver)) 5711 elif (matchTag != None) and tagcmp <= 0: 5712 dbpkginfo.add((idpackage, dbver)) 5713 elif direction == "<=": 5714 if (matchRevision != None) and pkgcmp >= 0: 5715 if pkgcmp == 0: 5716 if revcmp >= 0: 5717 dbpkginfo.add((idpackage, dbver)) 5718 else: 5719 dbpkginfo.add((idpackage, dbver)) 5720 elif pkgcmp >= 0 and matchRevision == None: 5721 dbpkginfo.add((idpackage, dbver)) 5722 elif (matchTag != None) and tagcmp >= 0: 5723 dbpkginfo.add((idpackage, dbver)) 5724 5725 else: # just the key 5726 5727 dbpkginfo = set([(x, self.retrieveVersion(x),) for x in foundIDs]) 5728 5729 return dbpkginfo
5730