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(etpConst['conf_raw_encoding']) 1866 except (UnicodeDecodeError,): 1867 lic_data = lic_data.encode(etpConst['conf_encoding']) 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 is None: 2442 counter = -2 2443 elif counter >= -1: 2444 counter = -2 2445 else: 2446 counter -= 1 2447 2448 return counter
2449
2450 - def getApi(self):
2451 """ 2452 Reimplemented from EntropyRepositoryBase. 2453 """ 2454 cur = self._cursor().execute(""" 2455 SELECT max(etpapi) FROM baseinfo LIMIT 1 2456 """) 2457 api = cur.fetchone() 2458 if api: 2459 return api[0] 2460 return -1
2461
2462 - def getDependency(self, iddependency):
2463 """ 2464 Reimplemented from EntropyRepositoryBase. 2465 """ 2466 cur = self._cursor().execute(""" 2467 SELECT dependency FROM dependenciesreference 2468 WHERE iddependency = ? LIMIT 1 2469 """, (iddependency,)) 2470 dep = cur.fetchone() 2471 if dep: 2472 return dep[0]
2473
2474 - def getPackageIds(self, atom):
2475 """ 2476 Reimplemented from EntropyRepositoryBase. 2477 """ 2478 cur = self._cursor().execute(""" 2479 SELECT idpackage FROM baseinfo WHERE atom = ? 2480 """, (atom,)) 2481 return self._cur2frozenset(cur)
2482
2483 - def getPackageIdFromDownload(self, download_relative_path, 2484 endswith = False):
2485 """ 2486 Reimplemented from EntropyRepositoryBase. 2487 """ 2488 if endswith: 2489 cur = self._cursor().execute(""" 2490 SELECT baseinfo.idpackage FROM baseinfo,extrainfo 2491 WHERE extrainfo.download LIKE ? AND 2492 baseinfo.idpackage = extrainfo.idpackage 2493 LIMIT 1 2494 """, ("%"+download_relative_path,)) 2495 else: 2496 cur = self._cursor().execute(""" 2497 SELECT baseinfo.idpackage FROM baseinfo,extrainfo 2498 WHERE extrainfo.download = ? AND 2499 baseinfo.idpackage = extrainfo.idpackage 2500 LIMIT 1 2501 """, (download_relative_path,)) 2502 2503 package_id = cur.fetchone() 2504 if package_id: 2505 return package_id[0] 2506 return -1
2507
2508 - def getVersioningData(self, package_id):
2509 """ 2510 Reimplemented from EntropyRepositoryBase. 2511 """ 2512 cur = self._cursor().execute(""" 2513 SELECT version, versiontag, revision FROM baseinfo 2514 WHERE idpackage = ? LIMIT 1 2515 """, (package_id,)) 2516 return cur.fetchone()
2517
2518 - def getStrictData(self, package_id):
2519 """ 2520 Reimplemented from EntropyRepositoryBase. 2521 """ 2522 concat = self._concatOperator(("category", "'/'", "name")) 2523 cur = self._cursor().execute(""" 2524 SELECT %s, slot, version, versiontag, revision, atom 2525 FROM baseinfo 2526 WHERE idpackage = ? LIMIT 1 2527 """ % (concat,), (package_id,)) 2528 return cur.fetchone()
2529
2530 - def getStrictScopeData(self, package_id):
2531 """ 2532 Reimplemented from EntropyRepositoryBase. 2533 """ 2534 cur = self._cursor().execute(""" 2535 SELECT atom, slot, revision FROM baseinfo 2536 WHERE idpackage = ? LIMIT 1 2537 """, (package_id,)) 2538 return cur.fetchone()
2539
2540 - def getScopeData(self, package_id):
2541 """ 2542 Reimplemented from EntropyRepositoryBase. 2543 """ 2544 cur = self._cursor().execute(""" 2545 SELECT atom, category, name, version, slot, versiontag, 2546 revision, branch, etpapi FROM baseinfo 2547 WHERE baseinfo.idpackage = ? LIMIT 1 2548 """, (package_id,)) 2549 return cur.fetchone()
2550
2551 - def getBaseData(self, package_id):
2552 """ 2553 Reimplemented from EntropyRepositoryBase. 2554 """ 2555 sql = """ 2556 SELECT 2557 baseinfo.atom, 2558 baseinfo.name, 2559 baseinfo.version, 2560 baseinfo.versiontag, 2561 extrainfo.description, 2562 baseinfo.category, 2563 extrainfo.chost, 2564 extrainfo.cflags, 2565 extrainfo.cxxflags, 2566 extrainfo.homepage, 2567 baseinfo.license, 2568 baseinfo.branch, 2569 extrainfo.download, 2570 extrainfo.digest, 2571 baseinfo.slot, 2572 baseinfo.etpapi, 2573 extrainfo.datecreation, 2574 extrainfo.size, 2575 baseinfo.revision 2576 FROM 2577 baseinfo, 2578 extrainfo 2579 WHERE 2580 baseinfo.idpackage = ? 2581 AND baseinfo.idpackage = extrainfo.idpackage 2582 LIMIT 1 2583 """ 2584 cur = self._cursor().execute(sql, (package_id,)) 2585 return cur.fetchone()
2586
2587 - def retrieveRepositoryUpdatesDigest(self, repository):
2588 """ 2589 Reimplemented from EntropyRepositoryBase. 2590 """ 2591 cur = self._cursor().execute(""" 2592 SELECT digest FROM treeupdates WHERE repository = ? LIMIT 1 2593 """, (repository,)) 2594 2595 mydigest = cur.fetchone() 2596 if mydigest: 2597 return mydigest[0] 2598 return -1
2599
2600 - def listAllTreeUpdatesActions(self, no_ids_repos = False):
2601 """ 2602 Reimplemented from EntropyRepositoryBase. 2603 """ 2604 if no_ids_repos: 2605 cur = self._cursor().execute(""" 2606 SELECT command, branch, date FROM treeupdatesactions 2607 ORDER BY CAST(date AS FLOAT) 2608 """) 2609 else: 2610 cur = self._cursor().execute(""" 2611 SELECT idupdate, repository, command, branch, date 2612 FROM treeupdatesactions ORDER BY CAST(date AS FLOAT) 2613 """) 2614 return tuple(cur)
2615
2616 - def retrieveTreeUpdatesActions(self, repository):
2617 """ 2618 Reimplemented from EntropyRepositoryBase. 2619 """ 2620 params = (repository,) 2621 2622 cur = self._cursor().execute(""" 2623 SELECT command FROM treeupdatesactions WHERE 2624 repository = ? ORDER BY CAST(date AS FLOAT)""", params) 2625 return self._cur2tuple(cur)
2626
2627 - def bumpTreeUpdatesActions(self, updates):
2628 """ 2629 Reimplemented from EntropyRepositoryBase. 2630 """ 2631 self._cursor().execute('DELETE FROM treeupdatesactions') 2632 self._cursor().executemany(""" 2633 INSERT INTO treeupdatesactions VALUES (?, ?, ?, ?, ?) 2634 """, updates)
2635
2636 - def removeTreeUpdatesActions(self, repository):
2637 """ 2638 Reimplemented from EntropyRepositoryBase. 2639 """ 2640 self._cursor().execute(""" 2641 DELETE FROM treeupdatesactions WHERE repository = ? 2642 """, (repository,))
2643
2644 - def insertTreeUpdatesActions(self, updates, repository):
2645 """ 2646 Reimplemented from EntropyRepositoryBase. 2647 """ 2648 myupdates = [[repository]+list(x) for x in updates] 2649 self._cursor().executemany(""" 2650 INSERT INTO treeupdatesactions VALUES (NULL, ?, ?, ?, ?) 2651 """, myupdates)
2652
2653 - def setRepositoryUpdatesDigest(self, repository, digest):
2654 """ 2655 Reimplemented from EntropyRepositoryBase. 2656 """ 2657 self._cursor().execute(""" 2658 DELETE FROM treeupdates where repository = ? 2659 """, (repository,)) 2660 self._cursor().execute(""" 2661 INSERT INTO treeupdates VALUES (?, ?) 2662 """, (repository, digest,))
2663
2664 - def addRepositoryUpdatesActions(self, repository, actions, branch):
2665 """ 2666 Reimplemented from EntropyRepositoryBase. 2667 """ 2668 mytime = str(time.time()) 2669 myupdates = [ 2670 (repository, x, branch, mytime,) for x in actions \ 2671 if not self._doesTreeupdatesActionExist(repository, x, branch) 2672 ] 2673 self._cursor().executemany(""" 2674 INSERT INTO treeupdatesactions VALUES (NULL, ?, ?, ?, ?) 2675 """, myupdates)
2676
2677 - def _doesTreeupdatesActionExist(self, repository, command, branch):
2678 """ 2679 This method should be considered internal and not suited for general 2680 audience. 2681 Return whether provided "treeupdates" action in repository with 2682 provided branch exists. 2683 2684 @param repository: repository identifier 2685 @type repository: string 2686 @param command: treeupdates command 2687 @type command: string 2688 @param branch: branch metadata bound to command argument value given 2689 @type branch: string 2690 @return: if True, provided treeupdates action already exists 2691 @rtype: bool 2692 """ 2693 cur = self._cursor().execute(""" 2694 SELECT idupdate FROM treeupdatesactions 2695 WHERE repository = ? and command = ? 2696 and branch = ? LIMIT 1 2697 """, (repository, command, branch,)) 2698 2699 result = cur.fetchone() 2700 if result: 2701 return True 2702 return False
2703
2704 - def clearPackageSets(self):
2705 """ 2706 Reimplemented from EntropyRepositoryBase. 2707 """ 2708 self._cursor().execute('DELETE FROM packagesets')
2709
2710 - def insertPackageSets(self, sets_data):
2711 """ 2712 Reimplemented from EntropyRepositoryBase. 2713 """ 2714 mysets = [] 2715 for setname in sorted(sets_data): 2716 for dependency in sorted(sets_data[setname]): 2717 try: 2718 mysets.append((const_convert_to_unicode(setname), 2719 const_convert_to_unicode(dependency),)) 2720 except (UnicodeDecodeError, UnicodeEncodeError,): 2721 continue 2722 2723 self._cursor().executemany(""" 2724 INSERT INTO packagesets VALUES (?, ?) 2725 """, mysets)
2726
2727 - def retrievePackageSets(self):
2728 """ 2729 Reimplemented from EntropyRepositoryBase. 2730 """ 2731 cur = self._cursor().execute(""" 2732 SELECT setname, dependency FROM packagesets 2733 """) 2734 sets = {} 2735 for setname, dependency in cur: 2736 obj = sets.setdefault(setname, set()) 2737 obj.add(dependency) 2738 return sets
2739
2740 - def retrievePackageSet(self, setname):
2741 """ 2742 Reimplemented from EntropyRepositoryBase. 2743 """ 2744 cur = self._cursor().execute(""" 2745 SELECT dependency FROM packagesets WHERE setname = ?""", 2746 (setname,)) 2747 return self._cur2frozenset(cur)
2748
2749 - def retrieveAtom(self, package_id):
2750 """ 2751 Reimplemented from EntropyRepositoryBase. 2752 """ 2753 cur = self._cursor().execute(""" 2754 SELECT atom FROM baseinfo WHERE idpackage = ? LIMIT 1 2755 """, (package_id,)) 2756 atom = cur.fetchone() 2757 if atom: 2758 return atom[0]
2759
2760 - def retrieveBranch(self, package_id):
2761 """ 2762 Reimplemented from EntropyRepositoryBase. 2763 """ 2764 cur = self._cursor().execute(""" 2765 SELECT branch FROM baseinfo WHERE idpackage = ? LIMIT 1 2766 """, (package_id,)) 2767 branch = cur.fetchone() 2768 if branch: 2769 return branch[0]
2770
2771 - def retrieveTrigger(self, package_id):
2772 """ 2773 Reimplemented from EntropyRepositoryBase. 2774 """ 2775 cur = self._cursor().execute(""" 2776 SELECT data FROM triggers WHERE idpackage = ? LIMIT 1 2777 """, (package_id,)) 2778 trigger = cur.fetchone() 2779 if not trigger: 2780 # backward compatibility with <=0.52.x 2781 return const_convert_to_rawstring('') 2782 return const_convert_to_rawstring(trigger[0])
2783
2784 - def retrieveDownloadURL(self, package_id):
2785 """ 2786 Reimplemented from EntropyRepositoryBase. 2787 """ 2788 cur = self._cursor().execute(""" 2789 SELECT download FROM extrainfo WHERE idpackage = ? LIMIT 1 2790 """, (package_id,)) 2791 download = cur.fetchone() 2792 if download: 2793 return download[0]
2794
2795 - def retrieveDescription(self, package_id):
2796 """ 2797 Reimplemented from EntropyRepositoryBase. 2798 """ 2799 cur = self._cursor().execute(""" 2800 SELECT description FROM extrainfo WHERE idpackage = ? LIMIT 1 2801 """, (package_id,)) 2802 description = cur.fetchone() 2803 if description: 2804 return description[0]
2805
2806 - def retrieveHomepage(self, package_id):
2807 """ 2808 Reimplemented from EntropyRepositoryBase. 2809 """ 2810 cur = self._cursor().execute(""" 2811 SELECT homepage FROM extrainfo WHERE idpackage = ? LIMIT 1 2812 """, (package_id,)) 2813 home = cur.fetchone() 2814 if home: 2815 return home[0]
2816
2817 - def retrieveSpmUid(self, package_id):
2818 """ 2819 Reimplemented from EntropyRepositoryBase. 2820 """ 2821 cur = self._cursor().execute(""" 2822 SELECT counters.counter FROM counters,baseinfo 2823 WHERE counters.idpackage = ? AND 2824 baseinfo.idpackage = counters.idpackage AND 2825 baseinfo.branch = counters.branch LIMIT 1 2826 """, (package_id,)) 2827 mycounter = cur.fetchone() 2828 if mycounter: 2829 return mycounter[0] 2830 return -1
2831
2832 - def retrieveSize(self, package_id):
2833 """ 2834 Reimplemented from EntropyRepositoryBase. 2835 """ 2836 cur = self._cursor().execute(""" 2837 SELECT size FROM extrainfo WHERE idpackage = ? LIMIT 1 2838 """, (package_id,)) 2839 size = cur.fetchone() 2840 if size: 2841 try: 2842 return int(size[0]) 2843 except ValueError: # wtf? 2844 return 0
2845
2846 - def retrieveOnDiskSize(self, package_id):
2847 """ 2848 Reimplemented from EntropyRepositoryBase. 2849 """ 2850 cur = self._cursor().execute(""" 2851 SELECT size FROM sizes WHERE idpackage = ? LIMIT 1 2852 """, (package_id,)) 2853 size = cur.fetchone() 2854 if size: 2855 return size[0] 2856 return 0
2857
2858 - def retrieveDigest(self, package_id):
2859 """ 2860 Reimplemented from EntropyRepositoryBase. 2861 """ 2862 cur = self._cursor().execute(""" 2863 SELECT digest FROM extrainfo WHERE idpackage = ? LIMIT 1 2864 """, (package_id,)) 2865 digest = cur.fetchone() 2866 if digest: 2867 return digest[0] 2868 return None
2869
2870 - def retrieveSignatures(self, package_id):
2871 """ 2872 Reimplemented from EntropyRepositoryBase. 2873 """ 2874 cur = self._cursor().execute(""" 2875 SELECT sha1, sha256, sha512, gpg FROM packagesignatures 2876 WHERE idpackage = ? LIMIT 1 2877 """, (package_id,)) 2878 data = cur.fetchone() 2879 2880 if data: 2881 return data 2882 return None, None, None, None
2883
2884 - def retrieveExtraDownload(self, package_id, down_type = None):
2885 """ 2886 Reimplemented from EntropyRepositoryBase. 2887 """ 2888 down_type_str = "" 2889 params = [package_id] 2890 if down_type is not None: 2891 down_type_str = " AND down_type = ?" 2892 params.append(down_type) 2893 2894 cur = self._cursor().execute(""" 2895 SELECT download, type, size, disksize, md5, sha1, 2896 sha256, sha512, gpg 2897 FROM packagedownloads WHERE idpackage = ? 2898 """ + down_type_str, params) 2899 2900 result = [] 2901 for download, d_type, size, d_size, md5, sha1, sha256, sha512, gpg in \ 2902 cur: 2903 result.append({ 2904 "download": download, 2905 "type": d_type, 2906 "size": size, 2907 "disksize": d_size, 2908 "md5": md5, 2909 "sha1": sha1, 2910 "sha256": sha256, 2911 "sha512": sha512, 2912 "gpg": gpg, 2913 }) 2914 return tuple(result)
2915
2916 - def retrieveName(self, package_id):
2917 """ 2918 Reimplemented from EntropyRepositoryBase. 2919 """ 2920 cur = self._cursor().execute(""" 2921 SELECT name FROM baseinfo WHERE idpackage = ? LIMIT 1 2922 """, (package_id,)) 2923 name = cur.fetchone() 2924 if name: 2925 return name[0]
2926
2927 - def retrieveKeySplit(self, package_id):
2928 """ 2929 Reimplemented from EntropyRepositoryBase. 2930 """ 2931 cur = self._cursor().execute(""" 2932 SELECT category, name FROM baseinfo 2933 WHERE idpackage = ? LIMIT 1 2934 """, (package_id,)) 2935 return cur.fetchone()
2936
2937 - def retrieveKeySlot(self, package_id):
2938 """ 2939 Reimplemented from EntropyRepositoryBase. 2940 """ 2941 concat = self._concatOperator(("category", "'/'", "name")) 2942 cur = self._cursor().execute(""" 2943 SELECT %s, slot FROM baseinfo 2944 WHERE idpackage = ? LIMIT 1 2945 """ % (concat,), (package_id,)) 2946 return cur.fetchone()
2947
2948 - def retrieveKeySlotAggregated(self, package_id):
2949 """ 2950 Reimplemented from EntropyRepositoryBase. 2951 """ 2952 concat = self._concatOperator( 2953 ("category", 2954 "'/'", 2955 "name", 2956 "'%s'" % (etpConst['entropyslotprefix'],), 2957 "slot")) 2958 cur = self._cursor().execute(""" 2959 SELECT %s FROM baseinfo 2960 WHERE idpackage = ? LIMIT 1 2961 """ % (concat,), (package_id,)) 2962 keyslot = cur.fetchone() 2963 if keyslot: 2964 return keyslot[0] 2965 return None
2966
2967 - def retrieveKeySlotTag(self, package_id):
2968 """ 2969 Reimplemented from EntropyRepositoryBase. 2970 """ 2971 concat = self._concatOperator(("category", "'/'", "name")) 2972 cur = self._cursor().execute(""" 2973 SELECT %s, slot, versiontag 2974 FROM baseinfo WHERE 2975 idpackage = ? LIMIT 1 2976 """ % (concat,), (package_id,)) 2977 return cur.fetchone()
2978
2979 - def retrieveVersion(self, package_id):
2980 """ 2981 Reimplemented from EntropyRepositoryBase. 2982 """ 2983 cur = self._cursor().execute(""" 2984 SELECT version FROM baseinfo 2985 WHERE idpackage = ? LIMIT 1 2986 """, (package_id,)) 2987 version = cur.fetchone() 2988 if version: 2989 return version[0] 2990 return None
2991
2992 - def retrieveRevision(self, package_id):
2993 """ 2994 Reimplemented from EntropyRepositoryBase. 2995 """ 2996 cur = self._cursor().execute(""" 2997 SELECT revision FROM baseinfo 2998 WHERE idpackage = ? LIMIT 1 2999 """, (package_id,)) 3000 rev = cur.fetchone() 3001 if rev: 3002 return rev[0] 3003 return None
3004
3005 - def retrieveCreationDate(self, package_id):
3006 """ 3007 Reimplemented from EntropyRepositoryBase. 3008 """ 3009 cur = self._cursor().execute(""" 3010 SELECT datecreation FROM extrainfo WHERE idpackage = ? LIMIT 1 3011 """, (package_id,)) 3012 date = cur.fetchone() 3013 if date: 3014 return date[0]
3015
3016 - def retrieveApi(self, package_id):
3017 """ 3018 Reimplemented from EntropyRepositoryBase. 3019 """ 3020 cur = self._cursor().execute(""" 3021 SELECT etpapi FROM baseinfo WHERE idpackage = ? LIMIT 1 3022 """, (package_id,)) 3023 api = cur.fetchone() 3024 if api: 3025 return api[0]
3026
3027 - def retrieveUseflags(self, package_id):
3028 """ 3029 Reimplemented from EntropyRepositoryBase. 3030 """ 3031 cur = self._cursor().execute(""" 3032 SELECT useflagsreference.flagname 3033 FROM useflags, useflagsreference 3034 WHERE useflags.idpackage = ? 3035 AND useflags.idflag = useflagsreference.idflag 3036 """, (package_id,)) 3037 return self._cur2frozenset(cur)
3038
3039 - def retrieveSpmPhases(self, package_id):
3040 """ 3041 Reimplemented from EntropyRepositoryBase. 3042 """ 3043 cur = self._cursor().execute(""" 3044 SELECT phases FROM packagespmphases WHERE idpackage = ? LIMIT 1 3045 """, (package_id,)) 3046 spm_phases = cur.fetchone() 3047 3048 if spm_phases: 3049 return spm_phases[0]
3050
3051 - def retrieveSpmRepository(self, package_id):
3052 """ 3053 Reimplemented from EntropyRepositoryBase. 3054 """ 3055 cur = self._cursor().execute(""" 3056 SELECT repository FROM packagespmrepository 3057 WHERE idpackage = ? LIMIT 1 3058 """, (package_id,)) 3059 spm_repo = cur.fetchone() 3060 3061 if spm_repo: 3062 return spm_repo[0]
3063
3064 - def retrieveDesktopMime(self, package_id):
3065 """ 3066 Reimplemented from EntropyRepositoryBase. 3067 """ 3068 cur = self._cursor().execute(""" 3069 SELECT name, mimetype, executable, icon FROM packagedesktopmime 3070 WHERE idpackage = ?""", (package_id,)) 3071 data = [] 3072 for row in cur: 3073 item = {} 3074 item['name'], item['mimetype'], item['executable'], \ 3075 item['icon'] = row 3076 data.append(item) 3077 return data
3078
3079 - def retrieveProvidedMime(self, package_id):
3080 """ 3081 Reimplemented from EntropyRepositoryBase. 3082 """ 3083 cur = self._cursor().execute(""" 3084 SELECT mimetype FROM provided_mime WHERE idpackage = ? 3085 """, (package_id,)) 3086 return self._cur2frozenset(cur)
3087
3088 - def retrieveNeeded(self, package_id, extended = False, formatted = False):
3089 """ 3090 Reimplemented from EntropyRepositoryBase. 3091 """ 3092 if not self._doesTableExist("needed_libs"): 3093 # TODO: remove in 2016. 3094 return self._compatRetrieveNeeded( 3095 package_id, extended=extended, formatted=formatted) 3096 3097 if extended: 3098 cur = self._cursor().execute(""" 3099 SELECT soname, elfclass FROM needed_libs 3100 WHERE idpackage = ? ORDER BY soname 3101 """, (package_id,)) 3102 needed = tuple(cur) 3103 3104 else: 3105 cur = self._cursor().execute(""" 3106 SELECT soname FROM needed_libs 3107 WHERE idpackage = ? ORDER BY soname 3108 """, (package_id,)) 3109 needed = self._cur2tuple(cur) 3110 3111 if extended and formatted: 3112 return dict((lib, elfclass,) for lib, elfclass in needed) 3113 return needed
3114
3115 - def _compatRetrieveNeeded(self, package_id, extended = False, 3116 formatted = False):
3117 """ 3118 Backward compatibility schema support for retrieveNeeded(). 3119 """ 3120 if extended: 3121 cur = self._cursor().execute(""" 3122 SELECT library,elfclass FROM needed,neededreference 3123 WHERE needed.idpackage = ? AND 3124 needed.idneeded = neededreference.idneeded ORDER BY library 3125 """, (package_id,)) 3126 needed = tuple(cur) 3127 3128 else: 3129 cur = self._cursor().execute(""" 3130 SELECT library FROM needed,neededreference 3131 WHERE needed.idpackage = ? AND 3132 needed.idneeded = neededreference.idneeded ORDER BY library 3133 """, (package_id,)) 3134 needed = self._cur2tuple(cur) 3135 3136 if extended and formatted: 3137 return dict((lib, elfclass,) for lib, elfclass in needed) 3138 return needed
3139
3140 - def retrieveNeededLibraries(self, package_id):
3141 """ 3142 Reimplemented from EntropyRepositoryBase. 3143 """ 3144 cur = self._cursor().execute(""" 3145 SELECT lib_user_path, lib_user_soname, soname, elfclass, rpath 3146 FROM needed_libs WHERE idpackage = ? 3147 """, (package_id,)) 3148 return frozenset(cur)
3149
3150 - def retrieveProvidedLibraries(self, package_id):
3151 """ 3152 Reimplemented from EntropyRepositoryBase. 3153 """ 3154 cur = self._cursor().execute(""" 3155 SELECT library, path, elfclass FROM provided_libs 3156 WHERE idpackage = ? 3157 """, (package_id,)) 3158 return frozenset(cur)
3159
3160 - def retrieveConflicts(self, package_id):
3161 """ 3162 Reimplemented from EntropyRepositoryBase. 3163 """ 3164 cur = self._cursor().execute(""" 3165 SELECT conflict FROM conflicts WHERE idpackage = ? 3166 """, (package_id,)) 3167 return self._cur2frozenset(cur)
3168
3169 - def retrieveProvide(self, package_id):
3170 """ 3171 Reimplemented from EntropyRepositoryBase. 3172 """ 3173 cur = self._cursor().execute(""" 3174 SELECT atom, is_default FROM provide WHERE idpackage = ? 3175 """, (package_id,)) 3176 return frozenset(cur)
3177
3178 - def retrieveDependenciesList(self, package_id, exclude_deptypes = None, 3179 resolve_conditional_deps = True):
3180 """ 3181 Reimplemented from EntropyRepositoryBase. 3182 """ 3183 excluded_deptypes_query = "" 3184 if exclude_deptypes is not None: 3185 for dep_type in exclude_deptypes: 3186 excluded_deptypes_query += \ 3187 " AND dependencies.type != %d" % (dep_type,) 3188 3189 concat = self._concatOperator( 3190 ("'!'", "conflict")) 3191 cur = self._cursor().execute(""" 3192 SELECT dependenciesreference.dependency 3193 FROM dependencies, dependenciesreference 3194 WHERE dependencies.idpackage = (?) AND 3195 dependencies.iddependency = dependenciesreference.iddependency %s 3196 UNION SELECT %s FROM conflicts 3197 WHERE idpackage = (?)""" % (excluded_deptypes_query, concat,), 3198 (package_id, package_id,)) 3199 if resolve_conditional_deps: 3200 return frozenset(entropy.dep.expand_dependencies(cur, [self])) 3201 else: 3202 return self._cur2frozenset(cur)
3203
3204 - def retrieveBuildDependencies(self, package_id, extended = False, 3205 resolve_conditional_deps = True):
3206 """ 3207 Reimplemented from EntropyRepositoryBase. 3208 """ 3209 return self.retrieveDependencies(package_id, extended = extended, 3210 deptype = etpConst['dependency_type_ids']['bdepend_id'], 3211 resolve_conditional_deps = resolve_conditional_deps)
3212
3213 - def retrieveRuntimeDependencies(self, package_id, extended = False, 3214 resolve_conditional_deps = True):
3215 """ 3216 Reimplemented from EntropyRepositoryBase. 3217 """ 3218 return self.retrieveDependencies(package_id, extended = extended, 3219 deptype = etpConst['dependency_type_ids']['rdepend_id'], 3220 resolve_conditional_deps = resolve_conditional_deps)
3221
3222 - def retrievePostDependencies(self, package_id, extended = False, 3223 resolve_conditional_deps = True):
3224 """ 3225 Reimplemented from EntropyRepositoryBase. 3226 """ 3227 return self.retrieveDependencies(package_id, extended = extended, 3228 deptype = etpConst['dependency_type_ids']['pdepend_id'], 3229 resolve_conditional_deps = resolve_conditional_deps)
3230
3231 - def retrieveManualDependencies(self, package_id, extended = False, 3232 resolve_conditional_deps = True):
3233 """ 3234 Reimplemented from EntropyRepositoryBase. 3235 """ 3236 return self.retrieveDependencies(package_id, extended = extended, 3237 deptype = etpConst['dependency_type_ids']['mdepend_id'], 3238 resolve_conditional_deps = resolve_conditional_deps)
3239
3240 - def retrieveDependencies(self, package_id, extended = False, 3241 deptype = None, exclude_deptypes = None, 3242 resolve_conditional_deps = True):
3243 """ 3244 Reimplemented from EntropyRepositoryBase. 3245 """ 3246 searchdata = (package_id,) 3247 3248 depstring = '' 3249 if deptype is not None: 3250 depstring = 'and dependencies.type = ?' 3251 searchdata += (deptype,) 3252 3253 excluded_deptypes_query = "" 3254 if exclude_deptypes is not None: 3255 for dep_type in exclude_deptypes: 3256 excluded_deptypes_query += " AND dependencies.type != %d" % ( 3257 dep_type,) 3258 3259 cur = None 3260 iter_obj = None 3261 if extended: 3262 cur = self._cursor().execute(""" 3263 SELECT dependenciesreference.dependency,dependencies.type 3264 FROM dependencies,dependenciesreference 3265 WHERE dependencies.idpackage = ? AND 3266 dependencies.iddependency = 3267 dependenciesreference.iddependency %s %s""" % ( 3268 depstring, excluded_deptypes_query,), searchdata) 3269 iter_obj = tuple 3270 else: 3271 cur = self._cursor().execute(""" 3272 SELECT dependenciesreference.dependency 3273 FROM dependencies,dependenciesreference 3274 WHERE dependencies.idpackage = ? AND 3275 dependencies.iddependency = 3276 dependenciesreference.iddependency %s %s""" % ( 3277 depstring, excluded_deptypes_query,), searchdata) 3278 iter_obj = frozenset 3279 3280 if resolve_conditional_deps: 3281 return iter_obj(entropy.dep.expand_dependencies( 3282 cur, [self])) 3283 return iter_obj(cur)
3284
3285 - def retrieveKeywords(self, package_id):
3286 """ 3287 Reimplemented from EntropyRepositoryBase. 3288 """ 3289 cur = self._cursor().execute(""" 3290 SELECT keywordname FROM keywords,keywordsreference 3291 WHERE keywords.idpackage = ? AND 3292 keywords.idkeyword = keywordsreference.idkeyword""", (package_id,)) 3293 return self._cur2frozenset(cur)
3294
3295 - def retrieveProtect(self, package_id):
3296 """ 3297 Reimplemented from EntropyRepositoryBase. 3298 """ 3299 cur = self._cursor().execute(""" 3300 SELECT protect FROM configprotect,configprotectreference 3301 WHERE configprotect.idpackage = ? AND 3302 configprotect.idprotect = configprotectreference.idprotect 3303 LIMIT 1 3304 """, (package_id,)) 3305 3306 protect = cur.fetchone() 3307 if protect: 3308 return protect[0] 3309 return ''
3310
3311 - def retrieveProtectMask(self, package_id):
3312 """ 3313 Reimplemented from EntropyRepositoryBase. 3314 """ 3315 cur = self._cursor().execute(""" 3316 SELECT protect FROM configprotectmask,configprotectreference 3317 WHERE idpackage = ? AND 3318 configprotectmask.idprotect = configprotectreference.idprotect 3319 LIMIT 1 3320 """, (package_id,)) 3321 3322 protect = cur.fetchone() 3323 if protect: 3324 return protect[0] 3325 return ''
3326
3327 - def retrieveSources(self, package_id, extended = False):
3328 """ 3329 Reimplemented from EntropyRepositoryBase. 3330 """ 3331 cur = self._cursor().execute(""" 3332 SELECT sourcesreference.source FROM sources, sourcesreference 3333 WHERE idpackage = ? AND 3334 sources.idsource = sourcesreference.idsource 3335 """, (package_id,)) 3336 sources = self._cur2frozenset(cur) 3337 if not extended: 3338 return sources 3339 3340 source_data = {} 3341 mirror_str = "mirror://" 3342 for source in sources: 3343 3344 source_data[source] = set() 3345 if source.startswith(mirror_str): 3346 3347 mirrorname = source.split("/")[2] 3348 # avoid leading "/" 3349 mirror_url = source.split("/", 3)[3:][0].lstrip("/") 3350 source_data[source] |= set( 3351 [url.rstrip("/") + "/" + mirror_url for url in \ 3352 self.retrieveMirrorData(mirrorname)]) 3353 3354 else: 3355 source_data[source].add(source) 3356 3357 return source_data
3358
3359 - def retrieveAutomergefiles(self, package_id, get_dict = False):
3360 """ 3361 Reimplemented from EntropyRepositoryBase. 3362 """ 3363 # like portage does 3364 self._connection().unicode() 3365 3366 cur = self._cursor().execute(""" 3367 SELECT configfile, md5 FROM automergefiles WHERE idpackage = ? 3368 """, (package_id,)) 3369 data = frozenset(cur) 3370 3371 if get_dict: 3372 data = dict(((x, y,) for x, y in data)) 3373 return data
3374
3375 - def retrieveContent(self, package_id, extended = False, 3376 formatted = False, insert_formatted = False, order_by = None):
3377 """ 3378 Reimplemented from EntropyRepositoryBase. 3379 """ 3380 extstring = '' 3381 if extended: 3382 extstring = ",type" 3383 extstring_package_id = '' 3384 if insert_formatted: 3385 extstring_package_id = 'idpackage,' 3386 3387 searchkeywords = (package_id,) 3388 order_by_string = '' 3389 if order_by is not None: 3390 if order_by not in ("package_id", "idpackage", "file", "type",): 3391 raise AttributeError("invalid order_by argument") 3392 if order_by == "package_id": 3393 order_by = "idpackage" 3394 order_by_string = ' order by %s' % (order_by,) 3395 3396 cur = self._cursor().execute(""" 3397 SELECT %s file%s FROM content WHERE idpackage = ? %s""" % ( 3398 extstring_package_id, extstring, order_by_string,), 3399 searchkeywords) 3400 3401 if extended and insert_formatted: 3402 fl = tuple(cur) 3403 3404 elif extended and formatted: 3405 fl = {} 3406 items = cur.fetchone() 3407 while items: 3408 fl[items[0]] = items[1] 3409 items = cur.fetchone() 3410 3411 elif extended: 3412 fl = tuple(cur) 3413 3414 else: 3415 if order_by: 3416 fl = self._cur2tuple(cur) 3417 else: 3418 fl = self._cur2frozenset(cur) 3419 3420 return fl
3421
3422 - def retrieveContentIter(self, package_id, order_by = None, 3423 reverse = False):
3424 """ 3425 Reimplemented from EntropyRepositoryBase. 3426 """ 3427 class MyIter: 3428 3429 def __init__(self, db, query, keywords): 3430 self._cur = None 3431 self._db = db 3432 self._query = query 3433 self._keywords = keywords 3434 self._init_cur()
3435 3436 def _init_cur(self): 3437 self._cur = self._db._cursor().execute( 3438 self._query, self._keywords) 3439 3440 def __iter__(self): 3441 self._init_cur() 3442 return self 3443 3444 def __next__(self): 3445 return next(self._cur) 3446