Package entropy :: Package db :: Module sql

Source Code for Module entropy.db.sql

   1  # -*- coding: utf-8 -*- 
   2  """ 
   3   
   4      @author: Fabio Erculiani <[email protected]> 
   5      @contact: [email protected] 
   6      @copyright: Fabio Erculiani 
   7      @license: GPL-2 
   8   
   9      I{EntropyRepository} is an abstract class that implements 
  10      most of the EntropyRepository methods using standard SQL. 
  11   
  12  """ 
  13  import os 
  14  import hashlib 
  15  import itertools 
  16  import time 
  17  import threading 
  18   
  19  from entropy.const import etpConst, const_debug_write, \ 
  20      const_debug_enabled, const_isunicode, const_convert_to_unicode, \ 
  21      const_get_buffer, const_convert_to_rawstring, const_is_python3, \ 
  22      const_get_stringtype 
  23  from entropy.exceptions import SystemDatabaseError, SPMError 
  24  from entropy.spm.plugins.factory import get_default_instance as get_spm 
  25  from entropy.output import bold, red 
  26  from entropy.misc import ParallelTask 
  27   
  28  from entropy.i18n import _ 
  29   
  30  import entropy.dep 
  31  import entropy.tools 
  32   
  33  from entropy.db.skel import EntropyRepositoryBase 
  34  from entropy.db.cache import EntropyRepositoryCacher 
  35  from entropy.db.exceptions import Warning, Error, InterfaceError, \ 
  36      DatabaseError, DataError, OperationalError, IntegrityError, \ 
  37      InternalError, ProgrammingError, NotSupportedError 
