1
2 '''
3 # DESCRIPTION:
4 # Entropy Object Oriented Interface
5
6 Copyright (C) 2007-2009 Fabio Erculiani
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 '''
22 from __future__ import with_statement
23 import os
24 import stat
25 import sys
26 import shutil
27 import time
28 import subprocess
29 import tempfile
30 from entropy.i18n import _
31 from entropy.const import *
32 from entropy.exceptions import *
33 from entropy.db import dbapi2, LocalRepository, EntropyRepository
34 from entropy.output import purple, bold, red, blue, darkgreen, darkred, brown
35
36
38
39 __repo_error_messages_cache = set()
40 __repodb_cache = {}
41 _memory_db_instances = {}
42
44 self.MirrorStatus.clear()
45 self.__repo_error_messages_cache.clear()
46
47
48 cl_id = self.sys_settings_client_plugin_id
49 client_metadata = self.SystemSettings.get(cl_id, {})
50 if "masking_validation" in client_metadata:
51 client_metadata['masking_validation']['cache'].clear()
52
53
54 del self.validRepositories[:]
55 for repoid in self.SystemSettings['repositories']['order']:
56
57 try:
58 dbc = self.open_repository(repoid)
59 dbc.listConfigProtectDirectories()
60 dbc.validateDatabase()
61 self.validRepositories.append(repoid)
62 except RepositoryError:
63 t = _("Repository") + " " + repoid + " " + \
64 _("is not available") + ". " + _("Cannot validate")
65 t2 = _("Please update your repositories now in order to remove this message!")
66 self.updateProgress(
67 darkred(t),
68 importance = 1,
69 type = "warning"
70 )
71 self.updateProgress(
72 purple(t2),
73 header = bold("!!! "),
74 importance = 1,
75 type = "warning"
76 )
77 continue
78 except (self.dbapi2.OperationalError,self.dbapi2.DatabaseError,SystemDatabaseError,):
79 t = _("Repository") + " " + repoid + " " + \
80 _("is corrupted") + ". " + _("Cannot validate")
81 self.updateProgress(
82 darkred(t),
83 importance = 1,
84 type = "warning"
85 )
86 continue
87
88 self.close_all_repositories(mask_clear = False)
89
91 return (repoid, etpConst['systemroot'],)
92
94 dbc = self.open_memory_database(dbname = repoid)
95 repo_key = self.__get_repository_cache_key(repoid)
96 self._memory_db_instances[repo_key] = dbc
97
98
99 repodata = {
100 'repoid': repoid,
101 'in_memory': True,
102 'description': description,
103 'packages': package_mirrors,
104 'dbpath': ':memory:',
105 }
106 self.add_repository(repodata)
107 return dbc
108
120
125
139
141
142 if isinstance(repoid,basestring):
143 if repoid.endswith(etpConst['packagesext']):
144 xcache = False
145
146 repo_data = self.SystemSettings['repositories']['available']
147 if repoid not in repo_data:
148 t = _("bad repository id specified")
149 if repoid not in self.__repo_error_messages_cache:
150 self.updateProgress(
151 darkred(t),
152 importance = 2,
153 type = "warning"
154 )
155 self.__repo_error_messages_cache.add(repoid)
156 raise RepositoryError("RepositoryError: %s" % (t,))
157
158 if repo_data[repoid].get('in_memory'):
159 repo_key = self.__get_repository_cache_key(repoid)
160 conn = self._memory_db_instances.get(repo_key)
161 else:
162 dbfile = repo_data[repoid]['dbpath']+"/"+etpConst['etpdatabasefile']
163 if not os.path.isfile(dbfile):
164 t = _("Repository %s hasn't been downloaded yet.") % (repoid,)
165 if repoid not in self.__repo_error_messages_cache:
166 self.updateProgress(
167 darkred(t),
168 importance = 2,
169 type = "warning"
170 )
171 self.__repo_error_messages_cache.add(repoid)
172 raise RepositoryError("RepositoryError: %s" % (t,))
173
174 conn = LocalRepository(
175 readOnly = True,
176 dbFile = dbfile,
177 clientDatabase = True,
178 dbname = etpConst['dbnamerepoprefix']+repoid,
179 xcache = xcache,
180 indexing = indexing,
181 OutputInterface = self,
182 ServiceInterface = self
183 )
184
185 if (repoid not in etpConst['client_treeupdatescalled']) and \
186 (self.entropyTools.is_root()) and \
187 (not repoid.endswith(etpConst['packagesext'])):
188
189 updated = False
190 try:
191 updated = conn.clientUpdatePackagesData(self.clientDbconn)
192 except (self.dbapi2.OperationalError, self.dbapi2.DatabaseError):
193 pass
194 if updated:
195 self.clear_dump_cache(etpCache['world_update'])
196 self.clear_dump_cache(etpCache['critical_update'])
197 self.clear_dump_cache(etpCache['world'])
198 self.clear_dump_cache(etpCache['install'])
199 self.clear_dump_cache(etpCache['remove'])
200 self.calculate_world_updates(use_cache = False)
201 return conn
202
204 fname = self.SystemSettings['repositories']['available'][reponame]['dbpath']+"/"+etpConst['etpdatabaserevisionfile']
205 revision = -1
206 if os.path.isfile(fname) and os.access(fname,os.R_OK):
207 with open(fname,"r") as f:
208 try:
209 revision = int(f.readline().strip())
210 except (OSError, IOError, ValueError,):
211 pass
212 return revision
213
219
221 fname = self.SystemSettings['repositories']['available'][reponame]['dbpath']+"/"+etpConst['etpdatabasehashfile']
222 mhash = "-1"
223 if os.path.isfile(fname) and os.access(fname,os.R_OK):
224 with open(fname,"r") as f:
225 try:
226 mhash = f.readline().strip().split()[0]
227 except (OSError, IOError, IndexError,):
228 pass
229 return mhash
230
232 product = self.SystemSettings['repositories']['product']
233 branch = self.SystemSettings['repositories']['branch']
234
235 try:
236 self.SystemSettings['repositories']['available'][repodata['repoid']] = {}
237 self.SystemSettings['repositories']['available'][repodata['repoid']]['description'] = repodata['description']
238 except KeyError:
239 t = _("repodata dictionary is corrupted")
240 raise InvalidData("InvalidData: %s" % (t,))
241
242 if repodata['repoid'].endswith(etpConst['packagesext']) or repodata.get('in_memory'):
243 try:
244
245 self.SystemSettings['repositories']['available'][repodata['repoid']]['packages'] = repodata['packages'][:]
246 smart_package = repodata.get('smartpackage')
247 if smart_package != None:
248 self.SystemSettings['repositories']['available'][repodata['repoid']]['smartpackage'] = smart_package
249 except KeyError:
250 raise InvalidData("InvalidData: repodata dictionary is corrupted")
251 self.SystemSettings['repositories']['available'][repodata['repoid']]['dbpath'] = repodata.get('dbpath')
252 self.SystemSettings['repositories']['available'][repodata['repoid']]['pkgpath'] = repodata.get('pkgpath')
253 self.SystemSettings['repositories']['available'][repodata['repoid']]['in_memory'] = repodata.get('in_memory')
254
255 self.SystemSettings['repositories']['order'].insert(0, repodata['repoid'])
256 else:
257
258 self.SystemSettings['repositories']['available'][repodata['repoid']]['plain_packages'] = repodata['plain_packages'][:]
259 self.SystemSettings['repositories']['available'][repodata['repoid']]['packages'] = [x+"/"+product for x in repodata['plain_packages']]
260 self.SystemSettings['repositories']['available'][repodata['repoid']]['plain_database'] = repodata['plain_database']
261 self.SystemSettings['repositories']['available'][repodata['repoid']]['database'] = repodata['plain_database'] + \
262 "/" + product + "/database/" + etpConst['currentarch'] + "/" + branch
263 if not repodata['dbcformat'] in etpConst['etpdatabasesupportedcformats']:
264 repodata['dbcformat'] = etpConst['etpdatabasesupportedcformats'][0]
265 self.SystemSettings['repositories']['available'][repodata['repoid']]['dbcformat'] = repodata['dbcformat']
266 self.SystemSettings['repositories']['available'][repodata['repoid']]['dbpath'] = etpConst['etpdatabaseclientdir'] + \
267 "/" + repodata['repoid'] + "/" + product + "/" + etpConst['currentarch'] + "/" + branch
268
269 myrev = self.get_repository_revision(repodata['repoid'])
270 if myrev == -1:
271 myrev = 0
272 self.SystemSettings['repositories']['available'][repodata['repoid']]['dbrevision'] = str(myrev)
273 if repodata.has_key("position"):
274 self.SystemSettings['repositories']['order'].insert(
275 repodata['position'], repodata['repoid'])
276 else:
277 self.SystemSettings['repositories']['order'].append(
278 repodata['repoid'])
279 if not repodata.has_key("service_port"):
280 repodata['service_port'] = int(etpConst['socket_service']['port'])
281 if not repodata.has_key("ssl_service_port"):
282 repodata['ssl_service_port'] = int(etpConst['socket_service']['ssl_port'])
283 self.SystemSettings['repositories']['available'][repodata['repoid']]['service_port'] = repodata['service_port']
284 self.SystemSettings['repositories']['available'][repodata['repoid']]['ssl_service_port'] = repodata['ssl_service_port']
285 self.repository_move_clear_cache(repodata['repoid'])
286
287 self.entropyTools.save_repository_settings(repodata)
288 self.SystemSettings.clear()
289 self.close_all_repositories()
290 self.validate_repositories()
291
329
340
350
377
379 try:
380 repodata = self.SystemSettings['repositories']['available'][repoid].copy()
381 except KeyError:
382 if not self.SystemSettings['repositories']['excluded'].has_key(repoid):
383 raise
384 repodata = self.SystemSettings['repositories']['excluded'][repoid].copy()
385 return repodata
386
387
389 atoms_contained = []
390 basefile = os.path.basename(tbz2file)
391 cut_idx = -1*(len(etpConst['packagesext']))
392 db_dir = tempfile.mkdtemp()
393 dbfile = self.entropyTools.extract_edb(tbz2file,
394 dbpath = db_dir+"/packages.db")
395 if dbfile == None:
396 return -1, atoms_contained
397 etpSys['dirstoclean'].add(os.path.dirname(dbfile))
398
399 repodata = {}
400 repodata['repoid'] = basefile
401 repodata['description'] = "Dynamic database from " + basefile
402 repodata['packages'] = []
403 repodata['dbpath'] = os.path.dirname(dbfile)
404 repodata['pkgpath'] = os.path.realpath(tbz2file)
405 repodata['smartpackage'] = False
406
407 mydbconn = self.open_generic_database(dbfile)
408
409 try:
410 myidpackages = mydbconn.listAllIdpackages()
411 except (AttributeError, self.dbapi2.DatabaseError, \
412 self.dbapi2.IntegrityError, self.dbapi2.OperationalError,):
413 return -2, atoms_contained
414 if len(myidpackages) > 1:
415 repodata[basefile]['smartpackage'] = True
416 for myidpackage in myidpackages:
417 compiled_arch = mydbconn.retrieveDownloadURL(myidpackage)
418 if compiled_arch.find("/"+etpSys['arch']+"/") == -1:
419 return -3, atoms_contained
420 atoms_contained.append((int(myidpackage), basefile))
421
422 self.add_repository(repodata)
423 self.validate_repositories()
424 if basefile not in self.validRepositories:
425 self.remove_repository(basefile)
426 return -4, atoms_contained
427 mydbconn.closeDB()
428 del mydbconn
429 return 0, atoms_contained
430
436
438
439 def load_db_from_ram():
440 self.safe_mode = etpConst['safemodeerrors']['clientdb']
441 mytxt = "%s, %s" % (_("System database not found or corrupted"),
442 _("running in safe mode using empty database from RAM"),)
443 self.updateProgress(
444 darkred(mytxt),
445 importance = 1,
446 type = "warning",
447 header = bold("!!!"),
448 )
449 conn = self.open_memory_database(dbname = etpConst['clientdbid'])
450 return conn
451
452 db_dir = os.path.dirname(etpConst['etpdatabaseclientfilepath'])
453 if not os.path.isdir(db_dir): os.makedirs(db_dir)
454
455 db_path = etpConst['etpdatabaseclientfilepath']
456 if (not self.noclientdb) and (not os.path.isfile(db_path)):
457 conn = load_db_from_ram()
458 self.entropyTools.print_traceback(f = self.clientLog)
459 else:
460 try:
461 conn = LocalRepository(readOnly = False, dbFile = db_path,
462 clientDatabase = True, dbname = etpConst['clientdbid'],
463 xcache = self.xcache, indexing = self.indexing,
464 OutputInterface = self, ServiceInterface = self
465 )
466 except (self.dbapi2.DatabaseError,):
467 self.entropyTools.print_traceback(f = self.clientLog)
468 conn = load_db_from_ram()
469 else:
470
471 if not self.noclientdb:
472 try:
473 conn.validateDatabase()
474 except SystemDatabaseError:
475 try:
476 conn.closeDB()
477 except:
478 pass
479 self.entropyTools.print_traceback(f = self.clientLog)
480 conn = load_db_from_ram()
481
482 self.clientDbconn = conn
483 return self.clientDbconn
484
486 self.updateProgress(
487 darkred(_("Sanity Check") + ": " + _("system database")),
488 importance = 2,
489 type = "warning"
490 )
491 idpkgs = self.clientDbconn.listAllIdpackages()
492 length = len(idpkgs)
493 count = 0
494 errors = False
495 scanning_txt = _("Scanning...")
496 for x in idpkgs:
497 count += 1
498 self.updateProgress(
499 darkgreen(scanning_txt),
500 importance = 0,
501 type = "info",
502 back = True,
503 count = (count,length),
504 percent = True
505 )
506 try:
507 self.clientDbconn.getPackageData(x)
508 except Exception ,e:
509 self.entropyTools.print_traceback()
510 errors = True
511 self.updateProgress(
512 darkred(_("Errors on idpackage %s, error: %s")) % (x,str(e)),
513 importance = 0,
514 type = "warning"
515 )
516
517 if not errors:
518 t = _("Sanity Check") + ": %s" % (bold(_("PASSED")),)
519 self.updateProgress(
520 darkred(t),
521 importance = 2,
522 type = "warning"
523 )
524 return 0
525 else:
526 t = _("Sanity Check") + ": %s" % (bold(_("CORRUPTED")),)
527 self.updateProgress(
528 darkred(t),
529 importance = 2,
530 type = "warning"
531 )
532 return -1
533
534 - def open_generic_database(self, dbfile, dbname = None, xcache = None,
535 readOnly = False, indexing_override = None, skipChecks = False):
536 if xcache == None:
537 xcache = self.xcache
538 if indexing_override != None:
539 indexing = indexing_override
540 else:
541 indexing = self.indexing
542 if dbname == None:
543 dbname = etpConst['genericdbid']
544 return LocalRepository(
545 readOnly = readOnly,
546 dbFile = dbfile,
547 clientDatabase = True,
548 dbname = dbname,
549 xcache = xcache,
550 indexing = indexing,
551 OutputInterface = self,
552 skipChecks = skipChecks
553 )
554
556 if dbname == None:
557 dbname = etpConst['genericdbid']
558 dbc = LocalRepository(
559 readOnly = False,
560 dbFile = ':memory:',
561 clientDatabase = True,
562 dbname = dbname,
563 xcache = False,
564 indexing = False,
565 OutputInterface = self,
566 skipChecks = True,
567 ServiceInterface = self
568 )
569 dbc.initializeDatabase()
570 return dbc
571
572 - def backup_database(self, dbpath, backup_dir = None, silent = False, compress_level = 9):
573
574 if compress_level not in range(1,10):
575 compress_level = 9
576
577 backup_dir = os.path.dirname(dbpath)
578 if not backup_dir: backup_dir = os.path.dirname(dbpath)
579 dbname = os.path.basename(dbpath)
580 bytes_required = 1024000*300
581 if not (os.access(backup_dir,os.W_OK) and \
582 os.path.isdir(backup_dir) and os.path.isfile(dbpath) and \
583 os.access(dbpath,os.R_OK) and self.entropyTools.check_required_space(backup_dir, bytes_required)):
584 if not silent:
585 mytxt = "%s: %s, %s" % (darkred(_("Cannot backup selected database")),blue(dbpath),darkred(_("permission denied")),)
586 self.updateProgress(
587 mytxt,
588 importance = 1,
589 type = "error",
590 header = red(" @@ ")
591 )
592 return False, mytxt
593
594 def get_ts():
595 from datetime import datetime
596 ts = datetime.fromtimestamp(time.time())
597 return "%s%s%s_%sh%sm%ss" % (ts.year,ts.month,ts.day,ts.hour,ts.minute,ts.second)
598
599 comp_dbname = "%s%s.%s.bz2" % (etpConst['dbbackupprefix'],dbname,get_ts(),)
600 comp_dbpath = os.path.join(backup_dir,comp_dbname)
601 if not silent:
602 mytxt = "%s: %s ..." % (darkgreen(_("Backing up database to")),blue(comp_dbpath),)
603 self.updateProgress(
604 mytxt,
605 importance = 1,
606 type = "info",
607 header = blue(" @@ "),
608 back = True
609 )
610 import bz2
611 try:
612 self.entropyTools.compress_file(dbpath, comp_dbpath, bz2.BZ2File, compress_level)
613 except:
614 if not silent:
615 self.entropyTools.print_traceback()
616 return False, _("Unable to compress")
617
618 if not silent:
619 mytxt = "%s: %s" % (darkgreen(_("Database backed up successfully")),blue(comp_dbpath),)
620 self.updateProgress(
621 mytxt,
622 importance = 1,
623 type = "info",
624 header = blue(" @@ "),
625 back = True
626 )
627 return True, _("All fine")
628
630
631 bytes_required = 1024000*300
632 db_dir = os.path.dirname(db_destination)
633 if not (os.access(db_dir,os.W_OK) and os.path.isdir(db_dir) and \
634 os.path.isfile(backup_path) and os.access(backup_path,os.R_OK) and \
635 self.entropyTools.check_required_space(db_dir, bytes_required)):
636
637 if not silent:
638 mytxt = "%s: %s, %s" % (darkred(_("Cannot restore selected backup")),
639 blue(backup_path),darkred(_("permission denied")),)
640 self.updateProgress(
641 mytxt,
642 importance = 1,
643 type = "error",
644 header = red(" @@ ")
645 )
646 return False, mytxt
647
648 if not silent:
649 mytxt = "%s: %s => %s ..." % (darkgreen(_("Restoring backed up database")),
650 blue(os.path.basename(backup_path)),blue(db_destination),)
651 self.updateProgress(
652 mytxt,
653 importance = 1,
654 type = "info",
655 header = blue(" @@ "),
656 back = True
657 )
658
659 import bz2
660 try:
661 self.entropyTools.uncompress_file(backup_path, db_destination, bz2.BZ2File)
662 except:
663 if not silent:
664 self.entropyTools.print_traceback()
665 return False, _("Unable to unpack")
666
667 if not silent:
668 mytxt = "%s: %s" % (darkgreen(_("Database restored successfully")),
669 blue(db_destination),)
670 self.updateProgress(
671 mytxt,
672 importance = 1,
673 type = "info",
674 header = blue(" @@ "),
675 back = True
676 )
677 self.purge_cache()
678 return True, _("All fine")
679
681 if not client_dbdir:
682 client_dbdir = os.path.dirname(etpConst['etpdatabaseclientfilepath'])
683 return [os.path.join(client_dbdir,x) for x in os.listdir(client_dbdir) \
684 if x.startswith(etpConst['dbbackupprefix']) and \
685 os.access(os.path.join(client_dbdir,x),os.R_OK)
686 ]
687
689 """
690 This method is called whenever branch is successfully switched by user.
691 Branch is switched when user wants to upgrade the OS to a new
692 major release.
693 Any repository can be shipped with a sh script which if available,
694 handles system configuration to ease the migration.
695
696 @param old_branch: previously set branch
697 @type old_branch: string
698 @param new_branch: newly set branch
699 @type new_branch: string
700 @return: tuple composed by (1) list of repositories whose script has
701 been run and (2) bool describing if scripts exited with error
702 @rtype: tuple(set, bool)
703 """
704 from datetime import datetime
705
706 place_status_file = set()
707 hooks_ran = set()
708 errors = False
709 repo_data = self.SystemSettings['repositories']['available']
710 repo_data_excl = self.SystemSettings['repositories']['available']
711 all_repos = sorted(set(repo_data.keys() + repo_data_excl.keys()))
712 for repoid in all_repos:
713
714 mydata = repo_data.get(repoid)
715 if mydata is None:
716 mydata = repo_data_excl.get(repoid)
717
718 if mydata is None:
719 continue
720
721
722 status_file = mydata['post_branch_hop_status_file']
723 if os.access(status_file, os.F_OK):
724 continue
725 place_status_file.add(repoid)
726
727 branch_mig_script = mydata['post_branch_hop_script']
728 if os.access(branch_mig_script, os.F_OK):
729 args = ["/bin/sh", branch_mig_script, repoid, old_branch,
730 new_branch]
731 proc = subprocess.Popen(args, stdin = sys.stdin,
732 stdout = sys.stdout, stderr = sys.stderr)
733 mig_rc = proc.wait()
734 if mig_rc != 0:
735
736 errors = True
737 continue
738
739
740 if not os.path.isdir(os.path.dirname(status_file)):
741 continue
742
743 hooks_ran.add(repoid)
744 status_f = open(status_file, "w")
745 status_f.flush()
746 status_f.close()
747
748 for repoid in place_status_file:
749 status_file = self.get_post_branch_migration_status_file(repoid)
750 if status_file is None:
751 continue
752
753 avail = os.path.lexists(status_file)
754 if not avail:
755 ts = datetime.fromtimestamp(time.time())
756 status_f = open(status_file, "w")
757 status_f.write("%s => %s => %s\n" % (
758 ts, old_branch, new_branch,))
759 status_f.flush()
760 status_f.close()
761
762 return hooks_ran, errors
763
765 """
766 This method is called whenever branch is successfully switched by user
767 and all the updates have been installed (also look at:
768 run_repositories_post_branch_switch_hooks()).
769 Any repository can be shipped with a sh script which if available,
770 handles system configuration to ease the migration.
771
772 @return: list of repositories whose script has been run
773 @rtype: set
774 """
775 hooks_ran = set()
776
777 repo_data = self.SystemSettings['repositories']['available']
778 for repoid in self.validRepositories:
779
780 mydata = repo_data.get(repoid)
781 if mydata is None:
782 continue
783
784
785 branch_upg_script = mydata['post_branch_upgrade_script']
786 if not os.access(branch_upg_script, os.F_OK):
787
788
789 continue
790
791 status_file = self.get_post_branch_migration_status_file(repoid)
792 if status_file is None:
793 continue
794 avail = os.path.lexists(status_file)
795 if not avail:
796 continue
797
798
799 upgrade_status_file = self.get_post_branch_upgrade_status_file(
800 repoid)
801 if upgrade_status_file is None:
802 continue
803 avail = os.path.lexists(upgrade_status_file)
804 if avail:
805
806 continue
807
808 status_f = open(status_file, "r")
809
810 status_meta = status_f.readline().strip().split("=>")
811 status_f.close()
812
813 if len(status_meta) != 3:
814
815 continue
816
817
818 mtime, old_branch, new_branch = status_meta
819 args = ["/bin/sh", branch_upg_script, repoid, old_branch,
820 new_branch]
821 proc = subprocess.Popen(args, stdin = sys.stdin,
822 stdout = sys.stdout, stderr = sys.stderr)
823 mig_rc = proc.wait()
824 if mig_rc != 0:
825
826 continue
827
828
829
830 status_f = open(upgrade_status_file, "w")
831 status_f.flush()
832 status_f.close()
833 hooks_ran.add(repoid)
834
835 return hooks_ran
836
838 """
839 Returns path of the branch migration status file.
840 This file is placed inside the Entropy client directory to determine
841 if post-branch migration script has been run.
842 The content of this status file is usually something like this:
843 "<mtime> => <from branch> => <to branch>\n"
844
845 @param repoid: repository identifier
846 @type repoid: string
847 @return: branch migration status file path or None
848 @rtype: string or None
849 """
850 repo_data = self.SystemSettings['repositories']['available']
851 mydata = repo_data.get(repoid, {})
852 return mydata.get('post_branch_hop_status_file')
853
855 """
856 Returns path of the branch upgrade status file.
857 This file is placed inside the Entropy client directory to determine
858 whether running post-upgrade ("equo upgrade") repository branch update
859 scripts.
860 This file contains no data.
861
862 @param repoid: repository identifier
863 @type repoid: string
864 @return: branch upgrade status file path or None
865 @rtype: string or None
866 """
867 repo_data = self.SystemSettings['repositories']['available']
868 mydata = repo_data.get(repoid, {})
869 return mydata.get('post_branch_upgrade_status_file')
870
871
873
877
879
880 os.chmod(filepath,0664)
881 if etpConst['entropygid'] != None:
882 os.chown(filepath,-1,etpConst['entropygid'])
883
886
888 if os.path.isfile(etpConst['locks']['using_resources']):
889 os.remove(etpConst['locks']['using_resources'])
890
894
896 if not os.path.isfile(pidfile):
897 return False
898 f = open(pidfile)
899 s_pid = f.readline().strip()
900 f.close()
901 try:
902 s_pid = int(s_pid)
903 except ValueError:
904 return False
905
906 mypid = os.getpid()
907 if (s_pid != mypid) and os.path.isdir("%s/proc/%s" % (etpConst['systemroot'],s_pid,)):
908
909 return True
910 return False
911
913 lockdir = os.path.dirname(pidfile)
914 if not os.path.isdir(lockdir):
915 os.makedirs(lockdir,0775)
916 const_setup_perms(lockdir,etpConst['entropygid'])
917 if mypid == None:
918 mypid = os.getpid()
919 f = open(pidfile,"w")
920 f.write(str(mypid))
921 f.flush()
922 f.close()
923
925
926 etpConst['applicationlock'] = False
927 const_setup_entropy_pid(just_read = True)
928 locked = self.entropyTools.application_lock_check(option = None, gentle = True)
929 if locked:
930 if not silent:
931 self.updateProgress(
932 red(_("Another Entropy instance is currently active, cannot satisfy your request.")),
933 importance = 1,
934 type = "error",
935 header = darkred(" @@ ")
936 )
937 return True
938 return False
939
941
942 lock_count = 0
943 max_lock_count = 600
944 sleep_seconds = 0.5
945
946
947 while 1:
948 locked = check_function()
949 if not locked:
950 if lock_count > 0:
951 self.updateProgress(
952 blue(_("Resources unlocked, let's go!")),
953 importance = 1,
954 type = "info",
955 header = darkred(" @@ ")
956 )
957
958
959 time.sleep(5)
960 break
961 if lock_count >= max_lock_count:
962 mycalc = max_lock_count*sleep_seconds/60
963 self.updateProgress(
964 blue(_("Resources still locked after %s minutes, giving up!")) % (mycalc,),
965 importance = 1,
966 type = "warning",
967 header = darkred(" @@ ")
968 )
969 return True
970 lock_count += 1
971 self.updateProgress(
972 blue(_("Resources locked, sleeping %s seconds, check #%s/%s")) % (
973 sleep_seconds,
974 lock_count,
975 max_lock_count,
976 ),
977 importance = 1,
978 type = "warning",
979 header = darkred(" @@ "),
980 back = True
981 )
982 time.sleep(sleep_seconds)
983 return False
984
986 if etpConst.has_key(constant_name):
987 myinst = etpConst[constant_name]
988 if type(etpConst[constant_name]) in (list,tuple):
989 myinst = etpConst[constant_name][:]
990 elif type(etpConst[constant_name]) in (dict,set):
991 myinst = etpConst[constant_name].copy()
992 else:
993 myinst = etpConst[constant_name]
994 etpConst['backed_up'].update({constant_name: myinst})
995 else:
996 t = _("Nothing to backup in etpConst with %s key") % (constant_name,)
997 raise InvalidData("InvalidData: %s" % (t,))
998
1001
1003 if repositories == None:
1004 repositories = self.validRepositories
1005 for repoid in repositories:
1006 dbconn = self.open_repository(repoid)
1007
1030
1032 viewer = None
1033 if os.access("/usr/bin/less",os.X_OK):
1034 viewer = "/usr/bin/less"
1035 elif os.access("/bin/more",os.X_OK):
1036 viewer = "/bin/more"
1037 if not viewer:
1038 viewer = self.get_file_editor()
1039 return viewer
1040
1042 editor = None
1043 if os.getenv("EDITOR"):
1044 editor = "$EDITOR"
1045 elif os.access("/bin/nano",os.X_OK):
1046 editor = "/bin/nano"
1047 elif os.access("/bin/vi",os.X_OK):
1048 editor = "/bin/vi"
1049 elif os.access("/usr/bin/vi",os.X_OK):
1050 editor = "/usr/bin/vi"
1051 elif os.access("/usr/bin/emacs",os.X_OK):
1052 editor = "/usr/bin/emacs"
1053 elif os.access("/bin/emacs",os.X_OK):
1054 editor = "/bin/emacs"
1055 return editor
1056
1058
1059 def _ensure_package_sets_dir():
1060 sets_dir = etpConst['confsetsdir']
1061 if not os.path.isdir(sets_dir):
1062 if os.path.lexists(sets_dir):
1063 os.remove(sets_dir)
1064 os.makedirs(sets_dir,0775)
1065 const_setup_perms(sets_dir, etpConst['entropygid'])
1066
1067 try:
1068 set_name = str(set_name)
1069 except (UnicodeEncodeError,UnicodeDecodeError,):
1070 raise InvalidPackageSet("InvalidPackageSet: %s %s" % (set_name,_("must be an ASCII string"),))
1071
1072 if set_name.startswith(etpConst['packagesetprefix']):
1073 raise InvalidPackageSet("InvalidPackageSet: %s %s '%s'" % (set_name,_("cannot start with"),etpConst['packagesetprefix'],))
1074 set_match, rc = self.package_set_match(set_name)
1075 if rc: return -1,_("Name already taken")
1076
1077 _ensure_package_sets_dir()
1078 set_file = os.path.join(etpConst['confsetsdir'],set_name)
1079 if os.path.isfile(set_file) and os.access(set_file,os.W_OK):
1080 try:
1081 os.remove(set_file)
1082 except OSError:
1083 return -2,_("Cannot remove the old element")
1084 if not os.access(os.path.dirname(set_file),os.W_OK):
1085 return -3,_("Cannot create the element")
1086
1087 f = open(set_file,"w")
1088 for x in set_atoms: f.write("%s\n" % (x,))
1089 f.flush()
1090 f.close()
1091 self.SystemSettings['system_package_sets'][set_name] = set(set_atoms)
1092 return 0,_("All fine")
1093
1095
1096 try:
1097 set_name = str(set_name)
1098 except (UnicodeEncodeError,UnicodeDecodeError,):
1099 raise InvalidPackageSet("InvalidPackageSet: %s %s" % (set_name,_("must be an ASCII string"),))
1100
1101 if set_name.startswith(etpConst['packagesetprefix']):
1102 raise InvalidPackageSet("InvalidPackageSet: %s %s '%s'" % (set_name,_("cannot start with"),etpConst['packagesetprefix'],))
1103
1104 set_match, rc = self.package_set_match(set_name)
1105 if not rc: return -1,_("Already removed")
1106 set_id, set_x, set_y = set_match
1107
1108 if set_id != etpConst['userpackagesetsid']:
1109 return -2,_("Not defined by user")
1110 set_file = os.path.join(etpConst['confsetsdir'],set_name)
1111 if os.path.isfile(set_file) and os.access(set_file,os.W_OK):
1112 os.remove(set_file)
1113 if set_name in self.SystemSettings['system_package_sets']:
1114 del self.SystemSettings['system_package_sets'][set_name]
1115 return 0,_("All fine")
1116 return -3,_("Set not found or unable to remove")
1117
1119 client_plugin_id = etpConst['system_settings_plugins_ids']['client_plugin']
1120 mask_installed = self.SystemSettings[client_plugin_id]['system_mask']['repos_installed']
1121 if idpackage in mask_installed:
1122 return True
1123 return False
1124
1126 return db_download_uri.split("/")[2]
1127
1132
1136
1138 if not install_queue:
1139 return {}
1140 licenses = {}
1141 cl_id = self.sys_settings_client_plugin_id
1142 repo_sys_data = self.SystemSettings[cl_id]['repositories']
1143
1144 for match in install_queue:
1145 repoid = match[1]
1146 dbconn = self.open_repository(repoid)
1147 wl = repo_sys_data['license_whitelist'].get(repoid)
1148 if not wl:
1149 continue
1150 keys = dbconn.retrieveLicensedataKeys(match[0])
1151 for key in keys:
1152 if key not in wl:
1153 found = self.clientDbconn.isLicenseAccepted(key)
1154 if found:
1155 continue
1156 if not licenses.has_key(key):
1157 licenses[key] = set()
1158 licenses[key].add(match)
1159 return licenses
1160
1161 - def get_text_license(self, license_name, repoid):
1162 dbconn = self.open_repository(repoid)
1163 text = dbconn.retrieveLicenseText(license_name)
1164 tempfile = self.entropyTools.get_random_temp_file()
1165 f = open(tempfile,"w")
1166 f.write(text)
1167 f.flush()
1168 f.close()
1169 return tempfile
1170
1171 - def libraries_test(self, dbconn = None, broken_symbols = False, task_bombing_func = None):
1172
1173 if dbconn == None:
1174 dbconn = self.clientDbconn
1175
1176 self.updateProgress(
1177 blue(_("Libraries test")),
1178 importance = 2,
1179 type = "info",
1180 header = red(" @@ ")
1181 )
1182
1183 if not etpConst['systemroot']:
1184 myroot = "/"
1185 else:
1186 myroot = etpConst['systemroot']+"/"
1187
1188 subprocess.call("ldconfig -r %s &> /dev/null" % (myroot,), shell = True)
1189
1190 if not os.path.isfile(etpConst['systemroot']+"/etc/ld.so.conf"):
1191 self.updateProgress(
1192 blue(_("Cannot find "))+red(etpConst['systemroot']+"/etc/ld.so.conf"),
1193 importance = 1,
1194 type = "error",
1195 header = red(" @@ ")
1196 )
1197 return {},set(),-1
1198
1199 ldpaths = set(self.entropyTools.collect_linker_paths())
1200 ldpaths |= self.entropyTools.collect_paths()
1201
1202 if "/usr/lib64" in ldpaths and "/usr/lib" in ldpaths:
1203 if os.path.realpath("/usr/lib64") == "/usr/lib":
1204 ldpaths.discard("/usr/lib")
1205
1206 ldpaths.add("/usr/share")
1207
1208 ldpaths.add("/usr/libexec")
1209
1210 executables = set()
1211 total = len(ldpaths)
1212 count = 0
1213 sys_root_len = len(etpConst['systemroot'])
1214 for ldpath in ldpaths:
1215 if callable(task_bombing_func): task_bombing_func()
1216 count += 1
1217 self.updateProgress(
1218 blue("Tree: ")+red(etpConst['systemroot']+ldpath),
1219 importance = 0,
1220 type = "info",
1221 count = (count,total),
1222 back = True,
1223 percent = True,
1224 header = " "
1225 )
1226 ldpath = ldpath.encode(sys.getfilesystemencoding())
1227 mywalk_iter = os.walk(etpConst['systemroot']+ldpath)
1228
1229 def mywimf(dt):
1230
1231 currentdir, subdirs, files = dt
1232
1233 def mymf(item):
1234 filepath = os.path.join(currentdir,item)
1235 if filepath in etpConst['libtest_files_blacklist']:
1236 return 0
1237 if not os.access(filepath,os.R_OK):
1238 return 0
1239 if not os.path.isfile(filepath):
1240 return 0
1241 if not self.entropyTools.is_elf_file(filepath):
1242 return 0
1243 return filepath[sys_root_len:]
1244
1245 return set([x for x in map(mymf,files) if type(x) != int])
1246
1247 for x in map(mywimf,mywalk_iter): executables |= x
1248
1249 self.updateProgress(
1250 blue(_("Collecting broken executables")),
1251 importance = 2,
1252 type = "info",
1253 header = red(" @@ ")
1254 )
1255 t = red(_("Attention")) + ": " + \
1256 blue(_("don't worry about libraries that are shown here but not later."))
1257 self.updateProgress(
1258 t,
1259 importance = 1,
1260 type = "info",
1261 header = red(" @@ ")
1262 )
1263
1264 myQA = self.QA()
1265
1266 plain_brokenexecs = set()
1267 total = len(executables)
1268 count = 0
1269 scan_txt = blue("%s ..." % (_("Scanning libraries"),))
1270 for executable in executables:
1271 if callable(task_bombing_func): task_bombing_func()
1272 count += 1
1273 if (count%10 == 0) or (count == total) or (count == 1):
1274 self.updateProgress(
1275 scan_txt,
1276 importance = 0,
1277 type = "info",
1278 count = (count,total),
1279 back = True,
1280 percent = True,
1281 header = " "
1282 )
1283 myelfs = self.entropyTools.read_elf_dynamic_libraries(etpConst['systemroot']+executable)
1284 def mymf2(mylib):
1285 return not myQA.resolve_dynamic_library(mylib, executable)
1286 mylibs = set(filter(mymf2,myelfs))
1287 broken_sym_found = set()
1288 if broken_symbols and not mylibs: broken_sym_found |= self.entropyTools.read_elf_broken_symbols(etpConst['systemroot']+executable)
1289 if not (mylibs or broken_sym_found):
1290 continue
1291
1292 if mylibs:
1293 alllibs = blue(' :: ').join(list(mylibs))
1294 self.updateProgress(
1295 red(etpConst['systemroot']+executable)+" [ "+alllibs+" ]",
1296 importance = 1,
1297 type = "info",
1298 percent = True,
1299 count = (count,total),
1300 header = " "
1301 )
1302 elif broken_sym_found:
1303 allsyms = darkred(' :: ').join([brown(x) for x in list(broken_sym_found)])
1304 if len(allsyms) > 50: allsyms = brown(_('various broken symbols'))
1305 self.updateProgress(
1306 red(etpConst['systemroot']+executable)+" { "+allsyms+" }",
1307 importance = 1,
1308 type = "info",
1309 percent = True,
1310 count = (count,total),
1311 header = " "
1312 )
1313 plain_brokenexecs.add(executable)
1314
1315 del executables
1316 packagesMatched = {}
1317
1318 if not etpSys['serverside']:
1319
1320 self.updateProgress(
1321 blue(_("Matching broken libraries/executables")),
1322 importance = 1,
1323 type = "info",
1324 header = red(" @@ ")
1325 )
1326 matched = set()
1327 for brokenlib in plain_brokenexecs:
1328 idpackages = self.clientDbconn.searchBelongs(brokenlib)
1329 for idpackage in idpackages:
1330 key, slot = self.clientDbconn.retrieveKeySlot(idpackage)
1331 mymatch = self.atom_match(key, matchSlot = slot)
1332 if mymatch[0] == -1:
1333 matched.add(brokenlib)
1334 continue
1335 cmpstat = self.get_package_action(mymatch)
1336 if cmpstat == 0:
1337 continue
1338 if not packagesMatched.has_key(brokenlib):
1339 packagesMatched[brokenlib] = set()
1340 packagesMatched[brokenlib].add(mymatch)
1341 matched.add(brokenlib)
1342 plain_brokenexecs -= matched
1343
1344 return packagesMatched,plain_brokenexecs,0
1345
1347 """
1348 Set new Entropy branch. This is NOT thread-safe.
1349 Please note that if you call this method all your
1350 repository instance references will become invalid.
1351 This is caused by close_all_repositories and SystemSettings
1352 clear methods.
1353 Once you changed branch, the repository databases won't be
1354 available until you fetch them (through Repositories class)
1355
1356 @param branch -- new branch
1357 @type branch basestring
1358 @return None
1359 """
1360 self.Cacher.discard()
1361 self.Cacher.stop()
1362 self.purge_cache(showProgress = False)
1363 self.close_all_repositories()
1364
1365
1366 etpConst['branch'] = branch
1367 self.entropyTools.write_new_branch(branch)
1368 self.SystemSettings.clear()
1369
1370
1371 self.reopen_client_repository()
1372 self.clientDbconn.resetTreeupdatesDigests()
1373 self.close_all_repositories()
1374 if self.xcache:
1375 self.Cacher.start()
1376
1377 - def get_meant_packages(self, search_term, from_installed = False,
1378 valid_repos = []):
1379
1380 pkg_data = []
1381 atom_srch = False
1382 if "/" in search_term:
1383 atom_srch = True
1384
1385 if not valid_repos:
1386 valid_repos = self.validRepositories
1387 if from_installed:
1388 valid_repos = []
1389 if hasattr(self,'clientDbconn'):
1390 valid_repos.append(self.clientDbconn)
1391
1392 for repo in valid_repos:
1393 if isinstance(repo, basestring):
1394 dbconn = self.open_repository(repo)
1395 elif isinstance(repo, EntropyRepository):
1396 dbconn = repo
1397 else:
1398 continue
1399 pkg_data.extend([(x,repo,) for x in \
1400 dbconn.searchSimilarPackages(search_term, atom = atom_srch)])
1401
1402 return pkg_data
1403
1405 categories = set()
1406 for repo in self.validRepositories:
1407 dbconn = self.open_repository(repo)
1408 catsdata = dbconn.listAllCategories()
1409 categories.update(set([x[1] for x in catsdata]))
1410 return categories
1411
1413 pkg_matches = []
1414 for repo in self.validRepositories:
1415 dbconn = self.open_repository(repo)
1416 branch = self.SystemSettings['repositories']['branch']
1417 catsdata = dbconn.searchPackagesByCategory(category, branch = branch)
1418 pkg_matches.extend([(x[1],repo,) for x in catsdata if (x[1],repo,) not in pkg_matches])
1419 return pkg_matches
1420
1422
1423 data = {}
1424 for repo in self.validRepositories:
1425 try:
1426 dbconn = self.open_repository(repo)
1427 except RepositoryError:
1428 continue
1429 try:
1430 data = dbconn.retrieveCategoryDescription(category)
1431 except (self.dbapi2.OperationalError, self.dbapi2.IntegrityError,):
1432 continue
1433 if data: break
1434
1435 return data
1436
1440
1442
1443 idpackage, repoid = match
1444 dbconn = self.open_repository(repoid)
1445 cl_id = self.sys_settings_client_plugin_id
1446 misc_data = self.SystemSettings[cl_id]['misc']
1447 if mask:
1448 config_protect = set(dbconn.retrieveProtectMask(idpackage).split())
1449 config_protect |= set(misc_data['configprotectmask'])
1450 else:
1451 config_protect = set(dbconn.retrieveProtect(idpackage).split())
1452 config_protect |= set(misc_data['configprotect'])
1453 config_protect = [etpConst['systemroot']+x for x in config_protect]
1454
1455 return sorted(config_protect)
1456
1458
1459 if self.clientDbconn == None:
1460 return []
1461 cl_id = self.sys_settings_client_plugin_id
1462 misc_data = self.SystemSettings[cl_id]['misc']
1463 if mask:
1464 _pmask = self.clientDbconn.retrieveProtectMask(idpackage).split()
1465 config_protect = set(_pmask)
1466 config_protect |= set(misc_data['configprotectmask'])
1467 else:
1468 _protect = self.clientDbconn.retrieveProtect(idpackage).split()
1469 config_protect = set(_protect)
1470 config_protect |= set(misc_data['configprotect'])
1471 config_protect = [etpConst['systemroot']+x for x in config_protect]
1472
1473 return sorted(config_protect)
1474
1476
1477 if self.clientDbconn == None:
1478 return []
1479
1480
1481
1482 cl_id = self.sys_settings_client_plugin_id
1483 misc_data = self.SystemSettings[cl_id]['misc']
1484 if mask:
1485 _pmask = self.clientDbconn.listConfigProtectDirectories(mask = True)
1486 config_protect = set(_pmask)
1487 config_protect |= set(misc_data['configprotectmask'])
1488 else:
1489 _protect = self.clientDbconn.listConfigProtectDirectories()
1490 config_protect = set(_protect)
1491 config_protect |= set(misc_data['configprotect'])
1492 config_protect = [etpConst['systemroot']+x for x in config_protect]
1493
1494 return sorted(config_protect)
1495
1507
1513
1514 - def quickpkg(self, atomstring, savedir = None):
1515 if savedir == None:
1516 savedir = etpConst['packagestmpdir']
1517 if not os.path.isdir(etpConst['packagestmpdir']):
1518 os.makedirs(etpConst['packagestmpdir'])
1519
1520 match = self.clientDbconn.atomMatch(atomstring)
1521 if match[0] == -1:
1522 return -1,None,None
1523 atom = self.clientDbconn.atomMatch(match[0])
1524 pkgdata = self.clientDbconn.getPackageData(match[0])
1525 resultfile = self.quickpkg_handler(pkgdata = pkgdata, dirpath = savedir)
1526 if resultfile == None:
1527 return -1,atom,None
1528 else:
1529 return 0,atom,resultfile
1530
1531 - def quickpkg_handler(self, pkgdata, dirpath, edb = True,
1532 portdbPath = None, fake = False, compression = "bz2", shiftpath = ""):
1533
1534 import stat
1535 import tarfile
1536
1537 if compression not in ("bz2","","gz"):
1538 compression = "bz2"
1539
1540
1541 pkgtag = ''
1542 pkgrev = "~"+str(pkgdata['revision'])
1543 if pkgdata['versiontag']: pkgtag = "#"+pkgdata['versiontag']
1544 pkgname = pkgdata['name']+"-"+pkgdata['version']+pkgrev+pkgtag
1545 pkgcat = pkgdata['category']
1546
1547 dirpath += "/"+pkgname+etpConst['packagesext']
1548 if os.path.isfile(dirpath):
1549 os.remove(dirpath)
1550 tar = tarfile.open(dirpath,"w:"+compression)
1551
1552 if not fake:
1553
1554 contents = sorted([x for x in pkgdata['content']])
1555
1556
1557 for path in contents:
1558
1559 encoded_path = path
1560 path = path.encode('raw_unicode_escape')
1561 path = shiftpath+path
1562 try:
1563 exist = os.lstat(path)
1564 except OSError:
1565 continue
1566 arcname = path[len(shiftpath):]
1567 if arcname.startswith("/"):
1568 arcname = arcname[1:]
1569 ftype = pkgdata['content'][encoded_path]
1570 if str(ftype) == '0': ftype = 'dir'
1571 if 'dir' == ftype and \
1572 not stat.S_ISDIR(exist.st_mode) and \
1573 os.path.isdir(path):
1574 path = os.path.realpath(path)
1575
1576 tarinfo = tar.gettarinfo(path, arcname)
1577
1578 if stat.S_ISREG(exist.st_mode):
1579 tarinfo.mode = stat.S_IMODE(exist.st_mode)
1580 tarinfo.type = tarfile.REGTYPE
1581 f = open(path)
1582 try:
1583 tar.addfile(tarinfo, f)
1584 finally:
1585 f.close()
1586 else:
1587 tar.addfile(tarinfo)
1588
1589 tar.close()
1590
1591
1592 import entropy.xpak as xpak
1593 Spm = self.Spm()
1594
1595 gentoo_name = self.entropyTools.remove_tag(pkgname)
1596 gentoo_name = self.entropyTools.remove_entropy_revision(gentoo_name)
1597 if portdbPath == None:
1598 dbdir = Spm.get_vdb_path()+"/"+pkgcat+"/"+gentoo_name+"/"
1599 else:
1600 dbdir = portdbPath+"/"+pkgcat+"/"+gentoo_name+"/"
1601 if os.path.isdir(dbdir):
1602 tbz2 = xpak.tbz2(dirpath)
1603 tbz2.recompose(dbdir)
1604
1605 if edb:
1606 self.inject_entropy_database_into_package(dirpath, pkgdata)
1607
1608 if os.path.isfile(dirpath):
1609 return dirpath
1610 return None
1611
1612
1614
1616 """
1617 @input: matched atom (idpackage,repoid)
1618 @output:
1619 upgrade: int(2)
1620 install: int(1)
1621 reinstall: int(0)
1622 downgrade: int(-1)
1623 """
1624 dbconn = self.open_repository(match[1])
1625 pkgkey, pkgslot = dbconn.retrieveKeySlot(match[0])
1626 results = self.clientDbconn.searchKeySlot(pkgkey, pkgslot)
1627 if not results: return 1
1628
1629 installed_idpackage = results[0][0]
1630 pkgver, pkgtag, pkgrev = dbconn.getVersioningData(match[0])
1631 installedVer, installedTag, installedRev = self.clientDbconn.getVersioningData(installed_idpackage)
1632 pkgcmp = self.entropyTools.entropy_compare_versions((pkgver,pkgtag,pkgrev),(installedVer,installedTag,installedRev))
1633 if pkgcmp == 0:
1634 return 0
1635 elif pkgcmp > 0:
1636 return 2
1637 return -1
1638
1640 idpackage, repoid = match
1641 dbconn = self.open_repository(repoid)
1642 idpackage, idreason = dbconn.idpackageValidator(idpackage)
1643 masked = False
1644 if idpackage == -1: masked = True
1645 return masked, idreason, self.SystemSettings['pkg_masking_reasons'].get(idreason)
1646
1648 m_id, m_repo = match
1649 dbconn = self.open_repository(m_repo)
1650 conflicts = dbconn.retrieveConflicts(m_id)
1651 found_conflicts = set()
1652 for conflict in conflicts:
1653 my_m_id, my_m_rc = self.clientDbconn.atomMatch(conflict)
1654 if my_m_id != -1:
1655
1656 match_data = dbconn.retrieveKeySlot(m_id)
1657 installed_match_data = self.clientDbconn.retrieveKeySlot(my_m_id)
1658 if match_data != installed_match_data:
1659 found_conflicts.add(my_m_id)
1660 return found_conflicts
1661
1663 m_id, m_repo = match
1664 dbconn = self.open_repository(m_repo)
1665 idpackage, idreason = dbconn.idpackageValidator(m_id, live = live_check)
1666 if idpackage != -1:
1667 return False
1668 return True
1669
1671
1672 m_id, m_repo = match
1673 if m_repo not in self.validRepositories: return False
1674 dbconn = self.open_repository(m_repo)
1675 idpackage, idreason = dbconn.idpackageValidator(m_id, live = live_check)
1676 if idpackage != -1: return False
1677 myr = self.SystemSettings['pkg_masking_reference']
1678 user_masks = [myr['user_package_mask'],myr['user_license_mask'],myr['user_live_mask']]
1679 if idreason in user_masks:
1680 return True
1681 return False
1682
1684
1685 m_id, m_repo = match
1686 if m_repo not in self.validRepositories: return False
1687 dbconn = self.open_repository(m_repo)
1688 idpackage, idreason = dbconn.idpackageValidator(m_id, live = live_check)
1689 if idpackage == -1: return False
1690 myr = self.SystemSettings['pkg_masking_reference']
1691 user_masks = [
1692 myr['user_package_unmask'],myr['user_live_unmask'],myr['user_package_keywords'],
1693 myr['user_repo_package_keywords_all'], myr['user_repo_package_keywords']
1694 ]
1695 if idreason in user_masks:
1696 return True
1697 return False
1698
1699 - def mask_match(self, match, method = 'atom', dry_run = False, clean_all_cache = False):
1710
1711 - def unmask_match(self, match, method = 'atom', dry_run = False, clean_all_cache = False):
1722
1723 - def _mask_unmask_match(self, match, method, methods_reference, dry_run = False, clean_all_cache = False):
1750
1756
1762
1768
1774
1779
1784
1786 exist = False
1787 if not os.path.isfile(m_file):
1788 if not os.access(os.path.dirname(m_file),os.W_OK):
1789 return False
1790 elif not os.access(m_file, os.W_OK):
1791 return False
1792 elif not dry_run:
1793 exist = True
1794
1795 if dry_run:
1796 return True
1797
1798 content = []
1799 if exist:
1800 f = open(m_file,"r")
1801 content = [x.strip() for x in f.readlines()]
1802 f.close()
1803 content.append(keyword)
1804 m_file_tmp = m_file+".tmp"
1805 f = open(m_file_tmp,"w")
1806 for line in content:
1807 f.write(line+"\n")
1808 f.flush()
1809 f.close()
1810 shutil.move(m_file_tmp,m_file)
1811 return True
1812
1814 setting_data = self.SystemSettings.get_setting_files_data()
1815 masking_list = [setting_data['mask'],setting_data['unmask']]
1816 return self._clear_match_generic(match, masking_list = masking_list, dry_run = dry_run)
1817
1819
1820 self.SystemSettings['live_packagemasking']['unmask_matches'].discard(match)
1821 self.SystemSettings['live_packagemasking']['mask_matches'].discard(match)
1822
1823 if dry_run: return
1824
1825 for mask_file in masking_list:
1826 if not (os.path.isfile(mask_file) and os.access(mask_file,os.W_OK)): continue
1827 f = open(mask_file,"r")
1828 newf = self.entropyTools.open_buffer()
1829 line = f.readline()
1830 while line:
1831 line = line.strip()
1832 if line.startswith("#"):
1833 newf.write(line+"\n")
1834 line = f.readline()
1835 continue
1836 elif not line:
1837 newf.write("\n")
1838 line = f.readline()
1839 continue
1840 mymatch = self.atom_match(line, packagesFilter = False)
1841 if mymatch == match:
1842 line = f.readline()
1843 continue
1844 newf.write(line+"\n")
1845 line = f.readline()
1846 f.close()
1847 tmpfile = mask_file+".w_tmp"
1848 f = open(tmpfile,"w")
1849 f.write(newf.getvalue())
1850 f.flush()
1851 f.close()
1852 newf.close()
1853 shutil.move(tmpfile,mask_file)
1854