1
2 """
3
4 @author: Fabio Erculiani <lxnay@sabayonlinux.org>
5 @contact: lxnay@sabayonlinux.org
6 @copyright: Fabio Erculiani
7 @license: GPL-2
8
9 B{Entropy Package Manager Client Miscellaneous functions Interface}.
10
11 """
12 from __future__ import with_statement
13 import os
14 import stat
15 import fcntl
16 import errno
17 import sys
18 import shutil
19 import time
20 import subprocess
21 import tempfile
22 from entropy.i18n import _
23 from entropy.const import *
24 from entropy.exceptions import *
25 from entropy.db import dbapi2, EntropyRepository, EntropyRepository
26 from entropy.output import purple, bold, red, blue, darkgreen, darkred, brown
27
28
30
31 __repo_error_messages_cache = set()
32 __repodb_cache = {}
33 _memory_db_instances = {}
34
36 self.MirrorStatus.clear()
37 self.__repo_error_messages_cache.clear()
38
39
40 cl_id = self.sys_settings_client_plugin_id
41 client_metadata = self.SystemSettings.get(cl_id, {})
42 if "masking_validation" in client_metadata:
43 client_metadata['masking_validation']['cache'].clear()
44
45
46 del self.validRepositories[:]
47 for repoid in self.SystemSettings['repositories']['order']:
48
49 try:
50
51 dbc = self.open_repository(repoid)
52 dbc.listConfigProtectEntries()
53 dbc.validateDatabase()
54 self.validRepositories.append(repoid)
55
56 except RepositoryError:
57
58 if quiet:
59 continue
60
61 t = _("Repository") + " " + repoid + " " + \
62 _("is not available") + ". " + _("Cannot validate")
63 t2 = _("Please update your repositories now in order to remove this message!")
64 self.updateProgress(
65 darkred(t),
66 importance = 1,
67 type = "warning"
68 )
69 self.updateProgress(
70 purple(t2),
71 header = bold("!!! "),
72 importance = 1,
73 type = "warning"
74 )
75 continue
76 except (self.dbapi2.OperationalError,
77 self.dbapi2.DatabaseError,SystemDatabaseError,):
78
79 if quiet:
80 continue
81
82 t = _("Repository") + " " + repoid + " " + \
83 _("is corrupted") + ". " + _("Cannot validate")
84 self.updateProgress(
85 darkred(t),
86 importance = 1,
87 type = "warning"
88 )
89 continue
90
91
92 self.close_all_repositories(mask_clear = False)
93
95 return (repoid, etpConst['systemroot'],)
96
98 dbc = self.open_memory_database(dbname = repoid)
99 repo_key = self.__get_repository_cache_key(repoid)
100 self._memory_db_instances[repo_key] = dbc
101
102
103 repodata = {
104 'repoid': repoid,
105 'in_memory': True,
106 'description': description,
107 'packages': package_mirrors,
108 'dbpath': ':memory:',
109 }
110 self.add_repository(repodata)
111 return dbc
112
131
132
137
151
153
154 if isinstance(repoid,basestring):
155 if repoid.endswith(etpConst['packagesext']):
156 xcache = False
157
158 repo_data = self.SystemSettings['repositories']['available']
159 if repoid not in repo_data:
160 t = _("bad repository id specified")
161 if repoid not in self.__repo_error_messages_cache:
162 self.updateProgress(
163 darkred(t),
164 importance = 2,
165 type = "warning"
166 )
167 self.__repo_error_messages_cache.add(repoid)
168 raise RepositoryError("RepositoryError: %s" % (t,))
169
170 if repo_data[repoid].get('in_memory'):
171 repo_key = self.__get_repository_cache_key(repoid)
172 conn = self._memory_db_instances.get(repo_key)
173 else:
174 dbfile = repo_data[repoid]['dbpath']+"/"+etpConst['etpdatabasefile']
175 if not os.path.isfile(dbfile):
176 t = _("Repository %s hasn't been downloaded yet.") % (repoid,)
177 if repoid not in self.__repo_error_messages_cache:
178 self.updateProgress(
179 darkred(t),
180 importance = 2,
181 type = "warning"
182 )
183 self.__repo_error_messages_cache.add(repoid)
184 raise RepositoryError("RepositoryError: %s" % (t,))
185
186 conn = EntropyRepository(
187 readOnly = True,
188 dbFile = dbfile,
189 clientDatabase = True,
190 dbname = etpConst['dbnamerepoprefix']+repoid,
191 xcache = xcache,
192 indexing = indexing,
193 OutputInterface = self
194 )
195
196 if (repoid not in etpConst['client_treeupdatescalled']) and \
197 (self.entropyTools.is_root()) and \
198 (not repoid.endswith(etpConst['packagesext'])):
199
200 try:
201 updated = self.repository_packages_spm_sync(repoid, conn)
202 except (self.dbapi2.OperationalError, self.dbapi2.DatabaseError):
203 updated = False
204 if updated:
205 self.clear_dump_cache(etpCache['world_update'])
206 self.clear_dump_cache(etpCache['critical_update'])
207 self.clear_dump_cache(etpCache['world'])
208 self.clear_dump_cache(etpCache['install'])
209 self.clear_dump_cache(etpCache['remove'])
210 return conn
211
213 fname = self.SystemSettings['repositories']['available'][reponame]['dbpath']+"/"+etpConst['etpdatabaserevisionfile']
214 revision = -1
215 if os.path.isfile(fname) and os.access(fname,os.R_OK):
216 with open(fname,"r") as f:
217 try:
218 revision = int(f.readline().strip())
219 except (OSError, IOError, ValueError,):
220 pass
221 return revision
222
228
230 fname = self.SystemSettings['repositories']['available'][reponame]['dbpath']+"/"+etpConst['etpdatabasehashfile']
231 mhash = "-1"
232 if os.path.isfile(fname) and os.access(fname,os.R_OK):
233 with open(fname,"r") as f:
234 try:
235 mhash = f.readline().strip().split()[0]
236 except (OSError, IOError, IndexError,):
237 pass
238 return mhash
239
241 product = self.SystemSettings['repositories']['product']
242 branch = self.SystemSettings['repositories']['branch']
243
244 try:
245 self.SystemSettings['repositories']['available'][repodata['repoid']] = {}
246 self.SystemSettings['repositories']['available'][repodata['repoid']]['description'] = repodata['description']
247 except KeyError:
248 t = _("repodata dictionary is corrupted")
249 raise InvalidData("InvalidData: %s" % (t,))
250
251 if repodata['repoid'].endswith(etpConst['packagesext']) or repodata.get('in_memory'):
252 try:
253
254 self.SystemSettings['repositories']['available'][repodata['repoid']]['packages'] = repodata['packages'][:]
255 smart_package = repodata.get('smartpackage')
256 if smart_package != None:
257 self.SystemSettings['repositories']['available'][repodata['repoid']]['smartpackage'] = smart_package
258 except KeyError:
259 raise InvalidData("InvalidData: repodata dictionary is corrupted")
260 self.SystemSettings['repositories']['available'][repodata['repoid']]['dbpath'] = repodata.get('dbpath')
261 self.SystemSettings['repositories']['available'][repodata['repoid']]['pkgpath'] = repodata.get('pkgpath')
262 self.SystemSettings['repositories']['available'][repodata['repoid']]['in_memory'] = repodata.get('in_memory')
263
264 self.SystemSettings['repositories']['order'].insert(0, repodata['repoid'])
265 else:
266
267 self.SystemSettings['repositories']['available'][repodata['repoid']]['plain_packages'] = repodata['plain_packages'][:]
268 self.SystemSettings['repositories']['available'][repodata['repoid']]['packages'] = [x+"/"+product for x in repodata['plain_packages']]
269 self.SystemSettings['repositories']['available'][repodata['repoid']]['plain_database'] = repodata['plain_database']
270 self.SystemSettings['repositories']['available'][repodata['repoid']]['database'] = repodata['plain_database'] + \
271 "/" + product + "/database/" + etpConst['currentarch'] + "/" + branch
272 if not repodata['dbcformat'] in etpConst['etpdatabasesupportedcformats']:
273 repodata['dbcformat'] = etpConst['etpdatabasesupportedcformats'][0]
274 self.SystemSettings['repositories']['available'][repodata['repoid']]['dbcformat'] = repodata['dbcformat']
275 self.SystemSettings['repositories']['available'][repodata['repoid']]['dbpath'] = etpConst['etpdatabaseclientdir'] + \
276 "/" + repodata['repoid'] + "/" + product + "/" + etpConst['currentarch'] + "/" + branch
277
278 myrev = self.get_repository_revision(repodata['repoid'])
279 if myrev == -1:
280 myrev = 0
281 self.SystemSettings['repositories']['available'][repodata['repoid']]['dbrevision'] = str(myrev)
282 if repodata.has_key("position"):
283 self.SystemSettings['repositories']['order'].insert(
284 repodata['position'], repodata['repoid'])
285 else:
286 self.SystemSettings['repositories']['order'].append(
287 repodata['repoid'])
288 if not repodata.has_key("service_port"):
289 repodata['service_port'] = int(etpConst['socket_service']['port'])
290 if not repodata.has_key("ssl_service_port"):
291 repodata['ssl_service_port'] = int(etpConst['socket_service']['ssl_port'])
292 self.SystemSettings['repositories']['available'][repodata['repoid']]['service_port'] = repodata['service_port']
293 self.SystemSettings['repositories']['available'][repodata['repoid']]['ssl_service_port'] = repodata['ssl_service_port']
294 self.repository_move_clear_cache(repodata['repoid'])
295
296 self.entropyTools.save_repository_settings(repodata)
297 self.SystemSettings.clear()
298 self.close_all_repositories()
299 self.validate_repositories()
300
347
358
368
395
397 try:
398 repodata = self.SystemSettings['repositories']['available'][repoid].copy()
399 except KeyError:
400 if not self.SystemSettings['repositories']['excluded'].has_key(repoid):
401 raise
402 repodata = self.SystemSettings['repositories']['excluded'][repoid].copy()
403 return repodata
404
405
407 atoms_contained = []
408 basefile = os.path.basename(tbz2file)
409 db_dir = tempfile.mkdtemp()
410 dbfile = self.entropyTools.extract_edb(tbz2file,
411 dbpath = db_dir+"/packages.db")
412 if dbfile == None:
413 return -1, atoms_contained
414 etpSys['dirstoclean'].add(os.path.dirname(dbfile))
415
416 repodata = {}
417 repodata['repoid'] = basefile
418 repodata['description'] = "Dynamic database from " + basefile
419 repodata['packages'] = []
420 repodata['dbpath'] = os.path.dirname(dbfile)
421 repodata['pkgpath'] = os.path.realpath(tbz2file)
422 repodata['smartpackage'] = False
423
424 mydbconn = self.open_generic_database(dbfile)
425
426 try:
427 myidpackages = mydbconn.listAllIdpackages()
428 except (AttributeError, self.dbapi2.DatabaseError, \
429 self.dbapi2.IntegrityError, self.dbapi2.OperationalError,):
430 return -2, atoms_contained
431 if len(myidpackages) > 1:
432 repodata[basefile]['smartpackage'] = True
433 for myidpackage in myidpackages:
434 compiled_arch = mydbconn.retrieveDownloadURL(myidpackage)
435 if compiled_arch.find("/"+etpSys['arch']+"/") == -1:
436 return -3, atoms_contained
437 atoms_contained.append((int(myidpackage), basefile))
438
439 self.add_repository(repodata)
440 self.validate_repositories()
441 if basefile not in self.validRepositories:
442 self.remove_repository(basefile)
443 return -4, atoms_contained
444 mydbconn.closeDB()
445 del mydbconn
446 return 0, atoms_contained
447
453
455
456 def load_db_from_ram():
457 self.safe_mode = etpConst['safemodeerrors']['clientdb']
458 mytxt = "%s, %s" % (_("System database not found or corrupted"),
459 _("running in safe mode using empty database from RAM"),)
460 self.updateProgress(
461 darkred(mytxt),
462 importance = 1,
463 type = "warning",
464 header = bold("!!!"),
465 )
466 conn = self.open_memory_database(dbname = etpConst['clientdbid'])
467 return conn
468
469 db_dir = os.path.dirname(etpConst['etpdatabaseclientfilepath'])
470 if not os.path.isdir(db_dir): os.makedirs(db_dir)
471
472 db_path = etpConst['etpdatabaseclientfilepath']
473 if (not self.noclientdb) and (not os.path.isfile(db_path)):
474 conn = load_db_from_ram()
475 self.entropyTools.print_traceback(f = self.clientLog)
476 else:
477 try:
478 conn = EntropyRepository(readOnly = False, dbFile = db_path,
479 clientDatabase = True, dbname = etpConst['clientdbid'],
480 xcache = self.xcache, indexing = self.indexing,
481 OutputInterface = self
482 )
483 except (self.dbapi2.DatabaseError,):
484 self.entropyTools.print_traceback(f = self.clientLog)
485 conn = load_db_from_ram()
486 else:
487
488 if not self.noclientdb:
489 try:
490 conn.validateDatabase()
491 except SystemDatabaseError:
492 try:
493 conn.closeDB()
494 except:
495 pass
496 self.entropyTools.print_traceback(f = self.clientLog)
497 conn = load_db_from_ram()
498
499 self.clientDbconn = conn
500 return self.clientDbconn
501
503 self.updateProgress(
504 darkred(_("Sanity Check") + ": " + _("system database")),
505 importance = 2,
506 type = "warning"
507 )
508 idpkgs = self.clientDbconn.listAllIdpackages()
509 length = len(idpkgs)
510 count = 0
511 errors = False
512 scanning_txt = _("Scanning...")
513 for x in idpkgs:
514 count += 1
515 self.updateProgress(
516 darkgreen(scanning_txt),
517 importance = 0,
518 type = "info",
519 back = True,
520 count = (count,length),
521 percent = True
522 )
523 try:
524 self.clientDbconn.getPackageData(x)
525 except Exception ,e:
526 self.entropyTools.print_traceback()
527 errors = True
528 self.updateProgress(
529 darkred(_("Errors on idpackage %s, error: %s")) % (x,str(e)),
530 importance = 0,
531 type = "warning"
532 )
533
534 if not errors:
535 t = _("Sanity Check") + ": %s" % (bold(_("PASSED")),)
536 self.updateProgress(
537 darkred(t),
538 importance = 2,
539 type = "warning"
540 )
541 return 0
542 else:
543 t = _("Sanity Check") + ": %s" % (bold(_("CORRUPTED")),)
544 self.updateProgress(
545 darkred(t),
546 importance = 2,
547 type = "warning"
548 )
549 return -1
550
551 - def open_generic_database(self, dbfile, dbname = None, xcache = None,
552 readOnly = False, indexing_override = None, skipChecks = False):
553 if xcache == None:
554 xcache = self.xcache
555 if indexing_override != None:
556 indexing = indexing_override
557 else:
558 indexing = self.indexing
559 if dbname == None:
560 dbname = etpConst['genericdbid']
561 return EntropyRepository(
562 readOnly = readOnly,
563 dbFile = dbfile,
564 clientDatabase = True,
565 dbname = dbname,
566 xcache = xcache,
567 indexing = indexing,
568 OutputInterface = self,
569 skipChecks = skipChecks
570 )
571
573 if dbname == None:
574 dbname = etpConst['genericdbid']
575 dbc = EntropyRepository(
576 readOnly = False,
577 dbFile = ':memory:',
578 clientDatabase = True,
579 dbname = dbname,
580 xcache = False,
581 indexing = False,
582 OutputInterface = self,
583 skipChecks = True
584 )
585 dbc.initializeDatabase()
586 return dbc
587
588 - def backup_database(self, dbpath, backup_dir = None, silent = False, compress_level = 9):
589
590 if compress_level not in range(1,10):
591 compress_level = 9
592
593 backup_dir = os.path.dirname(dbpath)
594 if not backup_dir: backup_dir = os.path.dirname(dbpath)
595 dbname = os.path.basename(dbpath)
596 bytes_required = 1024000*300
597 if not (os.access(backup_dir,os.W_OK) and \
598 os.path.isdir(backup_dir) and os.path.isfile(dbpath) and \
599 os.access(dbpath,os.R_OK) and self.entropyTools.check_required_space(backup_dir, bytes_required)):
600 if not silent:
601 mytxt = "%s: %s, %s" % (darkred(_("Cannot backup selected database")),blue(dbpath),darkred(_("permission denied")),)
602 self.updateProgress(
603 mytxt,
604 importance = 1,
605 type = "error",
606 header = red(" @@ ")
607 )
608 return False, mytxt
609
610 def get_ts():
611 from datetime import datetime
612 ts = datetime.fromtimestamp(time.time())
613 return "%s%s%s_%sh%sm%ss" % (ts.year,ts.month,ts.day,ts.hour,ts.minute,ts.second)
614
615 comp_dbname = "%s%s.%s.bz2" % (etpConst['dbbackupprefix'],dbname,get_ts(),)
616 comp_dbpath = os.path.join(backup_dir,comp_dbname)
617 if not silent:
618 mytxt = "%s: %s ..." % (darkgreen(_("Backing up database to")),blue(comp_dbpath),)
619 self.updateProgress(
620 mytxt,
621 importance = 1,
622 type = "info",
623 header = blue(" @@ "),
624 back = True
625 )
626 import bz2
627 try:
628 self.entropyTools.compress_file(dbpath, comp_dbpath, bz2.BZ2File, compress_level)
629 except:
630 if not silent:
631 self.entropyTools.print_traceback()
632 return False, _("Unable to compress")
633
634 if not silent:
635 mytxt = "%s: %s" % (darkgreen(_("Database backed up successfully")),blue(comp_dbpath),)
636 self.updateProgress(
637 mytxt,
638 importance = 1,
639 type = "info",
640 header = blue(" @@ "),
641 back = True
642 )
643 return True, _("All fine")
644
646
647 bytes_required = 1024000*300
648 db_dir = os.path.dirname(db_destination)
649 if not (os.access(db_dir,os.W_OK) and os.path.isdir(db_dir) and \
650 os.path.isfile(backup_path) and os.access(backup_path,os.R_OK) and \
651 self.entropyTools.check_required_space(db_dir, bytes_required)):
652
653 if not silent:
654 mytxt = "%s: %s, %s" % (darkred(_("Cannot restore selected backup")),
655 blue(backup_path),darkred(_("permission denied")),)
656 self.updateProgress(
657 mytxt,
658 importance = 1,
659 type = "error",
660 header = red(" @@ ")
661 )
662 return False, mytxt
663
664 if not silent:
665 mytxt = "%s: %s => %s ..." % (darkgreen(_("Restoring backed up database")),
666 blue(os.path.basename(backup_path)),blue(db_destination),)
667 self.updateProgress(
668 mytxt,
669 importance = 1,
670 type = "info",
671 header = blue(" @@ "),
672 back = True
673 )
674
675 import bz2
676 try:
677 self.entropyTools.uncompress_file(backup_path, db_destination, bz2.BZ2File)
678 except:
679 if not silent:
680 self.entropyTools.print_traceback()
681 return False, _("Unable to unpack")
682
683 if not silent:
684 mytxt = "%s: %s" % (darkgreen(_("Database restored successfully")),
685 blue(db_destination),)
686 self.updateProgress(
687 mytxt,
688 importance = 1,
689 type = "info",
690 header = blue(" @@ "),
691 back = True
692 )
693 self.purge_cache()
694 return True, _("All fine")
695
697 if not client_dbdir:
698 client_dbdir = os.path.dirname(etpConst['etpdatabaseclientfilepath'])
699 return [os.path.join(client_dbdir,x) for x in os.listdir(client_dbdir) \
700 if x.startswith(etpConst['dbbackupprefix']) and \
701 os.access(os.path.join(client_dbdir,x),os.R_OK)
702 ]
703
705 """
706 This method is called whenever branch is successfully switched by user.
707 Branch is switched when user wants to upgrade the OS to a new
708 major release.
709 Any repository can be shipped with a sh script which if available,
710 handles system configuration to ease the migration.
711
712 @param old_branch: previously set branch
713 @type old_branch: string
714 @param new_branch: newly set branch
715 @type new_branch: string
716 @return: tuple composed by (1) list of repositories whose script has
717 been run and (2) bool describing if scripts exited with error
718 @rtype: tuple(set, bool)
719 """
720
721 const_debug_write(__name__,
722 "run_repositories_post_branch_switch_hooks: called")
723
724 client_dbconn = self.clientDbconn
725 hooks_ran = set()
726 if client_dbconn is None:
727 const_debug_write(__name__,
728 "run_repositories_post_branch_switch_hooks: clientdb not avail")
729 return hooks_ran, True
730
731 errors = False
732 repo_data = self.SystemSettings['repositories']['available']
733 repo_data_excl = self.SystemSettings['repositories']['available']
734 all_repos = sorted(set(repo_data.keys() + repo_data_excl.keys()))
735
736 for repoid in all_repos:
737
738 const_debug_write(__name__,
739 "run_repositories_post_branch_switch_hooks: %s" % (
740 repoid,)
741 )
742
743 mydata = repo_data.get(repoid)
744 if mydata is None:
745 mydata = repo_data_excl.get(repoid)
746
747 if mydata is None:
748 const_debug_write(__name__,
749 "run_repositories_post_branch_switch_hooks: skipping %s" % (
750 repoid,)
751 )
752 continue
753
754 branch_mig_script = mydata['post_branch_hop_script']
755 branch_mig_md5sum = '0'
756 if os.access(branch_mig_script, os.R_OK | os.F_OK):
757 branch_mig_md5sum = self.entropyTools.md5sum(branch_mig_script)
758
759 const_debug_write(__name__,
760 "run_repositories_post_branch_switch_hooks: script md5: %s" % (
761 branch_mig_md5sum,)
762 )
763
764
765 status_md5sums = client_dbconn.isBranchMigrationAvailable(
766 repoid, old_branch, new_branch)
767 if status_md5sums:
768 if branch_mig_md5sum == status_md5sums[0]:
769 const_debug_write(__name__,
770 "run_repositories_post_branch_switch_hooks: skip %s" % (
771 branch_mig_script,)
772 )
773 continue
774
775 const_debug_write(__name__,
776 "run_repositories_post_branch_switch_hooks: preparing run: %s" % (
777 branch_mig_script,)
778 )
779
780 if branch_mig_md5sum != '0':
781 args = ["/bin/sh", branch_mig_script, repoid,
782 etpConst['systemroot'] + "/", old_branch, new_branch]
783 const_debug_write(__name__,
784 "run_repositories_post_branch_switch_hooks: run: %s" % (
785 args,)
786 )
787 proc = subprocess.Popen(args, stdin = sys.stdin,
788 stdout = sys.stdout, stderr = sys.stderr)
789
790
791
792 br_rc = proc.wait()
793 const_debug_write(__name__,
794 "run_repositories_post_branch_switch_hooks: rc: %s" % (
795 br_rc,)
796 )
797 if br_rc != 0:
798 errors = True
799
800 const_debug_write(__name__,
801 "run_repositories_post_branch_switch_hooks: done")
802
803
804
805
806
807
808 client_dbconn.insertBranchMigration(repoid, old_branch, new_branch,
809 branch_mig_md5sum, '0')
810
811 const_debug_write(__name__,
812 "run_repositories_post_branch_switch_hooks: db data: %s" % (
813 (repoid, old_branch, new_branch, branch_mig_md5sum, '0',),)
814 )
815
816 hooks_ran.add(repoid)
817
818 return hooks_ran, errors
819
821 """
822 This method is called whenever branch is successfully switched by user
823 and all the updates have been installed (also look at:
824 run_repositories_post_branch_switch_hooks()).
825 Any repository can be shipped with a sh script which if available,
826 handles system configuration to ease the migration.
827
828 @param pretend: do not run hooks but just return list of repos whose
829 scripts should be run
830 @type pretend: bool
831 @return: tuple of length 2 composed by list of repositories whose
832 scripts have been run and errors boolean)
833 @rtype: tuple
834 """
835
836 const_debug_write(__name__,
837 "run_repository_post_branch_upgrade_hooks: called"
838 )
839
840 client_dbconn = self.clientDbconn
841 hooks_ran = set()
842 if client_dbconn is None:
843 return hooks_ran, True
844
845 repo_data = self.SystemSettings['repositories']['available']
846 branch = self.SystemSettings['repositories']['branch']
847 errors = False
848
849 for repoid in self.validRepositories:
850
851 const_debug_write(__name__,
852 "run_repository_post_branch_upgrade_hooks: repoid: %s" % (
853 (repoid,),
854 )
855 )
856
857 mydata = repo_data.get(repoid)
858 if mydata is None:
859 const_debug_write(__name__,
860 "run_repository_post_branch_upgrade_hooks: repo data N/A")
861 continue
862
863
864 branch_upg_script = mydata['post_branch_upgrade_script']
865 branch_upg_md5sum = '0'
866 if os.access(branch_upg_script, os.R_OK | os.F_OK):
867 branch_upg_md5sum = self.entropyTools.md5sum(branch_upg_script)
868
869 const_debug_write(__name__,
870 "run_repository_post_branch_upgrade_hooks: script md5: %s" % (
871 branch_upg_md5sum,)
872 )
873
874 upgrade_data = client_dbconn.retrieveBranchMigration(branch)
875 if upgrade_data.get(repoid) is None:
876
877 const_debug_write(__name__,
878 "run_repository_post_branch_upgrade_hooks: %s: %s" % (
879 repoid, "branch upgrade data not avail",)
880 )
881 continue
882 repo_upgrade_data = upgrade_data[repoid]
883
884 const_debug_write(__name__,
885 "run_repository_post_branch_upgrade_hooks: upgrade data: %s" % (
886 repo_upgrade_data,)
887 )
888
889 for from_branch in sorted(repo_upgrade_data):
890
891 const_debug_write(__name__,
892 "run_repository_post_branch_upgrade_hooks: upgrade: %s" % (
893 from_branch,)
894 )
895
896
897
898
899 post_mig_md5, post_upg_md5 = repo_upgrade_data[from_branch]
900 if branch_upg_md5sum == post_upg_md5:
901
902 const_debug_write(__name__,
903 "run_repository_post_branch_upgrade_hooks: %s: %s" % (
904 "already run for from_branch", from_branch,)
905 )
906 continue
907
908 hooks_ran.add(repoid)
909
910 if pretend:
911 const_debug_write(__name__,
912 "run_repository_post_branch_upgrade_hooks: %s: %s => %s" % (
913 "pretend enabled, not actually running",
914 repoid, from_branch,
915 )
916 )
917 continue
918
919 const_debug_write(__name__,
920 "run_repository_post_branch_upgrade_hooks: %s: %s" % (
921 "running upgrade script from_branch:", from_branch,)
922 )
923
924 args = ["/bin/sh", branch_upg_script, repoid,
925 etpConst['systemroot'] + "/", from_branch, branch]
926 proc = subprocess.Popen(args, stdin = sys.stdin,
927 stdout = sys.stdout, stderr = sys.stderr)
928 mig_rc = proc.wait()
929
930 const_debug_write(__name__,
931 "run_repository_post_branch_upgrade_hooks: %s: %s" % (
932 "upgrade script exit status", mig_rc,)
933 )
934
935 if mig_rc != 0:
936 errors = True
937
938
939 client_dbconn.setBranchMigrationPostUpgradeMd5sum(repoid,
940 from_branch, branch, branch_upg_md5sum)
941
942 const_debug_write(__name__,
943 "run_repository_post_branch_upgrade_hooks: %s: %s" % (
944 "saved upgrade data",
945 (repoid, from_branch, branch, branch_upg_md5sum,),
946 )
947 )
948
949 return hooks_ran, errors
950
951
953
954
955 RESOURCES_LOCK_F_REF = None
956 RESOURCES_LOCK_F_COUNT = 0
957
961
963
964 os.chmod(filepath,0664)
965 if etpConst['entropygid'] != None:
966 os.chown(filepath,-1,etpConst['entropygid'])
967
974
996
999
1001 if not os.path.isfile(pidfile):
1002 return False
1003 f = open(pidfile)
1004 s_pid = f.readline().strip()
1005 f.close()
1006 try:
1007 s_pid = int(s_pid)
1008 except ValueError:
1009 return False
1010
1011
1012 mypid = os.getpid()
1013 if (s_pid != mypid) and const_pid_exists(s_pid):
1014
1015 return True
1016 return False
1017
1019
1020 if MiscMixin.RESOURCES_LOCK_F_REF is not None:
1021
1022 return True
1023
1024 lockdir = os.path.dirname(pidfile)
1025 if not os.path.isdir(lockdir):
1026 os.makedirs(lockdir,0775)
1027 const_setup_perms(lockdir,etpConst['entropygid'])
1028 if mypid == None:
1029 mypid = os.getpid()
1030
1031 pid_f = open(pidfile, "w")
1032 try:
1033 fcntl.flock(pid_f.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
1034 except IOError, err:
1035 if err.errno not in (errno.EACCES, errno.EAGAIN,):
1036
1037 raise
1038 pid_f.close()
1039 return False
1040
1041 pid_f.write(str(mypid))
1042 pid_f.flush()
1043 MiscMixin.RESOURCES_LOCK_F_REF = pid_f
1044 return True
1045
1047
1048 etpConst['applicationlock'] = False
1049 const_setup_entropy_pid(just_read = True)
1050 locked = self.entropyTools.application_lock_check(gentle = True)
1051 if locked:
1052 if not silent:
1053 self.updateProgress(
1054 red(_("Another Entropy instance is currently active, cannot satisfy your request.")),
1055 importance = 1,
1056 type = "error",
1057 header = darkred(" @@ ")
1058 )
1059 return True
1060 return False
1061
1063
1064 lock_count = 0
1065 max_lock_count = 600
1066 sleep_seconds = 0.5
1067
1068
1069 while 1:
1070 locked = check_function()
1071 if not locked:
1072 if lock_count > 0:
1073 self.updateProgress(
1074 blue(_("Resources unlocked, let's go!")),
1075 importance = 1,
1076 type = "info",
1077 header = darkred(" @@ ")
1078 )
1079
1080
1081 time.sleep(5)
1082 break
1083 if lock_count >= max_lock_count:
1084 mycalc = max_lock_count*sleep_seconds/60
1085 self.updateProgress(
1086 blue(_("Resources still locked after %s minutes, giving up!")) % (mycalc,),
1087 importance = 1,
1088 type = "warning",
1089 header = darkred(" @@ ")
1090 )
1091 return True
1092 lock_count += 1
1093 self.updateProgress(
1094 blue(_("Resources locked, sleeping %s seconds, check #%s/%s")) % (
1095 sleep_seconds,
1096 lock_count,
1097 max_lock_count,
1098 ),
1099 importance = 1,
1100 type = "warning",
1101 header = darkred(" @@ "),
1102 back = True
1103 )
1104 time.sleep(sleep_seconds)
1105 return False
1106
1108 if etpConst.has_key(constant_name):
1109 myinst = etpConst[constant_name]
1110 if type(etpConst[constant_name]) in (list,tuple):
1111 myinst = etpConst[constant_name][:]
1112 elif type(etpConst[constant_name]) in (dict,set):
1113 myinst = etpConst[constant_name].copy()
1114 else:
1115 myinst = etpConst[constant_name]
1116 etpConst['backed_up'].update({constant_name: myinst})
1117 else:
1118 t = _("Nothing to backup in etpConst with %s key") % (constant_name,)
1119 raise InvalidData("InvalidData: %s" % (t,))
1120
1123
1125 if repositories is None:
1126 repositories = self.validRepositories
1127 for repoid in repositories:
1128 self.open_repository(repoid)
1129
1152
1154 viewer = None
1155 if os.access("/usr/bin/less",os.X_OK):
1156 viewer = "/usr/bin/less"
1157 elif os.access("/bin/more",os.X_OK):
1158 viewer = "/bin/more"
1159 if not viewer:
1160 viewer = self.get_file_editor()
1161 return viewer
1162
1164 editor = None
1165 if os.getenv("EDITOR"):
1166 editor = "$EDITOR"
1167 elif os.access("/bin/nano",os.X_OK):
1168 editor = "/bin/nano"
1169 elif os.access("/bin/vi",os.X_OK):
1170 editor = "/bin/vi"
1171 elif os.access("/usr/bin/vi",os.X_OK):
1172 editor = "/usr/bin/vi"
1173 elif os.access("/usr/bin/emacs",os.X_OK):
1174 editor = "/usr/bin/emacs"
1175 elif os.access("/bin/emacs",os.X_OK):
1176 editor = "/bin/emacs"
1177 return editor
1178
1180
1181 def _ensure_package_sets_dir():
1182 sets_dir = etpConst['confsetsdir']
1183 if not os.path.isdir(sets_dir):
1184 if os.path.lexists(sets_dir):
1185 os.remove(sets_dir)
1186 os.makedirs(sets_dir,0775)
1187 const_setup_perms(sets_dir, etpConst['entropygid'])
1188
1189 try:
1190 set_name = str(set_name)
1191 except (UnicodeEncodeError,UnicodeDecodeError,):
1192 raise InvalidPackageSet("InvalidPackageSet: %s %s" % (set_name,_("must be an ASCII string"),))
1193
1194 if set_name.startswith(etpConst['packagesetprefix']):
1195 raise InvalidPackageSet("InvalidPackageSet: %s %s '%s'" % (set_name,_("cannot start with"),etpConst['packagesetprefix'],))
1196 set_match, rc = self.package_set_match(set_name)
1197 if rc: return -1,_("Name already taken")
1198
1199 _ensure_package_sets_dir()
1200 set_file = os.path.join(etpConst['confsetsdir'],set_name)
1201 if os.path.isfile(set_file) and os.access(set_file,os.W_OK):
1202 try:
1203 os.remove(set_file)
1204 except OSError:
1205 return -2,_("Cannot remove the old element")
1206 if not os.access(os.path.dirname(set_file),os.W_OK):
1207 return -3,_("Cannot create the element")
1208
1209 f = open(set_file,"w")
1210 for x in set_atoms: f.write("%s\n" % (x,))
1211 f.flush()
1212 f.close()
1213 self.SystemSettings['system_package_sets'][set_name] = set(set_atoms)
1214 return 0,_("All fine")
1215
1217
1218 try:
1219 set_name = str(set_name)
1220 except (UnicodeEncodeError,UnicodeDecodeError,):
1221 raise InvalidPackageSet("InvalidPackageSet: %s %s" % (set_name,_("must be an ASCII string"),))
1222
1223 if set_name.startswith(etpConst['packagesetprefix']):
1224 raise InvalidPackageSet("InvalidPackageSet: %s %s '%s'" % (set_name,_("cannot start with"),etpConst['packagesetprefix'],))
1225
1226 set_match, rc = self.package_set_match(set_name)
1227 if not rc: return -1,_("Already removed")
1228 set_id, set_x, set_y = set_match
1229
1230 if set_id != etpConst['userpackagesetsid']:
1231 return -2,_("Not defined by user")
1232 set_file = os.path.join(etpConst['confsetsdir'],set_name)
1233 if os.path.isfile(set_file) and os.access(set_file,os.W_OK):
1234 os.remove(set_file)
1235 if set_name in self.SystemSettings['system_package_sets']:
1236 del self.SystemSettings['system_package_sets'][set_name]
1237 return 0,_("All fine")
1238 return -3,_("Set not found or unable to remove")
1239
1241 client_plugin_id = etpConst['system_settings_plugins_ids']['client_plugin']
1242 mask_installed = self.SystemSettings[client_plugin_id]['system_mask']['repos_installed']
1243 if idpackage in mask_installed:
1244 return True
1245 return False
1246
1248 return db_download_uri.split("/")[2]
1249
1254
1258
1260 if not install_queue:
1261 return {}
1262 licenses = {}
1263 cl_id = self.sys_settings_client_plugin_id
1264 repo_sys_data = self.SystemSettings[cl_id]['repositories']
1265
1266 for match in install_queue:
1267 repoid = match[1]
1268 dbconn = self.open_repository(repoid)
1269 wl = repo_sys_data['license_whitelist'].get(repoid)
1270 if not wl:
1271 continue
1272 keys = dbconn.retrieveLicensedataKeys(match[0])
1273 for key in keys:
1274 if key not in wl:
1275 found = self.clientDbconn.isLicenseAccepted(key)
1276 if found:
1277 continue
1278 if not licenses.has_key(key):
1279 licenses[key] = set()
1280 licenses[key].add(match)
1281 return licenses
1282
1283 - def get_text_license(self, license_name, repoid):
1284 dbconn = self.open_repository(repoid)
1285 text = dbconn.retrieveLicenseText(license_name)
1286 tempfile = self.entropyTools.get_random_temp_file()
1287 f = open(tempfile,"w")
1288 f.write(text)
1289 f.flush()
1290 f.close()
1291 return tempfile
1292
1294 """
1295 Set new Entropy branch. This is NOT thread-safe.
1296 Please note that if you call this method all your
1297 repository instance references will become invalid.
1298 This is caused by close_all_repositories and SystemSettings
1299 clear methods.
1300 Once you changed branch, the repository databases won't be
1301 available until you fetch them (through Repositories class)
1302
1303 @param branch -- new branch
1304 @type branch basestring
1305 @return None
1306 """
1307 self.Cacher.discard()
1308 self.Cacher.stop()
1309 self.purge_cache(showProgress = False)
1310 self.close_all_repositories()
1311
1312
1313 etpConst['branch'] = branch
1314 self.entropyTools.write_new_branch(branch)
1315
1316 del self.validRepositories[:]
1317 self.SystemSettings.clear()
1318
1319
1320 self.reopen_client_repository()
1321 self.clientDbconn.resetTreeupdatesDigests()
1322 self.validate_repositories(quiet = True)
1323 self.close_all_repositories()
1324 if self.xcache:
1325 self.Cacher.start()
1326
1327 - def get_meant_packages(self, search_term, from_installed = False,
1328 valid_repos = None):
1329
1330 if valid_repos is None:
1331 valid_repos = []
1332
1333 pkg_data = []
1334 atom_srch = False
1335 if "/" in search_term:
1336 atom_srch = True
1337
1338 if from_installed:
1339 if hasattr(self, 'clientDbconn'):
1340 if self.clientDbconn is not None:
1341 valid_repos.append(self.clientDbconn)
1342
1343 elif not valid_repos:
1344 valid_repos.extend(self.validRepositories[:])
1345
1346 for repo in valid_repos:
1347 if isinstance(repo, basestring):
1348 dbconn = self.open_repository(repo)
1349 elif isinstance(repo, EntropyRepository):
1350 dbconn = repo
1351 else:
1352 continue
1353 pkg_data.extend([(x,repo,) for x in \
1354 dbconn.searchSimilarPackages(search_term, atom = atom_srch)])
1355
1356 return pkg_data
1357
1359 """
1360 Return Entropy Package Groups metadata. The returned dictionary
1361 contains information to make Entropy Client users to group packages
1362 into "macro" categories.
1363
1364 @return: Entropy Package Groups metadata
1365 @rtype: dict
1366 """
1367 from entropy.spm.plugins.factory import get_default_class
1368 spm = get_default_class()
1369 groups = spm.get_package_groups().copy()
1370
1371
1372 categories = self.list_repo_categories()
1373 for data in groups.values():
1374
1375 exp_cats = set()
1376 for g_cat in data['categories']:
1377 exp_cats.update([x for x in categories if x.startswith(g_cat)])
1378 data['categories'] = sorted(exp_cats)
1379
1380 return groups
1381
1383 categories = set()
1384 for repo in self.validRepositories:
1385 dbconn = self.open_repository(repo)
1386 catsdata = dbconn.listAllCategories()
1387 categories.update(set([x[1] for x in catsdata]))
1388 return categories
1389
1391 pkg_matches = []
1392 for repo in self.validRepositories:
1393 dbconn = self.open_repository(repo)
1394 branch = self.SystemSettings['repositories']['branch']
1395 catsdata = dbconn.searchPackagesByCategory(category, branch = branch)
1396 pkg_matches.extend([(x[1],repo,) for x in catsdata if (x[1],repo,) not in pkg_matches])
1397 return pkg_matches
1398
1400
1401 data = {}
1402 for repo in self.validRepositories:
1403 try:
1404 dbconn = self.open_repository(repo)
1405 except RepositoryError:
1406 continue
1407 try:
1408 data = dbconn.retrieveCategoryDescription(category)
1409 except (self.dbapi2.OperationalError, self.dbapi2.IntegrityError,):
1410 continue
1411 if data: break
1412
1413 return data
1414
1418
1420
1421 idpackage, repoid = match
1422 dbconn = self.open_repository(repoid)
1423 cl_id = self.sys_settings_client_plugin_id
1424 misc_data = self.SystemSettings[cl_id]['misc']
1425 if mask:
1426 config_protect = set(dbconn.retrieveProtectMask(idpackage).split())
1427 config_protect |= set(misc_data['configprotectmask'])
1428 else:
1429 config_protect = set(dbconn.retrieveProtect(idpackage).split())
1430 config_protect |= set(misc_data['configprotect'])
1431 config_protect = [etpConst['systemroot']+x for x in config_protect]
1432
1433 return sorted(config_protect)
1434
1436
1437 if self.clientDbconn == None:
1438 return []
1439 cl_id = self.sys_settings_client_plugin_id
1440 misc_data = self.SystemSettings[cl_id]['misc']
1441 if mask:
1442 _pmask = self.clientDbconn.retrieveProtectMask(idpackage).split()
1443 config_protect = set(_pmask)
1444 config_protect |= set(misc_data['configprotectmask'])
1445 else:
1446 _protect = self.clientDbconn.retrieveProtect(idpackage).split()
1447 config_protect = set(_protect)
1448 config_protect |= set(misc_data['configprotect'])
1449 config_protect = [etpConst['systemroot']+x for x in config_protect]
1450
1451 return sorted(config_protect)
1452
1454
1455 if self.clientDbconn == None:
1456 return []
1457
1458
1459
1460 cl_id = self.sys_settings_client_plugin_id
1461 misc_data = self.SystemSettings[cl_id]['misc']
1462 if mask:
1463 _pmask = self.clientDbconn.listConfigProtectEntries(mask = True)
1464 config_protect = set(_pmask)
1465 config_protect |= set(misc_data['configprotectmask'])
1466 else:
1467 _protect = self.clientDbconn.listConfigProtectEntries()
1468 config_protect = set(_protect)
1469 config_protect |= set(misc_data['configprotect'])
1470 config_protect = [etpConst['systemroot']+x for x in config_protect]
1471
1472 return sorted(config_protect)
1473
1485
1487 dbpath = etpConst['packagestmpdir']+"/"+str(self.entropyTools.get_random_number())
1488 while os.path.isfile(dbpath):
1489 dbpath = etpConst['packagestmpdir']+"/"+str(self.entropyTools.get_random_number())
1490 return dbpath
1491
1492 - def quickpkg(self, atomstring, savedir = None):
1493 if savedir == None:
1494 savedir = etpConst['packagestmpdir']
1495 if not os.path.isdir(etpConst['packagestmpdir']):
1496 os.makedirs(etpConst['packagestmpdir'])
1497
1498 match = self.clientDbconn.atomMatch(atomstring)
1499 if match[0] == -1:
1500 return -1,None,None
1501 atom = self.clientDbconn.atomMatch(match[0])
1502 pkgdata = self.clientDbconn.getPackageData(match[0])
1503 resultfile = self.quickpkg_handler(pkgdata = pkgdata, dirpath = savedir)
1504 if resultfile == None:
1505 return -1,atom,None
1506 else:
1507 return 0,atom,resultfile
1508
1509 - def quickpkg_handler(self, pkgdata, dirpath, edb = True,
1510 portdbPath = None, fake = False, compression = "bz2", shiftpath = ""):
1511
1512 import tarfile
1513
1514 if compression not in ("bz2","","gz"):
1515 compression = "bz2"
1516
1517
1518 pkgtag = ''
1519 pkgrev = "~"+str(pkgdata['revision'])
1520 if pkgdata['versiontag']: pkgtag = "#"+pkgdata['versiontag']
1521 pkgname = pkgdata['name']+"-"+pkgdata['version']+pkgrev+pkgtag
1522 pkgcat = pkgdata['category']
1523 dirpath += "/"+pkgname+etpConst['packagesext']
1524 if os.path.isfile(dirpath):
1525 os.remove(dirpath)
1526 tar = tarfile.open(dirpath,"w:"+compression)
1527
1528 if not fake:
1529
1530 contents = sorted([x for x in pkgdata['content']])
1531
1532
1533 for path in contents:
1534
1535 encoded_path = path
1536 path = path.encode('raw_unicode_escape')
1537 path = shiftpath+path
1538 try:
1539 exist = os.lstat(path)
1540 except OSError:
1541 continue
1542 arcname = path[len(shiftpath):]
1543 if arcname.startswith("/"):
1544 arcname = arcname[1:]
1545 ftype = pkgdata['content'][encoded_path]
1546 if str(ftype) == '0': ftype = 'dir'
1547 if 'dir' == ftype and \
1548 not stat.S_ISDIR(exist.st_mode) and \
1549 os.path.isdir(path):
1550 path = os.path.realpath(path)
1551
1552 tarinfo = tar.gettarinfo(path, arcname)
1553
1554 if stat.S_ISREG(exist.st_mode):
1555 tarinfo.mode = stat.S_IMODE(exist.st_mode)
1556 tarinfo.type = tarfile.REGTYPE
1557 f = open(path)
1558 try:
1559 tar.addfile(tarinfo, f)
1560 finally:
1561 f.close()
1562 else:
1563 tar.addfile(tarinfo)
1564
1565 tar.close()
1566
1567
1568 import entropy.xpak as xpak
1569 Spm = self.Spm()
1570
1571 spm_name = self.entropyTools.remove_tag(pkgname)
1572 spm_name = self.entropyTools.remove_entropy_revision(spm_name)
1573 if portdbPath is None:
1574 spm_pkg = os.path.join(pkgcat, spm_name)
1575 dbbuild = Spm.get_installed_package_build_script_path(spm_pkg)
1576 dbdir = os.path.dirname(dbbuild)
1577 else:
1578 dbdir = os.path.join(portdbPath, pkgcat, spm_name)
1579
1580 if os.path.isdir(dbdir):
1581 tbz2 = xpak.tbz2(dirpath)
1582 tbz2.recompose(dbdir)
1583
1584 if edb:
1585 self.inject_entropy_database_into_package(dirpath, pkgdata)
1586
1587 if os.path.isfile(dirpath):
1588 return dirpath
1589 return None
1590
1591
1593
1595 """
1596 @input: matched atom (idpackage,repoid)
1597 @output:
1598 upgrade: int(2)
1599 install: int(1)
1600 reinstall: int(0)
1601 downgrade: int(-1)
1602 """
1603 dbconn = self.open_repository(match[1])
1604 pkgkey, pkgslot = dbconn.retrieveKeySlot(match[0])
1605 results = self.clientDbconn.searchKeySlot(pkgkey, pkgslot)
1606 if not results: return 1
1607
1608 installed_idpackage = results[0][0]
1609 pkgver, pkgtag, pkgrev = dbconn.getVersioningData(match[0])
1610 installedVer, installedTag, installedRev = self.clientDbconn.getVersioningData(installed_idpackage)
1611 pkgcmp = self.entropyTools.entropy_compare_versions((pkgver,pkgtag,pkgrev),(installedVer,installedTag,installedRev))
1612 if pkgcmp == 0:
1613 return 0
1614 elif pkgcmp > 0:
1615 return 2
1616 return -1
1617
1619 idpackage, repoid = match
1620 dbconn = self.open_repository(repoid)
1621 idpackage, idreason = dbconn.idpackageValidator(idpackage)
1622 masked = False
1623 if idpackage == -1: masked = True
1624 return masked, idreason, self.SystemSettings['pkg_masking_reasons'].get(idreason)
1625
1627 m_id, m_repo = match
1628 dbconn = self.open_repository(m_repo)
1629 conflicts = dbconn.retrieveConflicts(m_id)
1630 found_conflicts = set()
1631 for conflict in conflicts:
1632 my_m_id, my_m_rc = self.clientDbconn.atomMatch(conflict)
1633 if my_m_id != -1:
1634
1635 match_data = dbconn.retrieveKeySlot(m_id)
1636 installed_match_data = self.clientDbconn.retrieveKeySlot(my_m_id)
1637 if match_data != installed_match_data:
1638 found_conflicts.add(my_m_id)
1639 return found_conflicts
1640
1642 m_id, m_repo = match
1643 dbconn = self.open_repository(m_repo)
1644 idpackage, idreason = dbconn.idpackageValidator(m_id, live = live_check)
1645 if idpackage != -1:
1646 return False
1647 return True
1648
1650
1651 m_id, m_repo = match
1652 if m_repo not in self.validRepositories: return False
1653 dbconn = self.open_repository(m_repo)
1654 idpackage, idreason = dbconn.idpackageValidator(m_id, live = live_check)
1655 if idpackage != -1: return False
1656 myr = self.SystemSettings['pkg_masking_reference']
1657 user_masks = [myr['user_package_mask'],myr['user_license_mask'],myr['user_live_mask']]
1658 if idreason in user_masks:
1659 return True
1660 return False
1661
1663
1664 m_id, m_repo = match
1665 if m_repo not in self.validRepositories: return False
1666 dbconn = self.open_repository(m_repo)
1667 idpackage, idreason = dbconn.idpackageValidator(m_id, live = live_check)
1668 if idpackage == -1: return False
1669 myr = self.SystemSettings['pkg_masking_reference']
1670 user_masks = [
1671 myr['user_package_unmask'],myr['user_live_unmask'],myr['user_package_keywords'],
1672 myr['user_repo_package_keywords_all'], myr['user_repo_package_keywords']
1673 ]
1674 if idreason in user_masks:
1675 return True
1676 return False
1677
1678 - def mask_match(self, match, method = 'atom', dry_run = False, clean_all_cache = False):
1689
1690 - def unmask_match(self, match, method = 'atom', dry_run = False, clean_all_cache = False):
1701
1702 - def _mask_unmask_match(self, match, method, methods_reference, dry_run = False, clean_all_cache = False):
1729
1735
1741
1747
1753
1758
1763
1765 exist = False
1766 if not os.path.isfile(m_file):
1767 if not os.access(os.path.dirname(m_file),os.W_OK):
1768 return False
1769 elif not os.access(m_file, os.W_OK):
1770 return False
1771 elif not dry_run:
1772 exist = True
1773
1774 if dry_run:
1775 return True
1776
1777 content = []
1778 if exist:
1779 f = open(m_file,"r")
1780 content = [x.strip() for x in f.readlines()]
1781 f.close()
1782 content.append(keyword)
1783 m_file_tmp = m_file+".tmp"
1784 f = open(m_file_tmp,"w")
1785 for line in content:
1786 f.write(line+"\n")
1787 f.flush()
1788 f.close()
1789 shutil.move(m_file_tmp,m_file)
1790 return True
1791
1793 setting_data = self.SystemSettings.get_setting_files_data()
1794 masking_list = [setting_data['mask'],setting_data['unmask']]
1795 return self._clear_match_generic(match, masking_list = masking_list, dry_run = dry_run)
1796
1798
1799 self.SystemSettings['live_packagemasking']['unmask_matches'].discard(match)
1800 self.SystemSettings['live_packagemasking']['mask_matches'].discard(match)
1801
1802 if dry_run: return
1803
1804 for mask_file in masking_list:
1805 if not (os.path.isfile(mask_file) and os.access(mask_file,os.W_OK)): continue
1806 f = open(mask_file,"r")
1807 newf = self.entropyTools.open_buffer()
1808 line = f.readline()
1809 while line:
1810 line = line.strip()
1811 if line.startswith("#"):
1812 newf.write(line+"\n")
1813 line = f.readline()
1814 continue
1815 elif not line:
1816 newf.write("\n")
1817 line = f.readline()
1818 continue
1819 mymatch = self.atom_match(line, packagesFilter = False)
1820 if mymatch == match:
1821 line = f.readline()
1822 continue
1823 newf.write(line+"\n")
1824 line = f.readline()
1825 f.close()
1826 tmpfile = mask_file+".w_tmp"
1827 f = open(tmpfile,"w")
1828 f.write(newf.getvalue())
1829 f.flush()
1830 f.close()
1831 newf.close()
1832 shutil.move(tmpfile,mask_file)
1833