38 39 40 -class SQLConnectionWrapper(object):
41 42 """ 43 This class wraps an implementation dependent 44 Connection object, exposing a common API which 45 resembles the Python DBAPI 2.0. 46 All the underlying library calls are wrapped 47 around using a proxy method in order to catch 48 and then raise entropy.db.exceptions exceptions. 49 """ 50
51 - def __init__(self, connection, exceptions):
52 self._con = connection 53 self._excs = exceptions
54
55 - def __hash__(self):
56 return id(self)
57 58 @staticmethod
59 - def _proxy_call(exceptions, method, *args, **kwargs):
60 """ 61 This method is tricky because it wraps every 62 underlying engine call catching all its exceptions 63 and respawning them as entropy.db.exceptions. 64 This provides optimum abstraction. 65 """ 66 try: 67 # do not change the exception handling 68 # order, we need to reverse the current 69 # hierarchy to avoid catching super 70 # classes before their subs. 71 return method(*args, **kwargs) 72 except exceptions.InterfaceError as err: 73 raise InterfaceError(err) 74 75 except exceptions.DataError as err: 76 raise DataError(err) 77 except exceptions.OperationalError as err: 78 raise OperationalError(err) 79 except exceptions.IntegrityError as err: 80 raise IntegrityError(err) 81 except exceptions.InternalError as err: 82 raise InternalError(err) 83 except exceptions.ProgrammingError as err: 84 raise ProgrammingError(err) 85 except exceptions.NotSupportedError as err: 86 raise NotSupportedError(err) 87 except exceptions.DatabaseError as err: 88 # this is the parent of all the above 89 raise DatabaseError(err) 90 91 except exceptions.Error as err: 92 raise Error(err) 93 except exceptions.Warning as err: 94 raise Warning(err)
95 96 @staticmethod
97 - def connect(module_proxy, module, subclass, *args, **kwargs):
98 conn_impl = SQLConnectionWrapper._proxy_call( 99 module_proxy.exceptions(), module.connect, 100 *args, **kwargs) 101 return subclass(conn_impl, module_proxy.exceptions())
102
103 - def commit(self):
104 return self._proxy_call(self._excs, self._con.commit)
105
106 - def rollback(self):
107 return self._proxy_call(self._excs, self._con.rollback)
108
109 - def close(self):
110 return self._proxy_call(self._excs, self._con.close)
111
112 - def cursor(self):
113 return self._proxy_call(self._excs, self._con.cursor)
114
115 - def ping(self):
116 """ 117 Ping the underlying connection to keep it alive. 118 """ 119 raise NotImplementedError()
120
121 - def unicode(self):
122 """ 123 Enforce Unicode strings. 124 """ 125 raise NotImplementedError()
126
127 - def rawstring(self):
128 """ 129 Enforce byte strings. 130 """ 131 raise NotImplementedError()
132
133 - def interrupt(self):
134 """ 135 Interrupt any pending activity. 136 """ 137 raise NotImplementedError()
138
139 140 -class SQLCursorWrapper(object):
141 """ 142 This class wraps an implementation dependent 143 Cursor object, exposing a common API which 144 resembles the Python DBAPI 2.0. 145 All the underlying library calls are wrapped 146 around using a proxy method in order to catch 147 and then raise entropy.db.exceptions exceptions. 148 """ 149
150 - def __init__(self, cursor, exceptions):
151 self._cur = cursor 152 self._excs = exceptions
153
154 - def _proxy_call(self, method, *args, **kwargs):
155 """ 156 This method is tricky because it wraps every 157 underlying engine call catching all its exceptions 158 and respawning them as entropy.db.exceptions. 159 This provides optimum abstraction. 160 """ 161 try: 162 # do not change the exception handling 163 # order, we need to reverse the current 164 # hierarchy to avoid catching super 165 # classes before their subs. 166 return method(*args, **kwargs) 167 except self._excs.InterfaceError as err: 168 raise InterfaceError(err) 169 170 except self._excs.DataError as err: 171 raise DataError(err) 172 except self._excs.OperationalError as err: 173 raise OperationalError(err) 174 except self._excs.IntegrityError as err: 175 raise IntegrityError(err) 176 except self._excs.InternalError as err: 177 raise InternalError(err) 178 except self._excs.ProgrammingError as err: 179 raise ProgrammingError(err) 180 except self._excs.NotSupportedError as err: 181 raise NotSupportedError(err) 182 except self._excs.DatabaseError as err: 183 # this is the parent of all the above 184 raise DatabaseError(err) 185 186 except self._excs.Error as err: 187 raise Error(err) 188 except self._excs.Warning as err: 189 raise Warning(err)
190
191 - def wrap(self, method, *args, **kwargs):
192 return self._proxy_call(method, *args, **kwargs)
193
194 - def execute(self, *args, **kwargs):
195 raise NotImplementedError()
196
197 - def executemany(self, *args, **kwargs):
198 raise NotImplementedError()
199
200 - def close(self, *args, **kwargs):
201 raise NotImplementedError()
202
203 - def fetchone(self, *args, **kwargs):
204 raise NotImplementedError()
205
206 - def fetchall(self, *args, **kwargs):
207 raise NotImplementedError()
208
209 - def fetchmany(self, *args, **kwargs):
210 raise NotImplementedError()
211
212 - def executescript(self, *args, **kwargs):
213 raise NotImplementedError()
214
215 - def callproc(self, *args, **kwargs):
216 raise NotImplementedError()
217
218 - def nextset(self, *args, **kwargs):
219 raise NotImplementedError()
220
221 - def __iter__(self):
222 raise NotImplementedError()
223
224 - def __next__(self):
225 raise NotImplementedError()
226
227 - def next(self):
228 raise NotImplementedError()
229 230 @property
231 - def lastrowid(self):
232 return self._cur.lastrowid
233 234 @property
235 - def rowcount(self):
236 return self._cur.rowcount
237 238 @property
239 - def description(self):
240 return self._cur.description
241
242 243 -class EntropySQLRepository(EntropyRepositoryBase):
244 245 """ 246 EntropySQLRepository partially implements a SQL based repository 247 storage. 248 """ 249
250 - class Schema(object):
251
252 - def get_init(self):
253 data = """ 254 CREATE TABLE baseinfo ( 255 idpackage INTEGER PRIMARY KEY AUTOINCREMENT, 256 atom VARCHAR, 257 category VARCHAR, 258 name VARCHAR, 259 version VARCHAR, 260 versiontag VARCHAR, 261 revision INTEGER, 262 branch VARCHAR, 263 slot VARCHAR, 264 license VARCHAR, 265 etpapi INTEGER, 266 trigger INTEGER 267 ); 268 269 CREATE TABLE extrainfo ( 270 idpackage INTEGER PRIMARY KEY, 271 description VARCHAR, 272 homepage VARCHAR, 273 download VARCHAR, 274 size VARCHAR, 275 chost VARCHAR, 276 cflags VARCHAR, 277 cxxflags VARCHAR, 278 digest VARCHAR, 279 datecreation VARCHAR, 280 FOREIGN KEY(idpackage) 281 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 282 ); 283 CREATE TABLE content ( 284 idpackage INTEGER, 285 file VARCHAR, 286 type VARCHAR, 287 FOREIGN KEY(idpackage) 288 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 289 ); 290 291 CREATE TABLE contentsafety ( 292 idpackage INTEGER, 293 file VARCHAR, 294 mtime FLOAT, 295 sha256 VARCHAR, 296 FOREIGN KEY(idpackage) 297 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 298 ); 299 300 CREATE TABLE provide ( 301 idpackage INTEGER, 302 atom VARCHAR, 303 is_default INTEGER DEFAULT 0, 304 FOREIGN KEY(idpackage) 305 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 306 ); 307 308 CREATE TABLE dependencies ( 309 idpackage INTEGER, 310 iddependency INTEGER, 311 type INTEGER, 312 FOREIGN KEY(idpackage) 313 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 314 ); 315 316 CREATE TABLE dependenciesreference ( 317 iddependency INTEGER PRIMARY KEY AUTOINCREMENT, 318 dependency VARCHAR 319 ); 320 321 CREATE TABLE conflicts ( 322 idpackage INTEGER, 323 conflict VARCHAR, 324 FOREIGN KEY(idpackage) 325 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 326 ); 327 328 CREATE TABLE mirrorlinks ( 329 mirrorname VARCHAR, 330 mirrorlink VARCHAR 331 ); 332 333 CREATE TABLE sources ( 334 idpackage INTEGER, 335 idsource INTEGER, 336 FOREIGN KEY(idpackage) 337 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 338 ); 339 340 CREATE TABLE sourcesreference ( 341 idsource INTEGER PRIMARY KEY AUTOINCREMENT, 342 source VARCHAR 343 ); 344 345 CREATE TABLE useflags ( 346 idpackage INTEGER, 347 idflag INTEGER, 348 FOREIGN KEY(idpackage) 349 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 350 ); 351 352 CREATE TABLE useflagsreference ( 353 idflag INTEGER PRIMARY KEY AUTOINCREMENT, 354 flagname VARCHAR 355 ); 356 357 CREATE TABLE keywords ( 358 idpackage INTEGER, 359 idkeyword INTEGER, 360 FOREIGN KEY(idpackage) 361 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 362 ); 363 364 CREATE TABLE keywordsreference ( 365 idkeyword INTEGER PRIMARY KEY AUTOINCREMENT, 366 keywordname VARCHAR 367 ); 368 369 CREATE TABLE configprotect ( 370 idpackage INTEGER PRIMARY KEY, 371 idprotect INTEGER, 372 FOREIGN KEY(idpackage) 373 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 374 ); 375 376 CREATE TABLE configprotectmask ( 377 idpackage INTEGER PRIMARY KEY, 378 idprotect INTEGER, 379 FOREIGN KEY(idpackage) 380 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 381 ); 382 383 CREATE TABLE configprotectreference ( 384 idprotect INTEGER PRIMARY KEY AUTOINCREMENT, 385 protect VARCHAR 386 ); 387 388 CREATE TABLE systempackages ( 389 idpackage INTEGER PRIMARY KEY, 390 FOREIGN KEY(idpackage) 391 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 392 ); 393 394 CREATE TABLE injected ( 395 idpackage INTEGER PRIMARY KEY, 396 FOREIGN KEY(idpackage) 397 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 398 ); 399 400 CREATE TABLE installedtable ( 401 idpackage INTEGER PRIMARY KEY, 402 repositoryname VARCHAR, 403 source INTEGER, 404 FOREIGN KEY(idpackage) 405 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 406 ); 407 408 CREATE TABLE sizes ( 409 idpackage INTEGER PRIMARY KEY, 410 size INTEGER, 411 FOREIGN KEY(idpackage) 412 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 413 ); 414 415 CREATE TABLE counters ( 416 counter INTEGER, 417 idpackage INTEGER, 418 branch VARCHAR, 419 PRIMARY KEY(idpackage,branch), 420 FOREIGN KEY(idpackage) 421 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 422 ); 423 424 CREATE TABLE trashedcounters ( 425 counter INTEGER 426 ); 427 428 CREATE TABLE needed_libs ( 429 idpackage INTEGER, 430 lib_user_path VARCHAR, 431 lib_user_soname VARCHAR, 432 soname VARCHAR, 433 elfclass INTEGER, 434 rpath VARCHAR, 435 FOREIGN KEY(idpackage) 436 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 437 ); 438 439 CREATE TABLE provided_libs ( 440 idpackage INTEGER, 441 library VARCHAR, 442 path VARCHAR, 443 elfclass INTEGER, 444 FOREIGN KEY(idpackage) 445 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 446 ); 447 448 CREATE TABLE treeupdates ( 449 repository VARCHAR PRIMARY KEY, 450 digest VARCHAR 451 ); 452 453 CREATE TABLE treeupdatesactions ( 454 idupdate INTEGER PRIMARY KEY AUTOINCREMENT, 455 repository VARCHAR, 456 command VARCHAR, 457 branch VARCHAR, 458 date VARCHAR 459 ); 460 461 CREATE TABLE licensedata ( 462 licensename VARCHAR UNIQUE, 463 text BLOB, 464 compressed INTEGER 465 ); 466 467 CREATE TABLE licenses_accepted ( 468 licensename VARCHAR UNIQUE 469 ); 470 471 CREATE TABLE triggers ( 472 idpackage INTEGER PRIMARY KEY, 473 data BLOB, 474 FOREIGN KEY(idpackage) 475 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 476 ); 477 478 CREATE TABLE entropy_misc_counters ( 479 idtype INTEGER PRIMARY KEY, 480 counter INTEGER 481 ); 482 483 CREATE TABLE categoriesdescription ( 484 category VARCHAR, 485 locale VARCHAR, 486 description VARCHAR 487 ); 488 489 CREATE TABLE packagesets ( 490 setname VARCHAR, 491 dependency VARCHAR 492 ); 493 494 CREATE TABLE packagechangelogs ( 495 category VARCHAR, 496 name VARCHAR, 497 changelog BLOB, 498 PRIMARY KEY (category, name) 499 ); 500 501 CREATE TABLE automergefiles ( 502 idpackage INTEGER, 503 configfile VARCHAR, 504 md5 VARCHAR, 505 FOREIGN KEY(idpackage) 506 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 507 ); 508 509 CREATE TABLE packagedesktopmime ( 510 idpackage INTEGER, 511 name VARCHAR, 512 mimetype VARCHAR, 513 executable VARCHAR, 514 icon VARCHAR, 515 FOREIGN KEY(idpackage) 516 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 517 ); 518 519 CREATE TABLE packagedownloads ( 520 idpackage INTEGER, 521 download VARCHAR, 522 type VARCHAR, 523 size INTEGER, 524 disksize INTEGER, 525 md5 VARCHAR, 526 sha1 VARCHAR, 527 sha256 VARCHAR, 528 sha512 VARCHAR, 529 gpg BLOB, 530 FOREIGN KEY(idpackage) 531 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 532 ); 533 534 CREATE TABLE provided_mime ( 535 mimetype VARCHAR, 536 idpackage INTEGER, 537 FOREIGN KEY(idpackage) 538 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 539 ); 540 541 CREATE TABLE packagesignatures ( 542 idpackage INTEGER PRIMARY KEY, 543 sha1 VARCHAR, 544 sha256 VARCHAR, 545 sha512 VARCHAR, 546 gpg BLOB, 547 FOREIGN KEY(idpackage) 548 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 549 ); 550 551 CREATE TABLE packagespmphases ( 552 idpackage INTEGER PRIMARY KEY, 553 phases VARCHAR, 554 FOREIGN KEY(idpackage) 555 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 556 ); 557 558 CREATE TABLE packagespmrepository ( 559 idpackage INTEGER PRIMARY KEY, 560 repository VARCHAR, 561 FOREIGN KEY(idpackage) 562 REFERENCES baseinfo(idpackage) ON DELETE CASCADE 563 ); 564 565 CREATE TABLE entropy_branch_migration ( 566 repository VARCHAR, 567 from_branch VARCHAR, 568 to_branch VARCHAR, 569 post_migration_md5sum VARCHAR, 570 post_upgrade_md5sum VARCHAR, 571 PRIMARY KEY (repository, from_branch, to_branch) 572 ); 573 574 CREATE TABLE preserved_libs ( 575 library VARCHAR, 576 elfclass INTEGER, 577 path VARCHAR, 578 atom VARCHAR, 579 PRIMARY KEY (library, path, elfclass) 580 ); 581 582 CREATE TABLE xpakdata ( 583 idpackage INTEGER PRIMARY KEY, 584 data BLOB 585 ); 586 587 CREATE TABLE settings ( 588 setting_name VARCHAR, 589 setting_value VARCHAR, 590 PRIMARY KEY(setting_name) 591 ); 592 593 """ 594 return data
595 596 # the "INSERT OR REPLACE" dialect 597 # For SQLite3 it's "INSERT OR REPLACE" 598 # while for MySQL it's "REPLACE" 599 _INSERT_OR_REPLACE = None 600 # the "INSERT OR IGNORE" dialect 601 _INSERT_OR_IGNORE = None 602 603 ## Optionals 604 605 # If not None, must contain the 606 # "UPDATE OR REPLACE" dialect 607 _UPDATE_OR_REPLACE = None 608 609 _MAIN_THREAD = threading.current_thread() 610 611 @classmethod
612 - def isMainThread(cls, thread_obj):
613 return thread_obj is cls._MAIN_THREAD
614 615 # Generic repository name to use when none is given. 616 GENERIC_NAME = "__generic__" 617
618 - def __init__(self, db, read_only, skip_checks, indexing, 619 xcache, temporary, name, direct=False, cache_policy=None):
620 # connection and cursor automatic cleanup support 621 self._cleanup_monitor_cache_mutex = threading.Lock() 622 self._cleanup_monitor_cache = {} 623 624 self._db = db 625 self._indexing = indexing 626 self._skip_checks = skip_checks 627 self._settings_cache = {} 628 self.__connection_pool = {} 629 self.__connection_pool_mutex = threading.RLock() 630 self.__cursor_pool_mutex = threading.RLock() 631 self.__cursor_pool = {} 632 if name is None: 633 name = self.GENERIC_NAME 634 self._live_cacher = EntropyRepositoryCacher() 635 636 EntropyRepositoryBase.__init__(self, read_only, xcache, 637 temporary, name, direct=direct, 638 cache_policy=cache_policy)
639
641 """ 642 Return the Cursor and Connection Pool key 643 that can be used inside the current thread 644 and process (multiprocessing not supported). 645 """ 646 current_thread = threading.current_thread() 647 thread_id = current_thread.ident 648 pid = os.getpid() 649 return self._db, thread_id, pid
650
651 - def _cleanup_all(self, _cleanup_main_thread=True):
652 """ 653 Clean all the Cursor and Connection resources 654 left open. 655 """ 656 if const_debug_enabled(): 657 const_debug_write( 658 __name__, 659 "called _cleanup_all() for %s" % (self,)) 660 with self._cursor_pool_mutex(): 661 with self._connection_pool_mutex(): 662 th_data = set(self._cursor_pool().keys()) 663 th_data.update(self._connection_pool().keys()) 664 for c_key in th_data: 665 self._cleanup_killer( 666 c_key, 667 _cleanup_main_thread=_cleanup_main_thread)
668
669 - def _cleanup_monitor(self, target_thread, c_key):
670 """ 671 Execute Cursor and Connection resources 672 termination. 673 """ 674 # join on thread 675 target_thread.join() 676 677 if const_debug_enabled(): 678 const_debug_write( 679 __name__, 680 "thread '%s' exited [%s], cleaning: %s" % ( 681 target_thread, hex(target_thread.ident), 682 c_key,)) 683 with self._cleanup_monitor_cache_mutex: 684 self._cleanup_monitor_cache.pop(c_key, None) 685 self._cleanup_killer(c_key)
686
687 - def _start_cleanup_monitor(self, current_thread, c_key):
688 """ 689 Allocate a new thread that monitors the thread object 690 passed as "current_thread". Once this thread terminates, 691 all its resources are automatically released. 692 current_thread is actually joined() and live cursor and 693 connections are checked against thread identity value 694 clashing (because thread.ident values are recycled). 695 For the main thread, this method is a NO-OP. 696 The allocated thread is a daemon thread, so it should 697 be safe to use join() on daemon threads as well. 698 """ 699 if self.isMainThread(current_thread): 700 const_debug_write( 701 __name__, 702 "NOT setting up a cleanup monitor for the MainThread") 703 # do not install any cleanup monitor then 704 return 705 706 with self._cleanup_monitor_cache_mutex: 707 mon = self._cleanup_monitor_cache.get(c_key) 708 if mon is not None: 709 # there is already a monitor for this 710 # cache key, quit straight away 711 return 712 self._cleanup_monitor_cache[c_key] = mon 713 714 if const_debug_enabled(): 715 const_debug_write( 716 __name__, 717 "setting up a new cleanup monitor") 718 mon = ParallelTask(self._cleanup_monitor, 719 current_thread, c_key) 720 mon.name = "CleanupMonitor" 721 mon.daemon = True 722 mon.start()
723
724 - def _cleanup_killer(self, c_key, _cleanup_main_thread=False):
725 """ 726 Cursor and Connection cleanup method. 727 """ 728 db, th_ident, pid = c_key 729 730 with self._cursor_pool_mutex(): 731 with self._connection_pool_mutex(): 732 cursor_pool = self._cursor_pool() 733 cur = None 734 threads = set() 735 736 cur_data = cursor_pool.get(c_key) 737 if cur_data is not None: 738 cur, threads = cur_data 739 740 connection_pool = self._connection_pool() 741 conn_data = connection_pool.get(c_key) 742 conn = None 743 if conn_data is not None: 744 conn, _threads = conn_data 745 threads |= _threads 746 747 if not threads: 748 # no threads? 749 return 750 751 # now cleanup threads set() first 752 # if it's empty, we can kill both 753 # connection and cursor 754 _dead_threads = set( 755 (x for x in threads if not x.is_alive())) 756 # we need to use the method rather than 757 # the operator, because we alter its data in 758 # place. 759 threads.difference_update(_dead_threads) 760 761 # also remove myself from the list 762 current_thread = threading.current_thread() 763 threads.discard(current_thread) 764 765 # closing the main thread objects (forcibly) 766 # is VERY dangerous, but it turned out 767 # that the original version of EntropyRepository.close() 768 # did that (that is why we have rwsems encapsulating 769 # entropy calls in RigoDaemon and Rigo). 770 # Also, one expects that close() really terminates 771 # all the connections and releases all the resources. 772 if _cleanup_main_thread and threads: 773 threads.discard(self._MAIN_THREAD) 774 775 if threads: 776 if const_debug_enabled(): 777 const_debug_write( 778 __name__, 779 "_cleanup_killer: " 780 "there are still alive threads, " 781 "not cleaning up resources, " 782 "alive: %s -- dead: %s" % ( 783 threads, _dead_threads,)) 784 return 785 786 cursor_pool.pop(c_key, None) 787 connection_pool.pop(c_key, None) 788 789 if const_debug_enabled(): 790 const_debug_write( 791 __name__, 792 "_cleanup_killer: " 793 "all threads sharing the same " 794 "ident are gone, i canz kill thread " 795 "ids: %s." % (hex(th_ident),)) 796 797 # WARNING !! BEHAVIOUR CHANGE 798 # no more implicit commit() 799 # caller has to do it! 800 try: 801 conn.close() 802 except OperationalError as err: 803 if const_debug_enabled(): 804 const_debug_write( 805 __name__, 806 "_cleanup_killer_1: %s" % (err,)) 807 try: 808 conn.interrupt() 809 conn.close() 810 except OperationalError as err: 811 # heh, unable to close due to 812 # unfinalized statements 813 # interpreter shutdown? 814 if const_debug_enabled(): 815 const_debug_write( 816 __name__, 817 "_cleanup_killer_2: %s" % (err,))
818
819 - def _concatOperator(self, fields):
820 """ 821 Return the SQL for the CONCAT() function 822 of the given field elements. 823 For instance, MySQL has CONCAT(el_1, el_2, ...) 824 while SQLite3 uses the || n-ary operator. 825 So, the output of this method is a string, which 826 for MySQL is something like "CONCAT(el_1, el_2, ...)" 827 """ 828 raise NotImplementedError()
829
830 - def _isBaseinfoExtrainfo2010(self):
831 """ 832 This method is mainly for old adapters that were 833 using a less-optimized more-normalized schema. 834 Just return True if you don't know what it does mean. 835 """ 836 return True
837
838 - def clearCache(self):
839 """ 840 Reimplemented from EntropyRepositoryBase. 841 """ 842 self._live_cacher.clear() 843 super(EntropySQLRepository, self).clearCache() 844 self._live_cacher.clear()
845
846 - def _clearLiveCache(self, key):
847 """ 848 Remove any in-memory cache pointed by key. 849 """ 850 self._live_cacher.clear_key(self._getLiveCacheKey() + key)
851
852 - def _discardLiveCache(self):
853 """ 854 Invalidate all the in-memory cache. 855 """ 856 self._live_cacher.discard(self._getLiveCacheKey())
857
858 - def _setLiveCache(self, key, value):
859 """ 860 Save a new key -> value pair to the in-memory cache. 861 """ 862 self._live_cacher.set(self._getLiveCacheKey() + key, value)
863
864 - def _getLiveCache(self, key):
865 """ 866 Lookup a key value from the in-memory cache. 867 """ 868 return self._live_cacher.get(self._getLiveCacheKey() + key)
869
870 - def _getLiveCacheKey(self):
871 """ 872 Reimplemented from EntropySQLRepository. 873 """ 874 return etpConst['systemroot'] + "_" + self._db + "_" + \ 875 self.name + "_"
876
877 - def _connection(self):
878 """ 879 Return a valid Connection object for this thread. 880 Must be implemented by subclasses and must return 881 a SQLConnectionWrapper object. 882 """ 883 raise NotImplementedError()
884
885 - def _cursor(self):
886 """ 887 Return a valid Cursor object for this thread. 888 Must be implemented by subclasses and must return 889 a SQLCursorWrapper object. 890 """ 891 raise NotImplementedError()
892
893 - def _cur2frozenset(self, cur):
894 """ 895 Flatten out a cursor content (usually some kind of list of lists) 896 and transform it into an immutable frozenset object. 897 """ 898 content = set() 899 for x in cur: 900 content |= set(x) 901 return frozenset(content)
902
903 - def _cur2tuple(self, cur):
904 """ 905 Flatten out a cursor content (usually some kind of list of lists) 906 and transform it into an immutable tuple object. 907 """ 908 return tuple(itertools.chain.from_iterable(cur))
909
910 - def _connection_pool(self):
911 """ 912 Return the Connection Pool mapping object 913 """ 914 return self.__connection_pool
915
916 - def _connection_pool_mutex(self):
917 """ 918 Return the Connection Pool mapping mutex 919 """ 920 return self.__connection_pool_mutex
921
922 - def _cursor_pool(self):
923 """ 924 Return the Cursor Pool mapping object 925 """ 926 return self.__cursor_pool
927
928 - def _cursor_pool_mutex(self):
929 """ 930 Return the Cursor Pool mapping mutex 931 """ 932 return self.__cursor_pool_mutex
933
934 - def _doesTableExist(self, table, temporary = False):
935 """ 936 Return whether a table exists. 937 """ 938 raise NotImplementedError()
939
940 - def _doesColumnInTableExist(self, table, column):
941 """ 942 Return whether a column in table exists. 943 """ 944 raise NotImplementedError()
945 946 @staticmethod
947 - def update(entropy_client, repository_id, force, gpg):
948 """ 949 Reimplemented from EntropyRepositoryBase. 950 """ 951 return EntropyRepositoryBase.update( 952 entropy_client, repository_id, force, gpg)
953 954 @staticmethod
955 - def revision(repository_id):
956 """ 957 Reimplemented from EntropyRepositoryBase. 958 """ 959 return EntropyRepositoryBase.revision(repository_id)
960 961 @staticmethod
962 - def remote_revision(repository_id):
963 """ 964 Reimplemented from EntropyRepositoryBase. 965 """ 966 return EntropyRepositoryBase.remote_revision(repository_id)
967
968 - def setIndexing(self, indexing):
969 """ 970 Enable or disable metadata indexing. 971 972 @param indexing: True, to enable indexing. 973 @type indexing: bool 974 """ 975 self._indexing = bool(indexing)
976
977 - def close(self, safe=False):
978 """ 979 Reimplemented from EntropyRepositoryBase. 980 Needs to call superclass method. This is a stub, 981 please implement the SQL logic. 982 """ 983 super(EntropySQLRepository, self).close(safe=safe)
984
985 - def vacuum(self):
986 """ 987 Reimplemented from EntropyRepositoryBase. 988 """ 989 raise NotImplementedError()
990
991 - def commit(self, force = False, no_plugins = False):
992 """ 993 Reimplemented from EntropyRepositoryBase. 994 Needs to call superclass method. 995 """ 996 if const_debug_enabled(): 997 const_debug_write( 998 __name__, 999 "commit(), " 1000 "force: %s, no_plugins: %s, readonly: %s | %s" % ( 1001 force, no_plugins, self.readonly(), self)) 1002 if force or not self.readonly(): 1003 # NOTE: the actual commit MUST be executed before calling 1004 # the superclass method (that is going to call EntropyRepositoryBase 1005 # plugins). This to avoid that other connection to the same exact 1006 # database file are opened and used before data is actually written 1007 # to disk, causing a tricky race condition hard to exploit. 1008 # So, FIRST commit changes, then call plugins. 1009 try: 1010 self._connection().commit() 1011 except OperationalError as err: 1012 # catch stupid sqlite3 error 1013 # 'cannot commit - no transaction is active' 1014 # and ignore. 1015 if str(err.message).find("no transaction is active") == -1: 1016 raise 1017 1018 super(EntropySQLRepository, self).commit( 1019 force = force, no_plugins = no_plugins)
1020
1021 - def rollback(self):
1022 """ 1023 Reimplemented from EntropyRepositoryBase. 1024 """ 1025 self._connection().rollback()
1026
1027 - def initializeRepository(self):
1028 """ 1029 Reimplemented from EntropyRepositoryBase. 1030 Needs to call superclass method. This is a stub, 1031 please implement the SQL logic. 1032 """ 1033 super(EntropySQLRepository, self).initializeRepository()
1034
1035 - def handlePackage(self, pkg_data, revision = None, 1036 formattedContent = False):
1037 """ 1038 Reimplemented from EntropyRepositoryBase. Raises NotImplementedError. 1039 Subclasses have to reimplement this. 1040 @raise NotImplementedError: guess what, you need to implement this. 1041 """ 1042 raise NotImplementedError()
1043
1044 - def _addCompileFlags(self, chost, cflags, cxxflags):
1045 """ 1046 NOTE: only working with _baseinfo_extrainfo_2010 disabled 1047 1048 Add package Compiler flags used to repository. 1049 Return its identifier (idflags). 1050 1051 @param chost: CHOST string 1052 @type chost: string 1053 @param cflags: CFLAGS string 1054 @type cflags: string 1055 @param cxxflags: CXXFLAGS string 1056 @type cxxflags: string 1057 @return: Compiler flags triple identifier (idflags) 1058 @rtype: int 1059 """ 1060 cur = self._cursor().execute(""" 1061 INSERT INTO flags VALUES (NULL,?,?,?) 1062 """, (chost, cflags, cxxflags,)) 1063 return cur.lastrowid
1064
1065 - def _areCompileFlagsAvailable(self, chost, cflags, cxxflags):
1066 """ 1067 NOTE: only working with _baseinfo_extrainfo_2010 disabled 1068 Return whether given Compiler FLAGS are available in repository. 1069 1070 @param chost: CHOST flag 1071 @type chost: string 1072 @param cflags: CFLAGS flag 1073 @type cflags: string 1074 @param cxxflags: CXXFLAGS flag 1075 @type cxxflags: string 1076 @return: availability (True if available) 1077 @rtype: bool 1078 """ 1079 cur = self._cursor().execute(""" 1080 SELECT idflags FROM flags WHERE chost = (?) 1081 AND cflags = (?) AND cxxflags = (?) LIMIT 1 1082 """, 1083 (chost, cflags, cxxflags,) 1084 ) 1085 result = cur.fetchone() 1086 if result: 1087 return result[0] 1088 return -1
1089
1090 - def _isLicenseAvailable(self, pkglicense):
1091 """ 1092 NOTE: only working with _baseinfo_extrainfo_2010 disabled 1093 1094 Return whether license metdatatum (NOT license name) is available 1095 in repository. 1096 1097 @param pkglicense: "license" package metadatum (returned by 1098 retrieveLicense) 1099 @type pkglicense: string 1100 @return: "license" metadatum identifier (idlicense) 1101 @rtype: int 1102 """ 1103 if not entropy.tools.is_valid_string(pkglicense): 1104 pkglicense = ' ' 1105 1106 cur = self._cursor().execute(""" 1107 SELECT idlicense FROM licenses WHERE license = (?) LIMIT 1 1108 """, (pkglicense,)) 1109 result = cur.fetchone() 1110 1111 if result: 1112 return result[0] 1113 return -1
1114
1115 - def _addLicense(self, pkglicense):
1116 """ 1117 NOTE: only working with _baseinfo_extrainfo_2010 disabled 1118 1119 Add package license name string to repository. 1120 Return its identifier (idlicense). 1121 1122 @param pkglicense: license name string 1123 @type pkglicense: string 1124 @return: license name identifier (idlicense) 1125 @rtype: int 1126 """ 1127 if not entropy.tools.is_valid_string(pkglicense): 1128 pkglicense = ' ' # workaround for broken license entries 1129 cur = self._cursor().execute(""" 1130 INSERT INTO licenses VALUES (NULL,?) 1131 """, (pkglicense,)) 1132 return cur.lastrowid
1133
1134 - def _isCategoryAvailable(self, category):
1135 """ 1136 NOTE: only working with _baseinfo_extrainfo_2010 disabled 1137 Return whether given category is available in repository. 1138 1139 @param category: category name 1140 @type category: string 1141 @return: availability (True if available) 1142 @rtype: bool 1143 """ 1144 cur = self._cursor().execute(""" 1145 SELECT idcategory FROM categories WHERE category = (?) LIMIT 1 1146 """, (category,)) 1147 result = cur.fetchone() 1148 if result: 1149 return result[0] 1150 return -1
1151
1152 - def _addCategory(self, category):
1153 """ 1154 NOTE: only working with _baseinfo_extrainfo_2010 disabled 1155 1156 Add package category string to repository. Return its identifier 1157 (idcategory). 1158 1159 @param category: name of the category to add 1160 @type category: string 1161 @return: category identifier (idcategory) 1162 @rtype: int 1163 """ 1164 cur = self._cursor().execute(""" 1165 INSERT INTO categories VALUES (NULL,?) 1166 """, (category,)) 1167 return cur.lastrowid
1168
1169 - def _addPackage(self, pkg_data, revision = -1, package_id = None, 1170 formatted_content = False):
1171 """ 1172 Reimplemented from EntropyRepositoryBase. 1173 """ 1174 if revision == -1: 1175 try: 1176 revision = int(pkg_data['revision']) 1177 except (KeyError, ValueError): 1178 pkg_data['revision'] = 0 # revision not specified 1179 revision = 0 1180 elif 'revision' not in pkg_data: 1181 pkg_data['revision'] = revision 1182 1183 _baseinfo_extrainfo_2010 = self._isBaseinfoExtrainfo2010() 1184 catid = None 1185 licid = None 1186 idflags = None 1187 if not _baseinfo_extrainfo_2010: 1188 # create new category if it doesn't exist 1189 catid = self._isCategoryAvailable(pkg_data['category']) 1190 if catid == -1: 1191 catid = self._addCategory(pkg_data['category']) 1192 1193 # create new license if it doesn't exist 1194 licid = self._isLicenseAvailable(pkg_data['license']) 1195 if licid == -1: 1196 licid = self._addLicense(pkg_data['license']) 1197 1198 idflags = self._areCompileFlagsAvailable(pkg_data['chost'], 1199 pkg_data['cflags'], pkg_data['cxxflags']) 1200 if idflags == -1: 1201 idflags = self._addCompileFlags(pkg_data['chost'], 1202 pkg_data['cflags'], pkg_data['cxxflags']) 1203 1204 idprotect = self._isProtectAvailable(pkg_data['config_protect']) 1205 if idprotect == -1: 1206 idprotect = self._addProtect(pkg_data['config_protect']) 1207 1208 idprotect_mask = self._isProtectAvailable( 1209 pkg_data['config_protect_mask']) 1210 if idprotect_mask == -1: 1211 idprotect_mask = self._addProtect( 1212 pkg_data['config_protect_mask']) 1213 1214 trigger = 0 1215 if pkg_data['trigger']: 1216 trigger = 1 1217 1218 # baseinfo 1219 pkgatom = entropy.dep.create_package_atom_string( 1220 pkg_data['category'], pkg_data['name'], pkg_data['version'], 1221 pkg_data['versiontag']) 1222 # add atom metadatum 1223 pkg_data['atom'] = pkgatom 1224 1225 if not _baseinfo_extrainfo_2010: 1226 mybaseinfo_data = (pkgatom, catid, pkg_data['name'], 1227 pkg_data['version'], pkg_data['versiontag'], revision, 1228 pkg_data['branch'], pkg_data['slot'], 1229 licid, pkg_data['etpapi'], trigger, 1230 ) 1231 else: 1232 mybaseinfo_data = (pkgatom, pkg_data['category'], pkg_data['name'], 1233 pkg_data['version'], pkg_data['versiontag'], revision, 1234 pkg_data['branch'], pkg_data['slot'], 1235 pkg_data['license'], pkg_data['etpapi'], trigger, 1236 ) 1237 1238 mypackage_id_string = 'NULL' 1239 if package_id is not None: 1240 1241 manual_deps = self.retrieveManualDependencies(package_id, 1242 resolve_conditional_deps = False) 1243 1244 # does it exist? 1245 self.removePackage(package_id, from_add_package = True) 1246 mypackage_id_string = '?' 1247 mybaseinfo_data = (package_id,)+mybaseinfo_data 1248 1249 # merge old manual dependencies 1250 m_dep_id = etpConst['dependency_type_ids']['mdepend_id'] 1251 1252 for manual_dep in manual_deps: 1253 pkg_data['pkg_dependencies'] += ((manual_dep, m_dep_id),) 1254 1255 cur = self._cursor().execute(""" 1256 INSERT INTO baseinfo VALUES 1257 (%s, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""" % ( 1258 mypackage_id_string,), mybaseinfo_data) 1259 if package_id is None: 1260 package_id = cur.lastrowid 1261 1262 # extrainfo 1263 if not _baseinfo_extrainfo_2010: 1264 self._cursor().execute( 1265 'INSERT INTO extrainfo VALUES (?, ?, ?, ?, ?, ?, ?, ?)', 1266 ( package_id, 1267 pkg_data['description'], 1268 pkg_data['homepage'], 1269 pkg_data['download'], 1270 pkg_data['size'], 1271 idflags, 1272 pkg_data['digest'], 1273 pkg_data['datecreation'], 1274 ) 1275 ) 1276 else: 1277 self._cursor().execute( 1278 'INSERT INTO extrainfo VALUES (?,?,?,?,?,?,?,?,?,?)', 1279 ( package_id, 1280 pkg_data['description'], 1281 pkg_data['homepage'], 1282 pkg_data['download'], 1283 pkg_data['size'], 1284 pkg_data['chost'], 1285 pkg_data['cflags'], 1286 pkg_data['cxxflags'], 1287 pkg_data['digest'], 1288 pkg_data['datecreation'], 1289 ) 1290 ) 1291 # baseinfo and extrainfo are tainted 1292 self.clearCache() 1293 ### other information iserted below are not as 1294 ### critical as these above 1295 1296 if "needed_libs" in pkg_data: 1297 needed_libs = pkg_data['needed_libs'] 1298 else: # needed, kept for backward compatibility. 1299 needed_libs = [("", "", soname, elfclass, "") 1300 for soname, elfclass in pkg_data['needed']] 1301 self._insertNeededLibs(package_id, needed_libs) 1302 1303 self.insertDependencies(package_id, pkg_data['pkg_dependencies']) 1304 1305 self._insertSources(package_id, pkg_data['sources']) 1306 self._insertUseflags(package_id, pkg_data['useflags']) 1307 self._insertKeywords(package_id, pkg_data['keywords']) 1308 self._insertLicenses(pkg_data['licensedata']) 1309 self._insertMirrors(pkg_data['mirrorlinks']) 1310 1311 # packages and file association metadata 1312 desktop_mime = pkg_data.get('desktop_mime') 1313 if desktop_mime: 1314 self._insertDesktopMime(package_id, desktop_mime) 1315 provided_mime = pkg_data.get('provided_mime') 1316 if provided_mime: 1317 self._insertProvidedMime(package_id, provided_mime) 1318 1319 # package ChangeLog 1320 if pkg_data.get('changelog'): 1321 self._insertChangelog(pkg_data['category'], pkg_data['name'], 1322 pkg_data['changelog']) 1323 # package signatures 1324 if pkg_data.get('signatures'): 1325 signatures = pkg_data['signatures'] 1326 sha1, sha256, sha512, gpg = signatures['sha1'], \ 1327 signatures['sha256'], signatures['sha512'], \ 1328 signatures.get('gpg') 1329 self._insertSignatures(package_id, sha1, sha256, sha512, 1330 gpg = gpg) 1331 1332 # extra package download URLs 1333 if pkg_data.get('extra_download'): 1334 extra_download = pkg_data['extra_download'] 1335 self._insertExtraDownload(package_id, extra_download) 1336 1337 if pkg_data.get('provided_libs'): 1338 self._insertProvidedLibraries( 1339 package_id, pkg_data['provided_libs']) 1340 1341 # spm phases 1342 if pkg_data.get('spm_phases') is not None: 1343 self._insertSpmPhases(package_id, pkg_data['spm_phases']) 1344 1345 if pkg_data.get('spm_repository') is not None: 1346 self._insertSpmRepository( 1347 package_id, pkg_data['spm_repository']) 1348 1349 # not depending on other tables == no select done 1350 self.insertContent(package_id, pkg_data['content'], 1351 already_formatted = formatted_content) 1352 # insert content safety metadata (checksum, mtime) 1353 # if metadatum exists 1354 content_safety = pkg_data.get('content_safety') 1355 if content_safety is not None: 1356 self._insertContentSafety(package_id, content_safety) 1357 1358 # handle SPM UID<->package_id binding 1359 pkg_data['counter'] = int(pkg_data['counter']) 1360 if not pkg_data['injected'] and (pkg_data['counter'] != -1): 1361 pkg_data['counter'] = self._bindSpmPackageUid( 1362 package_id, pkg_data['counter'], pkg_data['branch']) 1363 1364 self._insertOnDiskSize(package_id, pkg_data['disksize']) 1365 if pkg_data['trigger']: 1366 self._insertTrigger(package_id, pkg_data['trigger']) 1367 self.insertConflicts(package_id, pkg_data['conflicts']) 1368 1369 self._insertProvide(package_id, pkg_data['provide_extended']) 1370 1371 self._insertConfigProtect(package_id, idprotect) 1372 self._insertConfigProtect(package_id, idprotect_mask, mask = True) 1373 # injected? 1374 if pkg_data.get('injected'): 1375 self.setInjected(package_id) 1376 # is it a system package? 1377 if pkg_data.get('systempackage'): 1378 self._setSystemPackage(package_id) 1379 1380 # this will always be optional ! 1381 # (see entropy.client.interfaces.package) 1382 original_repository = pkg_data.get('original_repository') 1383 if original_repository is not None: 1384 self.storeInstalledPackage(package_id, original_repository) 1385 1386 # baseinfo and extrainfo are tainted 1387 # ensure that cache is clear even here 1388 self.clearCache() 1389 1390 return package_id
1391
1392 - def addPackage(self, pkg_data, revision = -1, package_id = None, 1393 formatted_content = False):
1394 """ 1395 Reimplemented from EntropyRepositoryBase. 1396 Needs to call superclass method. 1397 """ 1398 try: 1399 package_id = self._addPackage(pkg_data, revision = revision, 1400 package_id = package_id, 1401 formatted_content = formatted_content) 1402 super(EntropySQLRepository, self).addPackage( 1403 pkg_data, revision = revision, 1404 package_id = package_id, 1405 formatted_content = formatted_content) 1406 return package_id 1407 except: 1408 self._connection().rollback() 1409 raise
1410
1411 - def removePackage(self, package_id, from_add_package = False):
1412 """ 1413 Reimplemented from EntropyRepositoryBase. 1414 Needs to call superclass method. 1415 """ 1416 try: 1417 self.clearCache() 1418 super(EntropySQLRepository, self).removePackage( 1419 package_id, from_add_package = from_add_package) 1420 self.clearCache() 1421 1422 return self._removePackage(package_id, 1423 from_add_package = from_add_package) 1424 except: 1425 self._connection().rollback() 1426 raise
1427
1428 - def _removePackage(self, package_id, from_add_package = False):
1429 """ 1430 Reimplemented from EntropyRepositoryBase. 1431 This method uses "ON DELETE CASCADE" to implement quick 1432 and reliable package removal. 1433 """ 1434 self._cursor().execute( 1435 "DELETE FROM baseinfo WHERE idpackage = ?", (package_id,))
1436
1437 - def _removeMirrorEntries(self, mirrorname):
1438 """ 1439 Remove source packages mirror entries from database for the given 1440 mirror name. This is a representation of Portage's "thirdpartymirrors". 1441 1442 @param mirrorname: mirror name 1443 @type mirrorname: string 1444 """ 1445 self._cursor().execute(""" 1446 DELETE FROM mirrorlinks WHERE mirrorname = ? 1447 """, (mirrorname,))
1448
1449 - def _addMirrors(self, mirrorname, mirrorlist):
1450 """ 1451 Add source package mirror entry to database. 1452 This is a representation of Portage's "thirdpartymirrors". 1453 1454 @param mirrorname: name of the mirror from which "mirrorlist" belongs 1455 @type mirrorname: string 1456 @param mirrorlist: list of URLs belonging to the given mirror name 1457 @type mirrorlist: list 1458 """ 1459 self._cursor().executemany(""" 1460 INSERT INTO mirrorlinks VALUES (?, ?) 1461 """, [(mirrorname, x,) for x in mirrorlist])
1462
1463 - def _addProtect(self, protect):
1464 """ 1465 Add a single, generic CONFIG_PROTECT (not defined as _MASK/whatever 1466 here) path. Return its identifier (idprotect). 1467 1468 @param protect: CONFIG_PROTECT path to add 1469 @type protect: string 1470 @return: protect identifier (idprotect) 1471 @rtype: int 1472 """ 1473 cur = self._cursor().execute(""" 1474 INSERT INTO configprotectreference VALUES (NULL, ?) 1475 """, (protect,)) 1476 return cur.lastrowid
1477
1478 - def _addSource(self, source):
1479 """ 1480 Add source code package download path to repository. Return its 1481 identifier (idsource). 1482 1483 @param source: source package download path 1484 @type source: string 1485 @return: source identifier (idprotect) 1486 @rtype: int 1487 """ 1488 cur = self._cursor().execute(""" 1489 INSERT INTO sourcesreference VALUES (NULL, ?) 1490 """, (source,)) 1491 return cur.lastrowid
1492
1493 - def _addDependency(self, dependency):
1494 """ 1495 Add dependency string to repository. Return its identifier 1496 (iddependency). 1497 1498 @param dependency: dependency string 1499 @type dependency: string 1500 @return: dependency identifier (iddependency) 1501 @rtype: int 1502 """ 1503 cur = self._cursor().execute(""" 1504 INSERT INTO dependenciesreference VALUES (NULL, ?) 1505 """, (dependency,)) 1506 return cur.lastrowid
1507
1508 - def _addKeyword(self, keyword):
1509 """ 1510 Add package SPM keyword string to repository. 1511 Return its identifier (idkeyword). 1512 1513 @param keyword: keyword string 1514 @type keyword: string 1515 @return: keyword identifier (idkeyword) 1516 @rtype: int 1517 """ 1518 cur = self._cursor().execute(""" 1519 INSERT INTO keywordsreference VALUES (NULL, ?) 1520 """, (keyword,)) 1521 return cur.lastrowid
1522
1523 - def _addUseflag(self, useflag):
1524 """ 1525 Add package USE flag string to repository. 1526 Return its identifier (iduseflag). 1527 1528 @param useflag: useflag string 1529 @type useflag: string 1530 @return: useflag identifier (iduseflag) 1531 @rtype: int 1532 """ 1533 cur = self._cursor().execute(""" 1534 INSERT INTO useflagsreference VALUES (NULL, ?) 1535 """, (useflag,)) 1536 return cur.lastrowid
1537
1538 - def _setSystemPackage(self, package_id):
1539 """ 1540 Mark a package as system package, which means that entropy.client 1541 will deny its removal. 1542 1543 @param package_id: package identifier 1544 @type package_id: int 1545 """ 1546 self._cursor().execute(""" 1547 INSERT INTO systempackages VALUES (?) 1548 """, (package_id,))
1549
1550 - def setInjected(self, package_id):
1551 """ 1552 Reimplemented from EntropyRepositoryBase. 1553 """ 1554 if not self.isInjected(package_id): 1555 self._cursor().execute(""" 1556 INSERT INTO injected VALUES (?) 1557 """, (package_id,))
1558
1559 - def setCreationDate(self, package_id, date):
1560 """ 1561 Reimplemented from EntropyRepositoryBase. 1562 """ 1563 self._cursor().execute(""" 1564 UPDATE extrainfo SET datecreation = ? WHERE idpackage = ? 1565 """, (str(date), package_id,))
1566
1567 - def setDigest(self, package_id, digest):
1568 """ 1569 Reimplemented from EntropyRepositoryBase. 1570 """ 1571 self._cursor().execute(""" 1572 UPDATE extrainfo SET digest = ? WHERE idpackage = ? 1573 """, (digest, package_id,))
1574
1575 - def setSignatures(self, package_id, sha1, sha256, sha512, gpg = None):
1576 """ 1577 Reimplemented from EntropyRepositoryBase. 1578 """ 1579 self._cursor().execute(""" 1580 UPDATE packagesignatures SET sha1 = ?, sha256 = ?, sha512 = ?, 1581 gpg = ? WHERE idpackage = ? 1582 """, (sha1, sha256, sha512, gpg, package_id))
1583
1584 - def setDownloadURL(self, package_id, url):
1585 """ 1586 Set download URL prefix for package. 1587 1588 @param package_id: package indentifier 1589 @type package_id: int 1590 @param url: URL prefix to set 1591 @type url: string 1592 """ 1593 self._cursor().execute(""" 1594 UPDATE extrainfo SET download = ? WHERE idpackage = ? 1595 """, (url, package_id,))
1596
1597 - def setCategory(self, package_id, category):
1598 """ 1599 Reimplemented from EntropyRepositoryBase. 1600 """ 1601 self._cursor().execute(""" 1602 UPDATE baseinfo SET category = ? WHERE idpackage = ? 1603 """, (category, package_id,))
1604
1605 - def setCategoryDescription(self, category, description_data):
1606 """ 1607 Reimplemented from EntropyRepositoryBase. 1608 """ 1609 self._cursor().execute(""" 1610 DELETE FROM categoriesdescription WHERE category = ? 1611 """, (category,)) 1612 for locale in description_data: 1613 mydesc = description_data[locale] 1614 self._cursor().execute(""" 1615 INSERT INTO categoriesdescription VALUES (?, ?, ?) 1616 """, (category, locale, mydesc,))
1617
1618 - def setName(self, package_id, name):
1619 """ 1620 Reimplemented from EntropyRepositoryBase. 1621 """ 1622 self._cursor().execute(""" 1623 UPDATE baseinfo SET name = ? WHERE idpackage = ? 1624 """, (name, package_id,))
1625
1626 - def setDependency(self, iddependency, dependency):
1627 """ 1628 Reimplemented from EntropyRepositoryBase. 1629 """ 1630 self._cursor().execute(""" 1631 UPDATE dependenciesreference SET dependency = ? 1632 WHERE iddependency = ? 1633 """, (dependency, iddependency,))
1634
1635 - def setAtom(self, package_id, atom):
1636 """ 1637 Reimplemented from EntropyRepositoryBase. 1638 """ 1639 self._cursor().execute(""" 1640 UPDATE baseinfo SET atom = ? WHERE idpackage = ? 1641 """, (atom, package_id,))
1642
1643 - def setSlot(self, package_id, slot):
1644 """ 1645 Reimplemented from EntropyRepositoryBase. 1646 """ 1647 self._cursor().execute(""" 1648 UPDATE baseinfo SET slot = ? WHERE idpackage = ? 1649 """, (slot, package_id,))
1650
1651 - def setRevision(self, package_id, revision):
1652 """ 1653 Reimplemented from EntropyRepositoryBase. 1654 """ 1655 self._cursor().execute(""" 1656 UPDATE baseinfo SET revision = ? WHERE idpackage = ? 1657 """, (revision, package_id,))
1658
1659 - def removeDependencies(self, package_id):
1660 """ 1661 Reimplemented from EntropyRepositoryBase. 1662 """ 1663 self._cursor().execute(""" 1664 DELETE FROM dependencies WHERE idpackage = ? 1665 """, (package_id,))
1666
1667 - def insertDependencies(self, package_id, depdata):
1668 """ 1669 Reimplemented from EntropyRepositoryBase. 1670 """ 1671 1672 def insert_list(): 1673 deps = [] 1674 1675 for dep in depdata: 1676 deptype = 0 1677 1678 if isinstance(depdata, dict): 1679 deptype = depdata[dep] 1680 elif not isinstance(dep, const_get_stringtype()): 1681 dep, deptype = dep 1682 1683 iddep = self._isDependencyAvailable(dep) 1684 if iddep == -1: 1685 iddep = self._addDependency(dep) 1686 1687 deps.append((package_id, iddep, deptype,)) 1688 1689 return deps
1690 1691 self._cursor().executemany(""" 1692 INSERT INTO dependencies VALUES (?, ?, ?) 1693 """, insert_list())
1694
1695 - def removeConflicts(self, package_id):
1696 """ 1697 Remove all the conflicts of package. 1698 1699 @param package_id: package indentifier 1700 @type package_id: int 1701 """ 1702 self._cursor().execute(""" 1703 DELETE FROM conflicts WHERE idpackage = ? 1704 """, (package_id,))
1705
1706 - def insertConflicts(self, package_id, conflicts):
1707 """ 1708 Insert dependency conflicts for package. 1709 1710 @param package_id: package indentifier 1711 @type package_id: int 1712 @param conflicts: list of dep. conflicts 1713 @type conflicts: list 1714 """ 1715 self._cursor().executemany(""" 1716 INSERT INTO conflicts VALUES (?, ?) 1717 """, [(package_id, x,) for x in conflicts])
1718
1719 - def insertContent(self, package_id, content, already_formatted = False):
1720 """ 1721 Reimplemented from EntropyRepositoryBase. 1722 """ 1723 # respect iterators, so that if they're true iterators 1724 # we save a lot of memory. 1725 class MyIter: 1726 1727 def __init__(self, _package_id, _content, _already_fmt): 1728 self._package_id = _package_id 1729 self._content = _content 1730 self._already_fmt = _already_fmt 1731 self._iter = iter(self._content)
1732 1733 def __iter__(self): 1734 # reinit iter 1735 self._iter = iter(self._content) 1736 return self 1737 1738 def __next__(self): 1739 if self._already_fmt: 1740 a, x, y = next(self._iter) 1741 return self._package_id, x, y 1742 else: 1743 x = next(self._iter) 1744 return self._package_id, x, self._content[x] 1745 1746 def next(self): 1747 if self._already_fmt: 1748 a, x, y = self._iter.next() 1749 return self._package_id, x, y 1750 else: 1751 x = self._iter.next() 1752 return self._package_id, x, self._content[x] 1753 1754 if already_formatted: 1755 self._cursor().executemany(""" 1756 INSERT INTO content VALUES (?, ?, ?) 1757 """, MyIter(package_id, content, already_formatted)) 1758 else: 1759 self._cursor().executemany(""" 1760 INSERT INTO content VALUES (?, ?, ?) 1761 """, MyIter(package_id, content, already_formatted)) 1762
1763 - def _insertContentSafety(self, package_id, content_safety):
1764 """ 1765 Currently supported: sha256, mtime. 1766 Insert into contentsafety table package files sha256sum and mtime. 1767 """ 1768 if isinstance(content_safety, dict): 1769 self._cursor().executemany(""" 1770 INSERT INTO contentsafety VALUES (?, ?, ?, ?) 1771 """, [(package_id, k, v['mtime'], v['sha256']) \ 1772 for k, v in content_safety.items()]) 1773 else: 1774 # support for iterators containing tuples like this: 1775 # (path, sha256, mtime) 1776 class MyIterWrapper: 1777 def __init__(self, _iter): 1778 self._iter = iter(_iter)
1779 1780 def __iter__(self): 1781 # reinit iter 1782 self._iter = iter(self._iter) 1783 return self 1784 1785 def __next__(self): 1786 path, sha256, mtime = next(self._iter) 1787 # this is the insert order, with mtime 1788 # and sha256 swapped. 1789 return package_id, path, mtime, sha256 1790 1791 def next(self): 1792 path, sha256, mtime = self._iter.next() 1793 # this is the insert order, with mtime 1794 # and sha256 swapped. 1795 return package_id, path, mtime, sha256 1796 1797 self._cursor().executemany(""" 1798 INSERT INTO contentsafety VALUES (?, ?, ?, ?) 1799 """, MyIterWrapper(content_safety)) 1800
1801 - def _insertProvidedLibraries(self, package_id, libs_metadata):
1802 """ 1803 Insert library metadata owned by package. 1804 1805 @param package_id: package indentifier 1806 @type package_id: int 1807 @param libs_metadata: provided library metadata composed by list of 1808 tuples of length 3 containing library name, path and ELF class. 1809 @type libs_metadata: list 1810 """ 1811 self._cursor().executemany(""" 1812 INSERT INTO provided_libs VALUES (?, ?, ?, ?) 1813 """, [(package_id, x, y, z,) for x, y, z in libs_metadata])
1814
1815 - def insertAutomergefiles(self, package_id, automerge_data):
1816 """ 1817 Reimplemented from EntropyRepositoryBase. 1818 """ 1819 self._cursor().executemany(""" 1820 INSERT INTO automergefiles VALUES (?, ?, ?)""", 1821 [(package_id, x, y,) for x, y in automerge_data])
1822
1823 - def _insertChangelog(self, category, name, changelog_txt):
1824 """ 1825 Insert package changelog for package (in this case using category + 1826 name as key). 1827 1828 @param category: package category 1829 @type category: string 1830 @param name: package name 1831 @type name: string 1832 @param changelog_txt: changelog text 1833 @type changelog_txt: string 1834 """ 1835 mytxt = changelog_txt.encode('raw_unicode_escape') 1836 1837 self._cursor().execute(""" 1838 DELETE FROM packagechangelogs WHERE category = ? AND name = ? 1839 """, (category, name,)) 1840 1841 self._cursor().execute(""" 1842 INSERT INTO packagechangelogs VALUES (?, ?, ?) 1843 """, (category, name, const_get_buffer()(mytxt),))
1844
1845 - def _insertLicenses(self, licenses_data):
1846 """ 1847 insert license data (license names and text) into repository. 1848 1849 @param licenses_data: dictionary containing license names as keys and 1850 text as values 1851 @type licenses_data: dict 1852 """ 1853 1854 mylicenses = list(licenses_data.keys()) 1855 def my_mf(mylicense): 1856 return not self.isLicenseDataKeyAvailable(mylicense)
1857 1858 def my_mm(mylicense): 1859 1860 lic_data = licenses_data.get(mylicense, '') 1861 1862 # support both utf8 and str input 1863 if const_isunicode(lic_data): # encode to str 1864 try: 1865 lic_data = lic_data.encode('raw_unicode_escape') 1866 except (UnicodeDecodeError,): 1867 lic_data = lic_data.encode('utf-8') 1868 1869 return (mylicense, const_get_buffer()(lic_data), 0,) 1870 1871 # set() used after filter to remove duplicates 1872 self._cursor().executemany(""" 1873 %s INTO licensedata VALUES (?, ?, ?) 1874 """ % (self._INSERT_OR_REPLACE,), 1875 list(map(my_mm, set(filter(my_mf, mylicenses))))) 1876
1877 - def _insertConfigProtect(self, package_id, idprotect, mask = False):
1878 """ 1879 Insert CONFIG_PROTECT (configuration files protection) entry identifier 1880 for package. This entry is usually a space separated string of directory 1881 and files which are used to handle user-protected configuration files 1882 or directories, those that are going to be stashed in separate paths 1883 waiting for user merge decisions. 1884 1885 @param package_id: package indentifier 1886 @type package_id: int 1887 @param idprotect: configuration files protection identifier 1888 @type idprotect: int 1889 @keyword mask: if True, idproctect will be considered a "mask" entry, 1890 meaning that configuration files starting with paths referenced 1891 by idprotect will be forcefully merged. 1892 @type mask: bool 1893 """ 1894 1895 mytable = 'configprotect' 1896 if mask: 1897 mytable += 'mask' 1898 self._cursor().execute(""" 1899 INSERT INTO %s VALUES (?, ?) 1900 """ % (mytable,), (package_id, idprotect,))
1901
1902 - def _insertMirrors(self, mirrors):
1903 """ 1904 Insert list of "mirror name" and "mirror list" into repository. 1905 The term "mirror" in this case references to Source Package Manager 1906 package download mirrors. 1907 Argument format is like this for historical reasons and may change in 1908 future. 1909 1910 @todo: change argument format 1911 @param mirrors: list of tuples of length 2 containing string as first 1912 item and list as second. 1913 [('openoffice', ['http://openoffice1', 'http://..."],), ...] 1914 @type mirrors: list 1915 """ 1916 1917 for mirrorname, mirrorlist in mirrors: 1918 # remove old 1919 self._removeMirrorEntries(mirrorname) 1920 # add new 1921 self._addMirrors(mirrorname, mirrorlist)
1922
1923 - def _insertKeywords(self, package_id, keywords):
1924 """ 1925 Insert keywords for package. Keywords are strings contained in package 1926 metadata stating what architectures or subarchitectures are supported 1927 by package. It is historically used also for masking packages (making 1928 them not available). 1929 1930 @param package_id: package indentifier 1931 @type package_id: int 1932 @param keywords: list of keywords 1933 @type keywords: list 1934 """ 1935 1936 def mymf(key): 1937 idkeyword = self._isKeywordAvailable(key) 1938 if idkeyword == -1: 1939 # create category 1940 idkeyword = self._addKeyword(key) 1941 return (package_id, idkeyword,)
1942 1943 self._cursor().executemany(""" 1944 INSERT INTO keywords VALUES (?, ?) 1945 """, list(map(mymf, keywords))) 1946
1947 - def _insertUseflags(self, package_id, useflags):
1948 """ 1949 Insert Source Package Manager USE (components build) flags for package. 1950 1951 @param package_id: package indentifier 1952 @type package_id: int 1953 @param useflags: list of use flags strings 1954 @type useflags: list 1955 """ 1956 1957 def mymf(flag): 1958 iduseflag = self._isUseflagAvailable(flag) 1959 if iduseflag == -1: 1960 # create category 1961 iduseflag = self._addUseflag(flag) 1962 return (package_id, iduseflag,)
1963 1964 self._cursor().executemany(""" 1965 INSERT INTO useflags VALUES (?, ?) 1966 """, list(map(mymf, useflags))) 1967
1968 - def _insertSignatures(self, package_id, sha1, sha256, sha512, gpg = None):
1969 """ 1970 Insert package file extra hashes (sha1, sha256, sha512) for package. 1971 1972 @param package_id: package indentifier 1973 @type package_id: int 1974 @param sha1: SHA1 hash for package file 1975 @type sha1: string 1976 @param sha256: SHA256 hash for package file 1977 @type sha256: string 1978 @param sha512: SHA512 hash for package file 1979 @type sha512: string 1980 @keyword gpg: GPG signature file content 1981 @type gpg: string 1982 """ 1983 self._cursor().execute(""" 1984 INSERT INTO packagesignatures VALUES (?, ?, ?, ?, ?) 1985 """, (package_id, sha1, sha256, sha512, gpg))
1986
1987 - def _insertExtraDownload(self, package_id, package_downloads_data):
1988 """ 1989 Insert extra package files download objects to repository. 1990 1991 @param package_id: package indentifier 1992 @type package_id: int 1993 @param package_downloads_data: list of dict composed by 1994 (download, type, size, md5, sha1, sha256, sha512, gpg) as keys 1995 @type package_downloads_data: list 1996 """ 1997 self._cursor().executemany(""" 1998 INSERT INTO packagedownloads VALUES 1999 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 2000 """, [(package_id, edw['download'], edw['type'], edw['size'], 2001 edw['disksize'], edw['md5'], edw['sha1'], edw['sha256'], 2002 edw['sha512'], edw['gpg']) for edw in \ 2003 package_downloads_data])
2004
2005 - def _insertDesktopMime(self, package_id, metadata):
2006 """ 2007 Insert file association information for package. 2008 2009 @param package_id: package indentifier 2010 @type package_id: int 2011 @param metadata: list of dict() containing file association metadata 2012 @type metadata: list 2013 """ 2014 mime_data = [(package_id, x['name'], 2015 x['mimetype'], x['executable'], 2016 x['icon']) for x in metadata] 2017 self._cursor().executemany(""" 2018 INSERT INTO packagedesktopmime VALUES (?, ?, ?, ?, ?) 2019 """, mime_data)
2020
2021 - def _insertProvidedMime(self, package_id, mimetypes):
2022 """ 2023 Insert file association information for package in a way useful for 2024 making direct and inverse queries (having a mimetype or having a 2025 package identifier) 2026 2027 @param package_id: package indentifier 2028 @type package_id: int 2029 @param mimetypes: list of mimetypes supported by package 2030 @type mimetypes: list 2031 """ 2032 self._cursor().executemany(""" 2033 INSERT INTO provided_mime VALUES (?, ?)""", 2034 [(x, package_id) for x in mimetypes])
2035
2036 - def _insertSpmPhases(self, package_id, phases):
2037 """ 2038 Insert Source Package Manager phases for package. 2039 Entropy can call several Source Package Manager (the PM which Entropy 2040 relies on) package installation/removal phases. 2041 Such phase names are listed here. 2042 2043 @param package_id: package indentifier 2044 @type package_id: int 2045 @param phases: list of available Source Package Manager phases 2046 @type phases: list 2047 """ 2048 self._cursor().execute(""" 2049 INSERT INTO packagespmphases VALUES (?, ?) 2050 """, (package_id, phases,))
2051
2052 - def _insertSpmRepository(self, package_id, repository):
2053 """ 2054 Insert Source Package Manager repository for package. 2055 This medatatum describes the source repository where package has 2056 been compiled from. 2057 2058 @param package_id: package indentifier 2059 @type package_id: int 2060 @param repository: Source Package Manager repository 2061 @type repository: string 2062 """ 2063 self._cursor().execute(""" 2064 INSERT INTO packagespmrepository VALUES (?, ?) 2065 """, (package_id, repository,))
2066
2067 - def _insertSources(self, package_id, sources):
2068 """ 2069 Insert source code package download URLs for package_id. 2070 2071 @param package_id: package indentifier 2072 @type package_id: int 2073 @param sources: list of source URLs 2074 @type sources: list 2075 """ 2076 def mymf(source): 2077 2078 if (not source) or \ 2079 (not entropy.tools.is_valid_string(source)): 2080 return 0 2081 2082 idsource = self._isSourceAvailable(source) 2083 if idsource == -1: 2084 idsource = self._addSource(source) 2085 2086 return (package_id, idsource,)
2087 2088 self._cursor().executemany(""" 2089 INSERT INTO sources VALUES (?, ?) 2090 """, [x for x in map(mymf, sources) if x != 0]) 2091
2092 - def _insertProvide(self, package_id, provides):
2093 """ 2094 Insert PROVIDE metadata for package_id. 2095 This has been added for supporting Portage Source Package Manager 2096 old-style meta-packages support. 2097 Packages can provide extra atoms, you can see it like aliases, where 2098 these can be given by multiple packages. This allowed to make available 2099 multiple applications providing the same functionality which depending 2100 packages can reference, without forcefully being bound to a single 2101 package. 2102 2103 @param package_id: package indentifier 2104 @type package_id: int 2105 @param provides: list of atom strings 2106 @type provides: list 2107 """ 2108 default_provides = [x for x in provides if x[1]] 2109 2110 self._cursor().executemany(""" 2111 INSERT INTO provide VALUES (?, ?, ?) 2112 """, [(package_id, x, y,) for x, y in provides]) 2113 2114 if default_provides: 2115 # reset previously set default provides 2116 self._cursor().executemany(""" 2117 UPDATE provide SET is_default=0 WHERE atom = ? AND 2118 idpackage != ? 2119 """, default_provides)
2120
2121 - def _insertNeededLibs(self, package_id, needed_libs):
2122 """ 2123 Insert package libraries' ELF object NEEDED string for package. 2124 2125 @param package_id: package indentifier 2126 @type package_id: int 2127 @param needed_libs: list of tuples composed of: 2128 (library user path, library user soname, soname, elfclass, rpath) 2129 @type needed_libs: list 2130 """ 2131 self._cursor().executemany(""" 2132 INSERT INTO needed_libs VALUES (?, ?, ?, ?, ?, ?) 2133 """, [(package_id,) + tuple(x) for x in needed_libs])
2134
2135 - def _insertOnDiskSize(self, package_id, mysize):
2136 """ 2137 Insert on-disk size (bytes) for package. 2138 2139 @param package_id: package indentifier 2140 @type package_id: int 2141 @param mysize: package size (bytes) 2142 @type mysize: int 2143 """ 2144 self._cursor().execute(""" 2145 INSERT INTO sizes VALUES (?, ?) 2146 """, (package_id, mysize,))
2147
2148 - def _insertTrigger(self, package_id, trigger):
2149 """ 2150 Insert built-in trigger script for package, containing 2151 pre-install, post-install, pre-remove, post-remove hooks. 2152 This feature should be considered DEPRECATED, and kept for convenience. 2153 Please use Source Package Manager features if possible. 2154 2155 @param package_id: package indentifier 2156 @type package_id: int 2157 @param trigger: trigger file dump 2158 @type trigger: string 2159 """ 2160 self._cursor().execute(""" 2161 INSERT INTO triggers VALUES (?, ?) 2162 """, (package_id, const_get_buffer()(trigger),))
2163
2164 - def insertPreservedLibrary(self, library, elfclass, path, atom):
2165 """ 2166 Reimplemented from EntropyRepositoryBase. 2167 """ 2168 self._cursor().execute(""" 2169 %s INTO preserved_libs VALUES (?, ?, ?, ?) 2170 """ % (self._INSERT_OR_REPLACE,), (library, elfclass, path, atom))
2171
2172 - def removePreservedLibrary(self, library, elfclass, path):
2173 """ 2174 Reimplemented from EntropyRepositoryBase. 2175 """ 2176 self._cursor().execute(""" 2177 DELETE FROM preserved_libs 2178 WHERE library = ? AND elfclass = ? AND path = ? 2179 """, (library, elfclass, path))
2180
2181 - def listAllPreservedLibraries(self):
2182 """ 2183 Reimplemented from EntropyRepositoryBase. 2184 """ 2185 cur = self._cursor().execute(""" 2186 SELECT library, elfclass, path, atom FROM preserved_libs 2187 """) 2188 return tuple(cur)
2189
2190 - def retrievePreservedLibraries(self, library, elfclass):
2191 """ 2192 Reimplemented from EntropyRepositoryBase. 2193 """ 2194 cur = self._cursor().execute(""" 2195 SELECT path FROM preserved_libs WHERE library = ? AND elfclass = ? 2196 """, (library, elfclass)) 2197 return self._cur2tuple(cur)
2198
2199 - def insertBranchMigration(self, repository, from_branch, to_branch, 2200 post_migration_md5sum, post_upgrade_md5sum):
2201 """ 2202 Reimplemented from EntropyRepositoryBase. 2203 """ 2204 self._cursor().execute(""" 2205 %s INTO entropy_branch_migration VALUES (?,?,?,?,?) 2206 """ % (self._INSERT_OR_REPLACE,), ( 2207 repository, from_branch, 2208 to_branch, post_migration_md5sum, 2209 post_upgrade_md5sum, 2210 ) 2211 )
2212
2213 - def setBranchMigrationPostUpgradeMd5sum(self, repository, from_branch, 2214 to_branch, post_upgrade_md5sum):
2215 """ 2216 Reimplemented from EntropyRepositoryBase. 2217 """ 2218 self._cursor().execute(""" 2219 UPDATE entropy_branch_migration SET post_upgrade_md5sum = ? WHERE 2220 repository = ? AND from_branch = ? AND to_branch = ? 2221 """, (post_upgrade_md5sum, repository, from_branch, to_branch,))
2222
2223 - def _bindSpmPackageUid(self, package_id, spm_package_uid, branch):
2224 """ 2225 Bind Source Package Manager package identifier ("COUNTER" metadata 2226 for Portage) to Entropy package. 2227 If uid <= -2, a new negative UID will be allocated and returned. 2228 Negative UIDs are considered auto-allocated by Entropy. 2229 This is mainly used for binary packages not belonging to any SPM 2230 packages which are just "injected" inside the repository. 2231 2232 @param package_id: package indentifier 2233 @type package_id: int 2234 @param spm_package_uid: Source package Manager unique package identifier 2235 @type spm_package_uid: int 2236 @param branch: current running Entropy branch 2237 @type branch: string 2238 @return: uid set 2239 @rtype: int 2240 """ 2241 my_uid = spm_package_uid 2242 if my_uid <= -2: 2243 # special cases 2244 my_uid = self.getFakeSpmUid() 2245 2246 self._cursor().execute(""" 2247 INSERT INTO counters VALUES (?, ?, ?) 2248 """, (my_uid, package_id, branch,)) 2249 2250 return my_uid
2251
2252 - def insertSpmUid(self, package_id, spm_package_uid):
2253 """ 2254 Reimplemented from EntropyRepositoryBase. 2255 """ 2256 branch = self._settings['repositories']['branch'] 2257 2258 self._cursor().execute(""" 2259 DELETE FROM counters WHERE counter = ? 2260 AND branch = ? 2261 """, (spm_package_uid, branch,)) 2262 # the "OR REPLACE" clause handles the UPDATE 2263 # of the counter value in case of clashing 2264 self._cursor().execute(""" 2265 %s INTO counters VALUES (?, ?, ?); 2266 """ % (self._INSERT_OR_REPLACE,), 2267 (spm_package_uid, package_id, branch,))
2268
2269 - def removeTrashedUids(self, spm_package_uids):
2270 """ 2271 Remove given Source Package Manager unique package identifiers from 2272 the "trashed" list. This is only used by Entropy Server. 2273 """ 2274 self._cursor().executemany(""" 2275 DELETE FROM trashedcounters WHERE counter = ? 2276 """, [(x,) for x in spm_package_uids])
2277
2278 - def setTrashedUid(self, spm_package_uid):
2279 """ 2280 Reimplemented from EntropyRepositoryBase. 2281 """ 2282 self._cursor().execute(""" 2283 %s INTO trashedcounters VALUES (?) 2284 """ % (self._INSERT_OR_REPLACE,), (spm_package_uid,))
2285
2286 - def setSpmUid(self, package_id, spm_package_uid, branch = None):
2287 """ 2288 Reimplemented from EntropyRepositoryBase. 2289 """ 2290 branchstring = '' 2291 insertdata = (spm_package_uid, package_id) 2292 if branch: 2293 branchstring = ', branch = (?)' 2294 insertdata += (branch,) 2295 2296 if self._UPDATE_OR_REPLACE is not None: 2297 self._cursor().execute(""" 2298 %s counters SET counter = (?) %s 2299 WHERE idpackage = (?)""" % ( 2300 self._UPDATE_OR_REPLACE, 2301 branchstring,), insertdata) 2302 else: 2303 try: 2304 cur = self._cursor().execute(""" 2305 UPDATE counters SET counter = ? %s 2306 WHERE idpackage = ?""" % (branchstring,), insertdata) 2307 except IntegrityError as err: 2308 # this was used by MySQL 2309 # errno = self.ModuleProxy.errno() 2310 # if err.args[0].errno != errno['ER_DUP_ENTRY']: 2311 # raise 2312 # fallback to replace 2313 cur = self._cursor().execute(""" 2314 %s INTO counters SET counter = ? %s 2315 WHERE idpackage = ?""" % ( 2316 self._INSERT_OR_REPLACE, 2317 branchstring,), insertdata)
2318
2319 - def setContentSafety(self, package_id, content_safety):
2320 """ 2321 Reimplemented from EntropyRepositoryBase. 2322 """ 2323 self._cursor().execute(""" 2324 DELETE FROM contentsafety where idpackage = ? 2325 """, (package_id,)) 2326 self._insertContentSafety(package_id, content_safety)
2327
2328 - def contentDiff(self, package_id, dbconn, dbconn_package_id, 2329 extended = False):
2330 """ 2331 Reimplemented from EntropyRepositoryBase. 2332 """ 2333 # setup random table name 2334 random_str = "%svs%s_%s" % (package_id, id(dbconn), 2335 dbconn_package_id) 2336 if const_is_python3(): 2337 random_str = const_convert_to_rawstring(random_str) 2338 randomtable = "cdiff%s" % (hashlib.md5(random_str).hexdigest(),) 2339 2340 # create random table 2341 self._cursor().executescript(""" 2342 DROP TABLE IF EXISTS `%s`; 2343 CREATE TEMPORARY TABLE `%s` ( 2344 file VARCHAR(75), ftype VARCHAR(3) ); 2345 """ % (randomtable, randomtable,) 2346 ) 2347 2348 try: 2349 2350 content_iter = dbconn.retrieveContentIter(dbconn_package_id) 2351 self._cursor().executemany(""" 2352 INSERT INTO `%s` VALUES (?, ?)""" % (randomtable,), 2353 content_iter) 2354 2355 # remove this when the one in retrieveContent will be removed 2356 self._connection().unicode() 2357 2358 # now compare 2359 ftype_str = "" 2360 if extended: 2361 ftype_str = ", type" 2362 cur = self._cursor().execute(""" 2363 SELECT file%s FROM content 2364 WHERE content.idpackage = ? AND 2365 content.file NOT IN (SELECT file from `%s`)""" % ( 2366 ftype_str, randomtable,), (package_id,)) 2367 2368 # suck back 2369 if extended: 2370 return tuple(cur) 2371 return self._cur2frozenset(cur) 2372 2373 finally: 2374 self._cursor().execute('DROP TABLE IF EXISTS `%s`' % ( 2375 randomtable,))
2376
2377 - def clean(self):
2378 """ 2379 Reimplemented from EntropyRepositoryBase. 2380 """ 2381 self._cleanupUseflags() 2382 self._cleanupSources() 2383 self._cleanupDependencies() 2384 self._cleanupChangelogs()
2385
2386 - def _cleanupChangelogs(self):
2387 """ 2388 Cleanup "changelog" metadata unused references to save space. 2389 """ 2390 concat = self._concatOperator(("category", "'/'", "name")) 2391 concat_sub = self._concatOperator( 2392 ("baseinfo.category", "'/'", "baseinfo.name")) 2393 self._cursor().execute(""" 2394 DELETE FROM packagechangelogs 2395 WHERE %s NOT IN 2396 ( SELECT %s FROM baseinfo) 2397 """ % (concat, concat_sub,))
2398
2399 - def _cleanupUseflags(self):
2400 """ 2401 Cleanup "USE flags" metadata unused references to save space. 2402 """ 2403 self._cursor().execute(""" 2404 DELETE FROM useflagsreference 2405 WHERE idflag NOT IN (SELECT idflag FROM useflags)""")
2406
2407 - def _cleanupSources(self):
2408 """ 2409 Cleanup "sources" metadata unused references to save space. 2410 """ 2411 self._cursor().execute(""" 2412 DELETE FROM sourcesreference 2413 WHERE idsource NOT IN (SELECT idsource FROM sources)""")
2414
2415 - def _cleanupDependencies(self):
2416 """ 2417 Cleanup "dependencies" metadata unused references to save space. 2418 """ 2419 self._cursor().execute(""" 2420 DELETE FROM dependenciesreference 2421 WHERE iddependency NOT IN (SELECT iddependency FROM dependencies) 2422 """)
2423
2424 - def getFakeSpmUid(self):
2425 """ 2426 Reimplemented from EntropyRepositoryBase. 2427 """ 2428 try: 2429 cur = self._cursor().execute(""" 2430 SELECT min(counter) FROM counters LIMIT 1 2431 """) 2432 dbcounter = cur.fetchone() 2433 except Error: 2434 # first available counter 2435 return -2 2436 2437 counter = 0 2438 if dbcounter: 2439 counter = dbcounter[0] 2440 2441 if (counter >= -1) or (counter is None): 2442 counter = -2 2443 else: 2444 counter -= 1 2445 2446 return counter
2447
2448 - def getApi(self):
2449 """ 2450 Reimplemented from EntropyRepositoryBase. 2451 """ 2452 cur = self._cursor().execute(""" 2453 SELECT max(etpapi) FROM baseinfo LIMIT 1 2454 """) 2455 api = cur.fetchone() 2456 if api: 2457 return api[0] 2458 return -1
2459
2460 - def getDependency(self, iddependency):
2461 """ 2462 Reimplemented from EntropyRepositoryBase. 2463 """ 2464 cur = self._cursor().execute(""" 2465 SELECT dependency FROM dependenciesreference 2466 WHERE iddependency = ? LIMIT 1 2467 """, (iddependency,)) 2468 dep = cur.fetchone() 2469 if dep: 2470 return dep[0]
2471
2472 - def getPackageIds(self, atom):
2473 """ 2474 Reimplemented from EntropyRepositoryBase. 2475 """ 2476 cur = self._cursor().execute(""" 2477 SELECT idpackage FROM baseinfo WHERE atom = ? 2478 """, (atom,)) 2479 return self._cur2frozenset(cur)
2480
2481 - def getPackageIdFromDownload(self, download_relative_path, 2482 endswith = False):
2483 """ 2484 Reimplemented from EntropyRepositoryBase. 2485 """ 2486 if endswith: 2487 cur = self._cursor().execute(""" 2488 SELECT baseinfo.idpackage FROM baseinfo,extrainfo 2489 WHERE extrainfo.download LIKE ? AND 2490 baseinfo.idpackage = extrainfo.idpackage 2491 LIMIT 1 2492 """, ("%"+download_relative_path,)) 2493 else: 2494 cur = self._cursor().execute(""" 2495 SELECT baseinfo.idpackage FROM baseinfo,extrainfo 2496 WHERE extrainfo.download = ? AND 2497 baseinfo.idpackage = extrainfo.idpackage 2498 LIMIT 1 2499 """, (download_relative_path,)) 2500 2501 package_id = cur.fetchone() 2502 if package_id: 2503 return package_id[0] 2504 return -1
2505
2506 - def getVersioningData(self, package_id):
2507 """ 2508 Reimplemented from EntropyRepositoryBase. 2509 """ 2510 cur = self._cursor().execute(""" 2511 SELECT version, versiontag, revision FROM baseinfo 2512 WHERE idpackage = ? LIMIT 1 2513 """, (package_id,)) 2514 return cur.fetchone()
2515
2516 - def getStrictData(self, package_id):
2517 """ 2518 Reimplemented from EntropyRepositoryBase. 2519 """ 2520 concat = self._concatOperator(("category", "'/'", "name")) 2521 cur = self._cursor().execute(""" 2522 SELECT %s, slot, version, versiontag, revision, atom 2523 FROM baseinfo 2524 WHERE idpackage = ? LIMIT 1 2525 """ % (concat,), (package_id,)) 2526 return cur.fetchone()
2527
2528 - def getStrictScopeData(self, package_id):
2529 """ 2530 Reimplemented from EntropyRepositoryBase. 2531 """ 2532 cur = self._cursor().execute(""" 2533 SELECT atom, slot, revision FROM baseinfo 2534 WHERE idpackage = ? LIMIT 1 2535 """, (package_id,)) 2536 return cur.fetchone()
2537
2538 - def getScopeData(self, package_id):
2539 """ 2540 Reimplemented from EntropyRepositoryBase. 2541 """ 2542 cur = self._cursor().execute(""" 2543 SELECT atom, category, name, version, slot, versiontag, 2544 revision, branch, etpapi FROM baseinfo 2545 WHERE baseinfo.idpackage = ? LIMIT 1 2546 """, (package_id,)) 2547 return cur.fetchone()
2548
2549 - def getBaseData(self, package_id):
2550 """ 2551 Reimplemented from EntropyRepositoryBase. 2552 """ 2553 sql = """ 2554 SELECT 2555 baseinfo.atom, 2556 baseinfo.name, 2557 baseinfo.version, 2558 baseinfo.versiontag, 2559 extrainfo.description, 2560 baseinfo.category, 2561 extrainfo.chost, 2562 extrainfo.cflags, 2563 extrainfo.cxxflags, 2564 extrainfo.homepage, 2565 baseinfo.license, 2566 baseinfo.branch, 2567 extrainfo.download, 2568 extrainfo.digest, 2569 baseinfo.slot, 2570 baseinfo.etpapi, 2571 extrainfo.datecreation, 2572 extrainfo.size, 2573 baseinfo.revision 2574 FROM 2575 baseinfo, 2576 extrainfo 2577 WHERE 2578 baseinfo.idpackage = ? 2579 AND baseinfo.idpackage = extrainfo.idpackage 2580 LIMIT 1 2581 """ 2582 cur = self._cursor().execute(sql, (package_id,)) 2583 return cur.fetchone()
2584
2585 - def retrieveRepositoryUpdatesDigest(self, repository):
2586 """ 2587 Reimplemented from EntropyRepositoryBase. 2588 """ 2589 cur = self._cursor().execute(""" 2590 SELECT digest FROM treeupdates WHERE repository = ? LIMIT 1 2591 """, (repository,)) 2592 2593 mydigest = cur.fetchone() 2594 if mydigest: 2595 return mydigest[0] 2596 return -1
2597
2598 - def listAllTreeUpdatesActions(self, no_ids_repos = False):
2599 """ 2600 Reimplemented from EntropyRepositoryBase. 2601 """ 2602 if no_ids_repos: 2603 cur = self._cursor().execute(""" 2604 SELECT command, branch, date FROM treeupdatesactions 2605 ORDER BY CAST(date AS FLOAT) 2606 """) 2607 else: 2608 cur = self._cursor().execute(""" 2609 SELECT idupdate, repository, command, branch, date 2610 FROM treeupdatesactions ORDER BY CAST(date AS FLOAT) 2611 """) 2612 return tuple(cur)
2613
2614 - def retrieveTreeUpdatesActions(self, repository):
2615 """ 2616 Reimplemented from EntropyRepositoryBase. 2617 """ 2618 params = (repository,) 2619 2620 cur = self._cursor().execute(""" 2621 SELECT command FROM treeupdatesactions WHERE 2622 repository = ? ORDER BY CAST(date AS FLOAT)""", params) 2623 return self._cur2tuple(cur)
2624
2625 - def bumpTreeUpdatesActions(self, updates):
2626 """ 2627 Reimplemented from EntropyRepositoryBase. 2628 """ 2629 self._cursor().execute('DELETE FROM treeupdatesactions') 2630 self._cursor().executemany(""" 2631 INSERT INTO treeupdatesactions VALUES (?, ?, ?, ?, ?) 2632 """, updates)
2633
2634 - def removeTreeUpdatesActions(self, repository):
2635 """ 2636 Reimplemented from EntropyRepositoryBase. 2637 """ 2638 self._cursor().execute(""" 2639 DELETE FROM treeupdatesactions WHERE repository = ? 2640 """, (repository,))
2641
2642 - def insertTreeUpdatesActions(self, updates, repository):
2643 """ 2644 Reimplemented from EntropyRepositoryBase. 2645 """ 2646 myupdates = [[repository]+list(x) for x in updates] 2647 self._cursor().executemany(""" 2648 INSERT INTO treeupdatesactions VALUES (NULL, ?, ?, ?, ?) 2649 """, myupdates)
2650
2651 - def setRepositoryUpdatesDigest(self, repository, digest):
2652 """ 2653 Reimplemented from EntropyRepositoryBase. 2654 """ 2655 self._cursor().execute(""" 2656 DELETE FROM treeupdates where repository = ? 2657 """, (repository,)) 2658 self._cursor().execute(""" 2659 INSERT INTO treeupdates VALUES (?, ?) 2660 """, (repository, digest,))
2661
2662 - def addRepositoryUpdatesActions(self, repository, actions, branch):
2663 """ 2664 Reimplemented from EntropyRepositoryBase. 2665 """ 2666 mytime = str(time.time()) 2667 myupdates = [ 2668 (repository, x, branch, mytime,) for x in actions \ 2669 if not self._doesTreeupdatesActionExist(repository, x, branch) 2670 ] 2671 self._cursor().executemany(""" 2672 INSERT INTO treeupdatesactions VALUES (NULL, ?, ?, ?, ?) 2673 """, myupdates)
2674
2675 - def _doesTreeupdatesActionExist(self, repository, command, branch):
2676 """ 2677 This method should be considered internal and not suited for general 2678 audience. 2679 Return whether provided "treeupdates" action in repository with 2680 provided branch exists. 2681 2682 @param repository: repository identifier 2683 @type repository: string 2684 @param command: treeupdates command 2685 @type command: string 2686 @param branch: branch metadata bound to command argument value given 2687 @type branch: string 2688 @return: if True, provided treeupdates action already exists 2689 @rtype: bool 2690 """ 2691 cur = self._cursor().execute(""" 2692 SELECT idupdate FROM treeupdatesactions 2693 WHERE repository = ? and command = ? 2694 and branch = ? LIMIT 1 2695 """, (repository, command, branch,)) 2696 2697 result = cur.fetchone() 2698 if result: 2699 return True 2700 return False
2701
2702 - def clearPackageSets(self):
2703 """ 2704 Reimplemented from EntropyRepositoryBase. 2705 """ 2706 self._cursor().execute('DELETE FROM packagesets')
2707
2708 - def insertPackageSets(self, sets_data):
2709 """ 2710 Reimplemented from EntropyRepositoryBase. 2711 """ 2712 mysets = [] 2713 for setname in sorted(sets_data): 2714 for dependency in sorted(sets_data[setname]): 2715 try: 2716 mysets.append((const_convert_to_unicode(setname), 2717 const_convert_to_unicode(dependency),)) 2718 except (UnicodeDecodeError, UnicodeEncodeError,): 2719 continue 2720 2721 self._cursor().executemany(""" 2722 INSERT INTO packagesets VALUES (?, ?) 2723 """, mysets)
2724
2725 - def retrievePackageSets(self):
2726 """ 2727 Reimplemented from EntropyRepositoryBase. 2728 """ 2729 cur = self._cursor().execute(""" 2730 SELECT setname, dependency FROM packagesets 2731 """) 2732 sets = {} 2733 for setname, dependency in cur: 2734 obj = sets.setdefault(setname, set()) 2735 obj.add(dependency) 2736 return sets
2737
2738 - def retrievePackageSet(self, setname):
2739 """ 2740 Reimplemented from EntropyRepositoryBase. 2741 """ 2742 cur = self._cursor().execute(""" 2743 SELECT dependency FROM packagesets WHERE setname = ?""", 2744 (setname,)) 2745 return self._cur2frozenset(cur)
2746
2747 - def retrieveAtom(self, package_id):
2748 """ 2749 Reimplemented from EntropyRepositoryBase. 2750 """ 2751 cur = self._cursor().execute(""" 2752 SELECT atom FROM baseinfo WHERE idpackage = ? LIMIT 1 2753 """, (package_id,)) 2754 atom = cur.fetchone() 2755 if atom: 2756 return atom[0]
2757
2758 - def retrieveBranch(self, package_id):
2759 """ 2760 Reimplemented from EntropyRepositoryBase. 2761 """ 2762 cur = self._cursor().execute(""" 2763 SELECT branch FROM baseinfo WHERE idpackage = ? LIMIT 1 2764 """, (package_id,)) 2765 branch = cur.fetchone() 2766 if branch: 2767 return branch[0]
2768
2769 - def retrieveTrigger(self, package_id):
2770 """ 2771 Reimplemented from EntropyRepositoryBase. 2772 """ 2773 cur = self._cursor().execute(""" 2774 SELECT data FROM triggers WHERE idpackage = ? LIMIT 1 2775 """, (package_id,)) 2776 trigger = cur.fetchone() 2777 if not trigger: 2778 # backward compatibility with <=0.52.x 2779 return const_convert_to_rawstring('') 2780 return const_convert_to_rawstring(trigger[0])
2781
2782 - def retrieveDownloadURL(self, package_id):
2783 """ 2784 Reimplemented from EntropyRepositoryBase. 2785 """ 2786 cur = self._cursor().execute(""" 2787 SELECT download FROM extrainfo WHERE idpackage = ? LIMIT 1 2788 """, (package_id,)) 2789 download = cur.fetchone() 2790 if download: 2791 return download[0]
2792
2793 - def retrieveDescription(self, package_id):
2794 """ 2795 Reimplemented from EntropyRepositoryBase. 2796 """ 2797 cur = self._cursor().execute(""" 2798 SELECT description FROM extrainfo WHERE idpackage = ? LIMIT 1 2799 """, (package_id,)) 2800 description = cur.fetchone() 2801 if description: 2802 return description[0]
2803
2804 - def retrieveHomepage(self, package_id):
2805 """ 2806 Reimplemented from EntropyRepositoryBase. 2807 """ 2808 cur = self._cursor().execute(""" 2809 SELECT homepage FROM extrainfo WHERE idpackage = ? LIMIT 1 2810 """, (package_id,)) 2811 home = cur.fetchone() 2812 if home: 2813 return home[0]
2814
2815 - def retrieveSpmUid(self, package_id):
2816 """ 2817 Reimplemented from EntropyRepositoryBase. 2818 """ 2819 cur = self._cursor().execute(""" 2820 SELECT counters.counter FROM counters,baseinfo 2821 WHERE counters.idpackage = ? AND 2822 baseinfo.idpackage = counters.idpackage AND 2823 baseinfo.branch = counters.branch LIMIT 1 2824 """, (package_id,)) 2825 mycounter = cur.fetchone() 2826 if mycounter: 2827 return mycounter[0] 2828 return -1
2829
2830 - def retrieveSize(self, package_id):
2831 """ 2832 Reimplemented from EntropyRepositoryBase. 2833 """ 2834 cur = self._cursor().execute(""" 2835 SELECT size FROM extrainfo WHERE idpackage = ? LIMIT 1 2836 """, (package_id,)) 2837 size = cur.fetchone() 2838 if size: 2839 try: 2840 return int(size[0]) 2841 except ValueError: # wtf? 2842 return 0
2843
2844 - def retrieveOnDiskSize(self, package_id):
2845 """ 2846 Reimplemented from EntropyRepositoryBase. 2847 """ 2848 cur = self._cursor().execute(""" 2849 SELECT size FROM sizes WHERE idpackage = ? LIMIT 1 2850 """, (package_id,)) 2851 size = cur.fetchone() 2852 if size: 2853 return size[0] 2854 return 0
2855
2856 - def retrieveDigest(self, package_id):
2857 """ 2858 Reimplemented from EntropyRepositoryBase. 2859 """ 2860 cur = self._cursor().execute(""" 2861 SELECT digest FROM extrainfo WHERE idpackage = ? LIMIT 1 2862 """, (package_id,)) 2863 digest = cur.fetchone() 2864 if digest: 2865 return digest[0] 2866 return None
2867
2868 - def retrieveSignatures(self, package_id):
2869 """ 2870 Reimplemented from EntropyRepositoryBase. 2871 """ 2872 cur = self._cursor().execute(""" 2873 SELECT sha1, sha256, sha512, gpg FROM packagesignatures 2874 WHERE idpackage = ? LIMIT 1 2875 """, (package_id,)) 2876 data = cur.fetchone() 2877 2878 if data: 2879 return data 2880 return None, None, None, None
2881
2882 - def retrieveExtraDownload(self, package_id, down_type = None):
2883 """ 2884 Reimplemented from EntropyRepositoryBase. 2885 """ 2886 down_type_str = "" 2887 params = [package_id] 2888 if down_type is not None: 2889 down_type_str = " AND down_type = ?" 2890 params.append(down_type) 2891 2892 cur = self._cursor().execute(""" 2893 SELECT download, type, size, disksize, md5, sha1, 2894 sha256, sha512, gpg 2895 FROM packagedownloads WHERE idpackage = ? 2896 """ + down_type_str, params) 2897 2898 result = [] 2899 for download, d_type, size, d_size, md5, sha1, sha256, sha512, gpg in \ 2900 cur: 2901 result.append({ 2902 "download": download, 2903 "type": d_type, 2904 "size": size, 2905 "disksize": d_size, 2906 "md5": md5, 2907 "sha1": sha1, 2908 "sha256": sha256, 2909 "sha512": sha512, 2910 "gpg": gpg, 2911 }) 2912 return tuple(result)
2913
2914 - def retrieveName(self, package_id):
2915 """ 2916 Reimplemented from EntropyRepositoryBase. 2917 """ 2918 cur = self._cursor().execute(""" 2919 SELECT name FROM baseinfo WHERE idpackage = ? LIMIT 1 2920 """, (package_id,)) 2921 name = cur.fetchone() 2922 if name: 2923 return name[0]
2924
2925 - def retrieveKeySplit(self, package_id):
2926 """ 2927 Reimplemented from EntropyRepositoryBase. 2928 """ 2929 cur = self._cursor().execute(""" 2930 SELECT category, name FROM baseinfo 2931 WHERE idpackage = ? LIMIT 1 2932 """, (package_id,)) 2933 return cur.fetchone()
2934
2935 - def retrieveKeySlot(self, package_id):
2936 """ 2937 Reimplemented from EntropyRepositoryBase. 2938 """ 2939 concat = self._concatOperator(("category", "'/'", "name")) 2940 cur = self._cursor().execute(""" 2941 SELECT %s, slot FROM baseinfo 2942 WHERE idpackage = ? LIMIT 1 2943 """ % (concat,), (package_id,)) 2944 return cur.fetchone()
2945
2946 - def retrieveKeySlotAggregated(self, package_id):
2947 """ 2948 Reimplemented from EntropyRepositoryBase. 2949 """ 2950 concat = self._concatOperator( 2951 ("category", 2952 "'/'", 2953 "name", 2954 "'%s'" % (etpConst['entropyslotprefix'],), 2955 "slot")) 2956 cur = self._cursor().execute(""" 2957 SELECT %s FROM baseinfo 2958 WHERE idpackage = ? LIMIT 1 2959 """ % (concat,), (package_id,)) 2960 keyslot = cur.fetchone() 2961 if keyslot: 2962 return keyslot[0] 2963 return None
2964
2965 - def retrieveKeySlotTag(self, package_id):
2966 """ 2967 Reimplemented from EntropyRepositoryBase. 2968 """ 2969 concat = self._concatOperator(("category", "'/'", "name")) 2970 cur = self._cursor().execute(""" 2971 SELECT %s, slot, versiontag 2972 FROM baseinfo WHERE 2973 idpackage = ? LIMIT 1 2974 """ % (concat,), (package_id,)) 2975 return cur.fetchone()
2976
2977 - def retrieveVersion(self, package_id):
2978 """ 2979 Reimplemented from EntropyRepositoryBase. 2980 """ 2981 cur = self._cursor().execute(""" 2982 SELECT version FROM baseinfo 2983 WHERE idpackage = ? LIMIT 1 2984 """, (package_id,)) 2985 version = cur.fetchone() 2986 if version: 2987 return version[0] 2988 return None
2989
2990 - def retrieveRevision(self, package_id):
2991 """ 2992 Reimplemented from EntropyRepositoryBase. 2993 """ 2994 cur = self._cursor().execute(""" 2995 SELECT revision FROM baseinfo 2996 WHERE idpackage = ? LIMIT 1 2997 """, (package_id,)) 2998 rev = cur.fetchone() 2999 if rev: 3000 return rev[0] 3001 return None
3002
3003 - def retrieveCreationDate(self, package_id):
3004 """ 3005 Reimplemented from EntropyRepositoryBase. 3006 """ 3007 cur = self._cursor().execute(""" 3008 SELECT datecreation FROM extrainfo WHERE idpackage = ? LIMIT 1 3009 """, (package_id,)) 3010 date = cur.fetchone() 3011 if date: 3012 return date[0]
3013
3014 - def retrieveApi(self, package_id):
3015 """ 3016 Reimplemented from EntropyRepositoryBase. 3017 """ 3018 cur = self._cursor().execute(""" 3019 SELECT etpapi FROM baseinfo WHERE idpackage = ? LIMIT 1 3020 """, (package_id,)) 3021 api = cur.fetchone() 3022 if api: 3023 return api[0]
3024
3025 - def retrieveUseflags(self, package_id):
3026 """ 3027 Reimplemented from EntropyRepositoryBase. 3028 """ 3029 cur = self._cursor().execute(""" 3030 SELECT useflagsreference.flagname 3031 FROM useflags, useflagsreference 3032 WHERE useflags.idpackage = ? 3033 AND useflags.idflag = useflagsreference.idflag 3034 """, (package_id,)) 3035 return self._cur2frozenset(cur)
3036
3037 - def retrieveSpmPhases(self, package_id):
3038 """ 3039 Reimplemented from EntropyRepositoryBase. 3040 """ 3041 cur = self._cursor().execute(""" 3042 SELECT phases FROM packagespmphases WHERE idpackage = ? LIMIT 1 3043 """, (package_id,)) 3044 spm_phases = cur.fetchone() 3045 3046 if spm_phases: 3047 return spm_phases[0]
3048
3049 - def retrieveSpmRepository(self, package_id):
3050 """ 3051 Reimplemented from EntropyRepositoryBase. 3052 """ 3053 cur = self._cursor().execute(""" 3054 SELECT repository FROM packagespmrepository 3055 WHERE idpackage = ? LIMIT 1 3056 """, (package_id,)) 3057 spm_repo = cur.fetchone() 3058 3059 if spm_repo: 3060 return spm_repo[0]
3061
3062 - def retrieveDesktopMime(self, package_id):
3063 """ 3064 Reimplemented from EntropyRepositoryBase. 3065 """ 3066 cur = self._cursor().execute(""" 3067 SELECT name, mimetype, executable, icon FROM packagedesktopmime 3068 WHERE idpackage = ?""", (package_id,)) 3069 data = [] 3070 for row in cur: 3071 item = {} 3072 item['name'], item['mimetype'], item['executable'], \ 3073 item['icon'] = row 3074 data.append(item) 3075 return data
3076
3077 - def retrieveProvidedMime(self, package_id):
3078 """ 3079 Reimplemented from EntropyRepositoryBase. 3080 """ 3081 cur = self._cursor().execute(""" 3082 SELECT mimetype FROM provided_mime WHERE idpackage = ? 3083 """, (package_id,)) 3084 return self._cur2frozenset(cur)
3085
3086 - def retrieveNeeded(self, package_id, extended = False, formatted = False):
3087 """ 3088 Reimplemented from EntropyRepositoryBase. 3089 """ 3090 if not self._doesTableExist("needed_libs"): 3091 # TODO: remove in 2016. 3092 return self._compatRetrieveNeeded( 3093 package_id, extended=extended, formatted=formatted) 3094 3095 if extended: 3096 cur = self._cursor().execute(""" 3097 SELECT soname, elfclass FROM needed_libs 3098 WHERE idpackage = ? ORDER BY soname 3099 """, (package_id,)) 3100 needed = tuple(cur) 3101 3102 else: 3103 cur = self._cursor().execute(""" 3104 SELECT soname FROM needed_libs 3105 WHERE idpackage = ? ORDER BY soname 3106 """, (package_id,)) 3107 needed = self._cur2tuple(cur) 3108 3109 if extended and formatted: 3110 return dict((lib, elfclass,) for lib, elfclass in needed) 3111 return needed
3112
3113 - def _compatRetrieveNeeded(self, package_id, extended = False, 3114 formatted = False):
3115 """ 3116 Backward compatibility schema support for retrieveNeeded(). 3117 """ 3118 if extended: 3119 cur = self._cursor().execute(""" 3120 SELECT library,elfclass FROM needed,neededreference 3121 WHERE needed.idpackage = ? AND 3122 needed.idneeded = neededreference.idneeded ORDER BY library 3123 """, (package_id,)) 3124 needed = tuple(cur) 3125 3126 else: 3127 cur = self._cursor().execute(""" 3128 SELECT library FROM needed,neededreference 3129 WHERE needed.idpackage = ? AND 3130 needed.idneeded = neededreference.idneeded ORDER BY library 3131 """, (package_id,)) 3132 needed = self._cur2tuple(cur) 3133 3134 if extended and formatted: 3135 return dict((lib, elfclass,) for lib, elfclass in needed) 3136 return needed
3137
3138 - def retrieveNeededLibraries(self, package_id):
3139 """ 3140 Reimplemented from EntropyRepositoryBase. 3141 """ 3142 cur = self._cursor().execute(""" 3143 SELECT lib_user_path, lib_user_soname, soname, elfclass, rpath 3144 FROM needed_libs WHERE idpackage = ? 3145 """, (package_id,)) 3146 return frozenset(cur)
3147
3148 - def retrieveProvidedLibraries(self, package_id):
3149 """ 3150 Reimplemented from EntropyRepositoryBase. 3151 """ 3152 cur = self._cursor().execute(""" 3153 SELECT library, path, elfclass FROM provided_libs 3154 WHERE idpackage = ? 3155 """, (package_id,)) 3156 return frozenset(cur)
3157
3158 - def retrieveConflicts(self, package_id):
3159 """ 3160 Reimplemented from EntropyRepositoryBase. 3161 """ 3162 cur = self._cursor().execute(""" 3163 SELECT conflict FROM conflicts WHERE idpackage = ? 3164 """, (package_id,)) 3165 return self._cur2frozenset(cur)
3166
3167 - def retrieveProvide(self, package_id):
3168 """ 3169 Reimplemented from EntropyRepositoryBase. 3170 """ 3171 cur = self._cursor().execute(""" 3172 SELECT atom, is_default FROM provide WHERE idpackage = ? 3173 """, (package_id,)) 3174 return frozenset(cur)
3175
3176 - def retrieveDependenciesList(self, package_id, exclude_deptypes = None, 3177 resolve_conditional_deps = True):
3178 """ 3179 Reimplemented from EntropyRepositoryBase. 3180 """ 3181 excluded_deptypes_query = "" 3182 if exclude_deptypes is not None: 3183 for dep_type in exclude_deptypes: 3184 excluded_deptypes_query += \ 3185 " AND dependencies.type != %d" % (dep_type,) 3186 3187 concat = self._concatOperator( 3188 ("'!'", "conflict")) 3189 cur = self._cursor().execute(""" 3190 SELECT dependenciesreference.dependency 3191 FROM dependencies, dependenciesreference 3192 WHERE dependencies.idpackage = (?) AND 3193 dependencies.iddependency = dependenciesreference.iddependency %s 3194 UNION SELECT %s FROM conflicts 3195 WHERE idpackage = (?)""" % (excluded_deptypes_query, concat,), 3196 (package_id, package_id,)) 3197 if resolve_conditional_deps: 3198 return frozenset(entropy.dep.expand_dependencies(cur, [self])) 3199 else: 3200 return self._cur2frozenset(cur)
3201
3202 - def retrieveBuildDependencies(self, package_id, extended = False, 3203 resolve_conditional_deps = True):
3204 """ 3205 Reimplemented from EntropyRepositoryBase. 3206 """ 3207 return self.retrieveDependencies(package_id, extended = extended, 3208 deptype = etpConst['dependency_type_ids']['bdepend_id'], 3209 resolve_conditional_deps = resolve_conditional_deps)
3210
3211 - def retrieveRuntimeDependencies(self, package_id, extended = False, 3212 resolve_conditional_deps = True):
3213 """ 3214 Reimplemented from EntropyRepositoryBase. 3215 """ 3216 return self.retrieveDependencies(package_id, extended = extended, 3217 deptype = etpConst['dependency_type_ids']['rdepend_id'], 3218 resolve_conditional_deps = resolve_conditional_deps)
3219
3220 - def retrievePostDependencies(self, package_id, extended = False, 3221 resolve_conditional_deps = True):
3222 """ 3223 Reimplemented from EntropyRepositoryBase. 3224 """ 3225 return self.retrieveDependencies(package_id, extended = extended, 3226 deptype = etpConst['dependency_type_ids']['pdepend_id'], 3227 resolve_conditional_deps = resolve_conditional_deps)
3228
3229 - def retrieveManualDependencies(self, package_id, extended = False, 3230 resolve_conditional_deps = True):
3231 """ 3232 Reimplemented from EntropyRepositoryBase. 3233 """ 3234 return self.retrieveDependencies(package_id, extended = extended, 3235 deptype = etpConst['dependency_type_ids']['mdepend_id'], 3236 resolve_conditional_deps = resolve_conditional_deps)
3237
3238 - def retrieveDependencies(self, package_id, extended = False, 3239 deptype = None, exclude_deptypes = None, 3240 resolve_conditional_deps = True):
3241 """ 3242 Reimplemented from EntropyRepositoryBase. 3243 """ 3244 searchdata = (package_id,) 3245 3246 depstring = '' 3247 if deptype is not None: 3248 depstring = 'and dependencies.type = ?' 3249 searchdata += (deptype,) 3250 3251 excluded_deptypes_query = "" 3252 if exclude_deptypes is not None: 3253 for dep_type in exclude_deptypes: 3254 excluded_deptypes_query += " AND dependencies.type != %d" % ( 3255 dep_type,) 3256 3257 cur = None 3258 iter_obj = None 3259 if extended: 3260 cur = self._cursor().execute(""" 3261 SELECT dependenciesreference.dependency,dependencies.type 3262 FROM dependencies,dependenciesreference 3263 WHERE dependencies.idpackage = ? AND 3264 dependencies.iddependency = 3265 dependenciesreference.iddependency %s %s""" % ( 3266 depstring, excluded_deptypes_query,), searchdata) 3267 iter_obj = tuple 3268 else: 3269 cur = self._cursor().execute(""" 3270 SELECT dependenciesreference.dependency 3271 FROM dependencies,dependenciesreference 3272 WHERE dependencies.idpackage = ? AND 3273 dependencies.iddependency = 3274 dependenciesreference.iddependency %s %s""" % ( 3275 depstring, excluded_deptypes_query,), searchdata) 3276 iter_obj = frozenset 3277 3278 if resolve_conditional_deps: 3279 return iter_obj(entropy.dep.expand_dependencies( 3280 cur, [self])) 3281 return iter_obj(cur)
3282
3283 - def retrieveKeywords(self, package_id):
3284 """ 3285 Reimplemented from EntropyRepositoryBase. 3286 """ 3287 cur = self._cursor().execute(""" 3288 SELECT keywordname FROM keywords,keywordsreference 3289 WHERE keywords.idpackage = ? AND 3290 keywords.idkeyword = keywordsreference.idkeyword""", (package_id,)) 3291 return self._cur2frozenset(cur)
3292
3293 - def retrieveProtect(self, package_id):
3294 """ 3295 Reimplemented from EntropyRepositoryBase. 3296 """ 3297 cur = self._cursor().execute(""" 3298 SELECT protect FROM configprotect,configprotectreference 3299 WHERE configprotect.idpackage = ? AND 3300 configprotect.idprotect = configprotectreference.idprotect 3301 LIMIT 1 3302 """, (package_id,)) 3303 3304 protect = cur.fetchone() 3305 if protect: 3306 return protect[0] 3307 return ''
3308
3309 - def retrieveProtectMask(self, package_id):
3310 """ 3311 Reimplemented from EntropyRepositoryBase. 3312 """ 3313 cur = self._cursor().execute(""" 3314 SELECT protect FROM configprotectmask,configprotectreference 3315 WHERE idpackage = ? AND 3316 configprotectmask.idprotect = configprotectreference.idprotect 3317 LIMIT 1 3318 """, (package_id,)) 3319 3320 protect = cur.fetchone() 3321 if protect: 3322 return protect[0] 3323 return ''
3324
3325 - def retrieveSources(self, package_id, extended = False):
3326 """ 3327 Reimplemented from EntropyRepositoryBase. 3328 """ 3329 cur = self._cursor().execute(""" 3330 SELECT sourcesreference.source FROM sources, sourcesreference 3331 WHERE idpackage = ? AND 3332 sources.idsource = sourcesreference.idsource 3333 """, (package_id,)) 3334 sources = self._cur2frozenset(cur) 3335 if not extended: 3336 return sources 3337 3338 source_data = {} 3339 mirror_str = "mirror://" 3340 for source in sources: 3341 3342 source_data[source] = set() 3343 if source.startswith(mirror_str): 3344 3345 mirrorname = source.split("/")[2] 3346 # avoid leading "/" 3347 mirror_url = source.split("/", 3)[3:][0].lstrip("/") 3348 source_data[source] |= set( 3349 [url.rstrip("/") + "/" + mirror_url for url in \ 3350 self.retrieveMirrorData(mirrorname)]) 3351 3352 else: 3353 source_data[source].add(source) 3354 3355 return source_data
3356
3357 - def retrieveAutomergefiles(self, package_id, get_dict = False):
3358 """ 3359 Reimplemented from EntropyRepositoryBase. 3360 """ 3361 # like portage does 3362 self._connection().unicode() 3363 3364 cur = self._cursor().execute(""" 3365 SELECT configfile, md5 FROM automergefiles WHERE idpackage = ? 3366 """, (package_id,)) 3367 data = frozenset(cur) 3368 3369 if get_dict: 3370 data = dict(((x, y,) for x, y in data)) 3371 return data
3372
3373 - def retrieveContent(self, package_id, extended = False, 3374 formatted = False, insert_formatted = False, order_by = None):
3375 """ 3376 Reimplemented from EntropyRepositoryBase. 3377 """ 3378 extstring = '' 3379 if extended: 3380 extstring = ",type" 3381 extstring_package_id = '' 3382 if insert_formatted: 3383 extstring_package_id = 'idpackage,' 3384 3385 searchkeywords = (package_id,) 3386 order_by_string = '' 3387 if order_by is not None: 3388 if order_by not in ("package_id", "idpackage", "file", "type",): 3389 raise AttributeError("invalid order_by argument") 3390 if order_by == "package_id": 3391 order_by = "idpackage" 3392 order_by_string = ' order by %s' % (order_by,) 3393 3394 cur = self._cursor().execute(""" 3395 SELECT %s file%s FROM content WHERE idpackage = ? %s""" % ( 3396 extstring_package_id, extstring, order_by_string,), 3397 searchkeywords) 3398 3399 if extended and insert_formatted: 3400 fl = tuple(cur) 3401 3402 elif extended and formatted: 3403 fl = {} 3404 items = cur.fetchone() 3405 while items: 3406 fl[items[0]] = items[1] 3407 items = cur.fetchone() 3408 3409 elif extended: 3410 fl = tuple(cur) 3411 3412 else: 3413 if order_by: 3414 fl = self._cur2tuple(cur) 3415 else: 3416 fl = self._cur2frozenset(cur) 3417 3418 return fl
3419
3420 - def retrieveContentIter(self, package_id, order_by = None, 3421 reverse = False):
3422 """ 3423 Reimplemented from EntropyRepositoryBase. 3424 """ 3425 class MyIter: 3426 3427 def __init__(self, db, query, keywords): 3428 self._cur = None 3429 self._db = db 3430 self._query = query 3431 self._keywords = keywords 3432 self._init_cur()
3433 3434 def _init_cur(self): 3435 self._cur = self._db._cursor().execute( 3436 self._query, self._keywords) 3437 3438 def __iter__(self): 3439 self._init_cur() 3440 return self 3441 3442 def __next__(self): 3443 return next(self._cur) 3444 3445 def next(self): 3446 return self._cur.