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
338
349
359
386
388 try:
389 repodata = self.SystemSettings['repositories']['available'][repoid].copy()
390 except KeyError:
391 if not self.SystemSettings['repositories']['excluded'].has_key(repoid):
392 raise
393 repodata = self.SystemSettings['repositories']['excluded'][repoid].copy()
394 return repodata
395
396
398 atoms_contained = []
399 basefile = os.path.basename(tbz2file)
400 cut_idx = -1*(len(etpConst['packagesext']))
401 db_dir = tempfile.mkdtemp()
402 dbfile = self.entropyTools.extract_edb(tbz2file,
403 dbpath = db_dir+"/packages.db")
404 if dbfile == None:
405 return -1, atoms_contained
406 etpSys['dirstoclean'].add(os.path.dirname(dbfile))
407
408 repodata = {}
409 repodata['repoid'] = basefile
410 repodata['description'] = "Dynamic database from " + basefile
411 repodata['packages'] = []
412 repodata['dbpath'] = os.path.dirname(dbfile)
413 repodata['pkgpath'] = os.path.realpath(tbz2file)
414 repodata['smartpackage'] = False
415
416 mydbconn = self.open_generic_database(dbfile)
417
418 try:
419 myidpackages = mydbconn.listAllIdpackages()
420 except (AttributeError, self.dbapi2.DatabaseError, \
421 self.dbapi2.IntegrityError, self.dbapi2.OperationalError,):
422 return -2, atoms_contained
423 if len(myidpackages) > 1:
424 repodata[basefile]['smartpackage'] = True
425 for myidpackage in myidpackages:
426 compiled_arch = mydbconn.retrieveDownloadURL(myidpackage)
427 if compiled_arch.find("/"+etpSys['arch']+"/") == -1:
428 return -3, atoms_contained
429 atoms_contained.append((int(myidpackage), basefile))
430
431 self.add_repository(repodata)
432 self.validate_repositories()
433 if basefile not in self.validRepositories:
434 self.remove_repository(basefile)
435 return -4, atoms_contained
436 mydbconn.closeDB()
437 del mydbconn
438 return 0, atoms_contained
439
445
447
448 def load_db_from_ram():
449 self.safe_mode = etpConst['safemodeerrors']['clientdb']
450 mytxt = "%s, %s" % (_("System database not found or corrupted"),
451 _("running in safe mode using empty database from RAM"),)
452 self.updateProgress(
453 darkred(mytxt),
454 importance = 1,
455 type = "warning",
456 header = bold("!!!"),
457 )
458 conn = self.open_memory_database(dbname = etpConst['clientdbid'])
459 return conn
460
461 db_dir = os.path.dirname(etpConst['etpdatabaseclientfilepath'])
462 if not os.path.isdir(db_dir): os.makedirs(db_dir)
463
464 db_path = etpConst['etpdatabaseclientfilepath']
465 if (not self.noclientdb) and (not os.path.isfile(db_path)):
466 conn = load_db_from_ram()
467 self.entropyTools.print_traceback(f = self.clientLog)
468 else:
469 try:
470 conn = LocalRepository(readOnly = False, dbFile = db_path,
471 clientDatabase = True, dbname = etpConst['clientdbid'],
472 xcache = self.xcache, indexing = self.indexing,
473 OutputInterface = self, ServiceInterface = self
474 )
475 except (self.dbapi2.DatabaseError,):
476 self.entropyTools.print_traceback(f = self.clientLog)
477 conn = load_db_from_ram()
478 else:
479
480 if not self.noclientdb:
481 try:
482 conn.validateDatabase()
483 except SystemDatabaseError:
484 try:
485 conn.closeDB()
486 except:
487 pass
488 self.entropyTools.print_traceback(f = self.clientLog)
489 conn = load_db_from_ram()
490
491 self.clientDbconn = conn
492 return self.clientDbconn
493
495 self.updateProgress(
496 darkred(_("Sanity Check") + ": " + _("system database")),
497 importance = 2,
498 type = "warning"
499 )
500 idpkgs = self.clientDbconn.listAllIdpackages()
501 length = len(idpkgs)
502 count = 0
503 errors = False
504 scanning_txt = _("Scanning...")
505 for x in idpkgs:
506 count += 1
507 self.updateProgress(
508 darkgreen(scanning_txt),
509 importance = 0,
510 type = "info",
511 back = True,
512 count = (count,length),
513 percent = True
514 )
515 try:
516 self.clientDbconn.getPackageData(x)
517 except Exception ,e:
518 self.entropyTools.print_traceback()
519 errors = True
520 self.updateProgress(
521 darkred(_("Errors on idpackage %s, error: %s")) % (x,str(e)),
522 importance = 0,
523 type = "warning"
524 )
525
526 if not errors:
527 t = _("Sanity Check") + ": %s" % (bold(_("PASSED")),)
528 self.updateProgress(
529 darkred(t),
530 importance = 2,
531 type = "warning"
532 )
533 return 0
534 else:
535 t = _("Sanity Check") + ": %s" % (bold(_("CORRUPTED")),)
536 self.updateProgress(
537 darkred(t),
538 importance = 2,
539 type = "warning"
540 )
541 return -1
542
543 - def open_generic_database(self, dbfile, dbname = None, xcache = None,
544 readOnly = False, indexing_override = None, skipChecks = False):
545 if xcache == None:
546 xcache = self.xcache
547 if indexing_override != None:
548 indexing = indexing_override
549 else:
550 indexing = self.indexing
551 if dbname == None:
552 dbname = etpConst['genericdbid']
553 return LocalRepository(
554 readOnly = readOnly,
555 dbFile = dbfile,
556 clientDatabase = True,
557 dbname = dbname,
558 xcache = xcache,
559 indexing = indexing,
560 OutputInterface = self,
561 skipChecks = skipChecks
562 )
563
565 if dbname == None:
566 dbname = etpConst['genericdbid']
567 dbc = LocalRepository(
568 readOnly = False,
569 dbFile = ':memory:',
570 clientDatabase = True,
571 dbname = dbname,
572 xcache = False,
573 indexing = False,
574 OutputInterface = self,
575 skipChecks = True,
576 ServiceInterface = self
577 )
578 dbc.initializeDatabase()
579 return dbc
580
581 - def backup_database(self, dbpath, backup_dir = None, silent = False, compress_level = 9):
582
583 if compress_level not in range(1,10):
584 compress_level = 9
585
586 backup_dir = os.path.dirname(dbpath)
587 if not backup_dir: backup_dir = os.path.dirname(dbpath)
588 dbname = os.path.basename(dbpath)
589 bytes_required = 1024000*300
590 if not (os.access(backup_dir,os.W_OK) and \
591 os.path.isdir(backup_dir) and os.path.isfile(dbpath) and \
592 os.access(dbpath,os.R_OK) and self.entropyTools.check_required_space(backup_dir, bytes_required)):
593 if not silent:
594 mytxt = "%s: %s, %s" % (darkred(_("Cannot backup selected database")),blue(dbpath),darkred(_("permission denied")),)
595 self.updateProgress(
596 mytxt,
597 importance = 1,
598 type = "error",
599 header = red(" @@ ")
600 )
601 return False, mytxt
602
603 def get_ts():
604 from datetime import datetime
605 ts = datetime.fromtimestamp(time.time())
606 return "%s%s%s_%sh%sm%ss" % (ts.year,ts.month,ts.day,ts.hour,ts.minute,ts.second)
607
608 comp_dbname = "%s%s.%s.bz2" % (etpConst['dbbackupprefix'],dbname,get_ts(),)
609 comp_dbpath = os.path.join(backup_dir,comp_dbname)
610 if not silent:
611 mytxt = "%s: %s ..." % (darkgreen(_("Backing up database to")),blue(comp_dbpath),)
612 self.updateProgress(
613 mytxt,
614 importance = 1,
615 type = "info",
616 header = blue(" @@ "),
617 back = True
618 )
619 import bz2
620 try:
621 self.entropyTools.compress_file(dbpath, comp_dbpath, bz2.BZ2File, compress_level)
622 except:
623 if not silent:
624 self.entropyTools.print_traceback()
625 return False, _("Unable to compress")
626
627 if not silent:
628 mytxt = "%s: %s" % (darkgreen(_("Database backed up successfully")),blue(comp_dbpath),)
629 self.updateProgress(
630 mytxt,
631 importance = 1,
632 type = "info",
633 header = blue(" @@ "),
634 back = True
635 )
636 return True, _("All fine")
637
639
640 bytes_required = 1024000*300
641 db_dir = os.path.dirname(db_destination)
642 if not (os.access(db_dir,os.W_OK) and os.path.isdir(db_dir) and \
643 os.path.isfile(backup_path) and os.access(backup_path,os.R_OK) and \
644 self.entropyTools.check_required_space(db_dir, bytes_required)):
645
646 if not silent:
647 mytxt = "%s: %s, %s" % (darkred(_("Cannot restore selected backup")),
648 blue(backup_path),darkred(_("permission denied")),)
649 self.updateProgress(
650 mytxt,
651 importance = 1,
652 type = "error",
653 header = red(" @@ ")
654 )
655 return False, mytxt
656
657 if not silent:
658 mytxt = "%s: %s => %s ..." % (darkgreen(_("Restoring backed up database")),
659 blue(os.path.basename(backup_path)),blue(db_destination),)
660 self.updateProgress(
661 mytxt,
662 importance = 1,
663 type = "info",
664 header = blue(" @@ "),
665 back = True
666 )
667
668 import bz2
669 try:
670 self.entropyTools.uncompress_file(backup_path, db_destination, bz2.BZ2File)
671 except:
672 if not silent:
673 self.entropyTools.print_traceback()
674 return False, _("Unable to unpack")
675
676 if not silent:
677 mytxt = "%s: %s" % (darkgreen(_("Database restored successfully")),
678 blue(db_destination),)
679 self.updateProgress(
680 mytxt,
681 importance = 1,
682 type = "info",
683 header = blue(" @@ "),
684 back = True
685 )
686 self.purge_cache()
687 return True, _("All fine")
688
690 if not client_dbdir:
691 client_dbdir = os.path.dirname(etpConst['etpdatabaseclientfilepath'])
692 return [os.path.join(client_dbdir,x) for x in os.listdir(client_dbdir) \
693 if x.startswith(etpConst['dbbackupprefix']) and \
694 os.access(os.path.join(client_dbdir,x),os.R_OK)
695 ]
696
698 """
699 This method is called whenever branch is successfully switched by user.
700 Branch is switched when user wants to upgrade the OS to a new
701 major release.
702 Any repository can be shipped with a sh script which if available,
703 handles system configuration to ease the migration.
704
705 @param old_branch: previously set branch
706 @type old_branch: string
707 @param new_branch: newly set branch
708 @type new_branch: string
709 @return: tuple composed by (1) list of repositories whose script has
710 been run and (2) bool describing if scripts exited with error
711 @rtype: tuple(set, bool)
712 """
713
714 const_debug_write(__name__,
715 "run_repositories_post_branch_switch_hooks: called")
716
717 client_dbconn = self.clientDbconn
718 hooks_ran = set()
719 if client_dbconn is None:
720 const_debug_write(__name__,
721 "run_repositories_post_branch_switch_hooks: clientdb not avail")
722 return hooks_ran, True
723
724 from datetime import datetime
725 place_status_file = set()
726 errors = False
727 repo_data = self.SystemSettings['repositories']['available']
728 repo_data_excl = self.SystemSettings['repositories']['available']
729 all_repos = sorted(set(repo_data.keys() + repo_data_excl.keys()))
730
731 for repoid in all_repos:
732
733 const_debug_write(__name__,
734 "run_repositories_post_branch_switch_hooks: %s" % (
735 repoid,)
736 )
737
738 mydata = repo_data.get(repoid)
739 if mydata is None:
740 mydata = repo_data_excl.get(repoid)
741
742 if mydata is None:
743 const_debug_write(__name__,
744 "run_repositories_post_branch_switch_hooks: skipping %s" % (
745 repoid,)
746 )
747 continue
748
749 branch_mig_script = mydata['post_branch_hop_script']
750 branch_mig_md5sum = '0'
751 if os.access(branch_mig_script, os.R_OK | os.F_OK):
752 branch_mig_md5sum = self.entropyTools.md5sum(branch_mig_script)
753
754 const_debug_write(__name__,
755 "run_repositories_post_branch_switch_hooks: script md5: %s" % (
756 branch_mig_md5sum,)
757 )
758
759
760 status_md5sums = client_dbconn.isBranchMigrationAvailable(
761 repoid, old_branch, new_branch)
762 if status_md5sums:
763 if branch_mig_md5sum == status_md5sums[0]:
764 const_debug_write(__name__,
765 "run_repositories_post_branch_switch_hooks: skip %s" % (
766 branch_mig_script,)
767 )
768 continue
769
770 const_debug_write(__name__,
771 "run_repositories_post_branch_switch_hooks: preparing run: %s" % (
772 branch_mig_script,)
773 )
774
775 if branch_mig_md5sum != '0':
776 args = ["/bin/sh", branch_mig_script, repoid, old_branch,
777 new_branch]
778 const_debug_write(__name__,
779 "run_repositories_post_branch_switch_hooks: run: %s" % (
780 args,)
781 )
782 proc = subprocess.Popen(args, stdin = sys.stdin,
783 stdout = sys.stdout, stderr = sys.stderr)
784
785
786
787 br_rc = proc.wait()
788 const_debug_write(__name__,
789 "run_repositories_post_branch_switch_hooks: rc: %s" % (
790 br_rc,)
791 )
792 if br_rc != 0:
793 errors = True
794
795 const_debug_write(__name__,
796 "run_repositories_post_branch_switch_hooks: done")
797
798
799
800
801
802
803 client_dbconn.insertBranchMigration(repoid, old_branch, new_branch,
804 branch_mig_md5sum, '0')
805
806 const_debug_write(__name__,
807 "run_repositories_post_branch_switch_hooks: db data: %s" % (
808 (repoid, old_branch, new_branch, branch_mig_md5sum, '0',),)
809 )
810
811 hooks_ran.add(repoid)
812
813 return hooks_ran, errors
814
816 """
817 This method is called whenever branch is successfully switched by user
818 and all the updates have been installed (also look at:
819 run_repositories_post_branch_switch_hooks()).
820 Any repository can be shipped with a sh script which if available,
821 handles system configuration to ease the migration.
822
823 @return: list of repositories whose script has been run
824 @rtype: set
825 """
826
827 const_debug_write(__name__,
828 "run_repository_post_branch_upgrade_hooks: called"
829 )
830
831 client_dbconn = self.clientDbconn
832 hooks_ran = set()
833 if client_dbconn is None:
834 return hooks_ran, True
835
836 repo_data = self.SystemSettings['repositories']['available']
837 branch = self.SystemSettings['repositories']['branch']
838 errors = False
839
840 for repoid in self.validRepositories:
841
842 const_debug_write(__name__,
843 "run_repository_post_branch_upgrade_hooks: repoid: %s" % (
844 (repoid,),
845 )
846 )
847
848 mydata = repo_data.get(repoid)
849 if mydata is None:
850 const_debug_write(__name__,
851 "run_repository_post_branch_upgrade_hooks: repo data N/A")
852 continue
853
854
855 branch_upg_script = mydata['post_branch_upgrade_script']
856 branch_upg_md5sum = '0'
857 if os.access(branch_upg_script, os.R_OK | os.F_OK):
858 branch_upg_md5sum = self.entropyTools.md5sum(branch_upg_script)
859
860 const_debug_write(__name__,
861 "run_repository_post_branch_upgrade_hooks: script md5: %s" % (
862 branch_upg_md5sum,)
863 )
864
865 upgrade_data = client_dbconn.retrieveBranchMigration(branch)
866 if upgrade_data.get(repoid) is None:
867
868 const_debug_write(__name__,
869 "run_repository_post_branch_upgrade_hooks: %s: %s" % (
870 repoid, "branch upgrade data not avail",)
871 )
872 continue
873 repo_upgrade_data = upgrade_data[repoid]
874
875 const_debug_write(__name__,
876 "run_repository_post_branch_upgrade_hooks: upgrade data: %s" % (
877 repo_upgrade_data,)
878 )
879
880 for from_branch in sorted(repo_upgrade_data):
881
882 const_debug_write(__name__,
883 "run_repository_post_branch_upgrade_hooks: upgrade: %s" % (
884 from_branch,)
885 )
886
887
888
889
890 post_mig_md5, post_upg_md5 = repo_upgrade_data[from_branch]
891 if branch_upg_md5sum == post_upg_md5:
892
893 const_debug_write(__name__,
894 "run_repository_post_branch_upgrade_hooks: %s: %s" % (
895 "already run for from_branch", from_branch,)
896 )
897 continue
898
899 const_debug_write(__name__,
900 "run_repository_post_branch_upgrade_hooks: %s: %s" % (
901 "running upgrade script from_branch:", from_branch,)
902 )
903
904 args = ["/bin/sh", branch_upg_script, repoid, from_branch,
905 branch]
906 proc = subprocess.Popen(args, stdin = sys.stdin,
907 stdout = sys.stdout, stderr = sys.stderr)
908 mig_rc = proc.wait()
909
910 const_debug_write(__name__,
911 "run_repository_post_branch_upgrade_hooks: %s: %s" % (
912 "upgrade script exit status", mig_rc,)
913 )
914
915 if mig_rc != 0:
916 errors = True
917
918
919 client_dbconn.setBranchMigrationPostUpgradeMd5sum(repoid,
920 from_branch, branch, branch_upg_md5sum)
921
922 const_debug_write(__name__,
923 "run_repository_post_branch_upgrade_hooks: %s: %s" % (
924 "saved upgrade data",
925 (repoid, from_branch, branch, branch_upg_md5sum,),
926 )
927 )
928
929 return hooks_ran, errors
930
931
933
937
939
940 os.chmod(filepath,0664)
941 if etpConst['entropygid'] != None:
942 os.chown(filepath,-1,etpConst['entropygid'])
943
946
948 if os.path.isfile(etpConst['locks']['using_resources']):
949 os.remove(etpConst['locks']['using_resources'])
950
954
956 if not os.path.isfile(pidfile):
957 return False
958 f = open(pidfile)
959 s_pid = f.readline().strip()
960 f.close()
961 try:
962 s_pid = int(s_pid)
963 except ValueError:
964 return False
965
966 mypid = os.getpid()
967 if (s_pid != mypid) and os.path.isdir("%s/proc/%s" % (etpConst['systemroot'],s_pid,)):
968
969 return True
970 return False
971
973 lockdir = os.path.dirname(pidfile)
974 if not os.path.isdir(lockdir):
975 os.makedirs(lockdir,0775)
976 const_setup_perms(lockdir,etpConst['entropygid'])
977 if mypid == None:
978 mypid = os.getpid()
979 f = open(pidfile,"w")
980 f.write(str(mypid))
981 f.flush()
982 f.close()
983
985
986 etpConst['applicationlock'] = False
987 const_setup_entropy_pid(just_read = True)
988 locked = self.entropyTools.application_lock_check(option = None, gentle = True)
989 if locked:
990 if not silent:
991 self.updateProgress(
992 red(_("Another Entropy instance is currently active, cannot satisfy your request.")),
993 importance = 1,
994 type = "error",
995 header = darkred(" @@ ")
996 )
997 return True
998 return False
999
1001
1002 lock_count = 0
1003 max_lock_count = 600
1004 sleep_seconds = 0.5
1005
1006
1007 while 1:
1008 locked = check_function()
1009 if not locked:
1010 if lock_count > 0:
1011 self.updateProgress(
1012 blue(_("Resources unlocked, let's go!")),
1013 importance = 1,
1014 type = "info",
1015 header = darkred(" @@ ")
1016 )
1017
1018
1019 time.sleep(5)
1020 break
1021 if lock_count >= max_lock_count:
1022 mycalc = max_lock_count*sleep_seconds/60
1023 self.updateProgress(
1024 blue(_("Resources still locked after %s minutes, giving up!")) % (mycalc,),
1025 importance = 1,
1026 type = "warning",
1027 header = darkred(" @@ ")
1028 )
1029 return True
1030 lock_count += 1
1031 self.updateProgress(
1032 blue(_("Resources locked, sleeping %s seconds, check #%s/%s")) % (
1033 sleep_seconds,
1034 lock_count,
1035 max_lock_count,
1036 ),
1037 importance = 1,
1038 type = "warning",
1039 header = darkred(" @@ "),
1040 back = True
1041 )
1042 time.sleep(sleep_seconds)
1043 return False
1044
1046 if etpConst.has_key(constant_name):
1047 myinst = etpConst[constant_name]
1048 if type(etpConst[constant_name]) in (list,tuple):
1049 myinst = etpConst[constant_name][:]
1050 elif type(etpConst[constant_name]) in (dict,set):
1051 myinst = etpConst[constant_name].copy()
1052 else:
1053 myinst = etpConst[constant_name]
1054 etpConst['backed_up'].update({constant_name: myinst})
1055 else:
1056 t = _("Nothing to backup in etpConst with %s key") % (constant_name,)
1057 raise InvalidData("InvalidData: %s" % (t,))
1058
1061
1063 if repositories == None:
1064 repositories = self.validRepositories
1065 for repoid in repositories:
1066 dbconn = self.open_repository(repoid)
1067
1090
1092 viewer = None
1093 if os.access("/usr/bin/less",os.X_OK):
1094 viewer = "/usr/bin/less"
1095 elif os.access("/bin/more",os.X_OK):
1096 viewer = "/bin/more"
1097 if not viewer:
1098 viewer = self.get_file_editor()
1099 return viewer
1100
1102 editor = None
1103 if os.getenv("EDITOR"):
1104 editor = "$EDITOR"
1105 elif os.access("/bin/nano",os.X_OK):
1106 editor = "/bin/nano"
1107 elif os.access("/bin/vi",os.X_OK):
1108 editor = "/bin/vi"
1109 elif os.access("/usr/bin/vi",os.X_OK):
1110 editor = "/usr/bin/vi"
1111 elif os.access("/usr/bin/emacs",os.X_OK):
1112 editor = "/usr/bin/emacs"
1113 elif os.access("/bin/emacs",os.X_OK):
1114 editor = "/bin/emacs"
1115 return editor
1116
1118
1119 def _ensure_package_sets_dir():
1120 sets_dir = etpConst['confsetsdir']
1121 if not os.path.isdir(sets_dir):
1122 if os.path.lexists(sets_dir):
1123 os.remove(sets_dir)
1124 os.makedirs(sets_dir,0775)
1125 const_setup_perms(sets_dir, etpConst['entropygid'])
1126
1127 try:
1128 set_name = str(set_name)
1129 except (UnicodeEncodeError,UnicodeDecodeError,):
1130 raise InvalidPackageSet("InvalidPackageSet: %s %s" % (set_name,_("must be an ASCII string"),))
1131
1132 if set_name.startswith(etpConst['packagesetprefix']):
1133 raise InvalidPackageSet("InvalidPackageSet: %s %s '%s'" % (set_name,_("cannot start with"),etpConst['packagesetprefix'],))
1134 set_match, rc = self.package_set_match(set_name)
1135 if rc: return -1,_("Name already taken")
1136
1137 _ensure_package_sets_dir()
1138 set_file = os.path.join(etpConst['confsetsdir'],set_name)
1139 if os.path.isfile(set_file) and os.access(set_file,os.W_OK):
1140 try:
1141 os.remove(set_file)
1142 except OSError:
1143 return -2,_("Cannot remove the old element")
1144 if not os.access(os.path.dirname(set_file),os.W_OK):
1145 return -3,_("Cannot create the element")
1146
1147 f = open(set_file,"w")
1148 for x in set_atoms: f.write("%s\n" % (x,))
1149 f.flush()
1150 f.close()
1151 self.SystemSettings['system_package_sets'][set_name] = set(set_atoms)
1152 return 0,_("All fine")
1153
1155
1156 try:
1157 set_name = str(set_name)
1158 except (UnicodeEncodeError,UnicodeDecodeError,):
1159 raise InvalidPackageSet("InvalidPackageSet: %s %s" % (set_name,_("must be an ASCII string"),))
1160
1161 if set_name.startswith(etpConst['packagesetprefix']):
1162 raise InvalidPackageSet("InvalidPackageSet: %s %s '%s'" % (set_name,_("cannot start with"),etpConst['packagesetprefix'],))
1163
1164 set_match, rc = self.package_set_match(set_name)
1165 if not rc: return -1,_("Already removed")
1166 set_id, set_x, set_y = set_match
1167
1168 if set_id != etpConst['userpackagesetsid']:
1169 return -2,_("Not defined by user")
1170 set_file = os.path.join(etpConst['confsetsdir'],set_name)
1171 if os.path.isfile(set_file) and os.access(set_file,os.W_OK):
1172 os.remove(set_file)
1173 if set_name in self.SystemSettings['system_package_sets']:
1174 del self.SystemSettings['system_package_sets'][set_name]
1175 return 0,_("All fine")
1176 return -3,_("Set not found or unable to remove")
1177
1179 client_plugin_id = etpConst['system_settings_plugins_ids']['client_plugin']
1180 mask_installed = self.SystemSettings[client_plugin_id]['system_mask']['repos_installed']
1181 if idpackage in mask_installed:
1182 return True
1183 return False
1184
1186 return db_download_uri.split("/")[2]
1187
1192
1196
1198 if not install_queue:
1199 return {}
1200 licenses = {}
1201 cl_id = self.sys_settings_client_plugin_id
1202 repo_sys_data = self.SystemSettings[cl_id]['repositories']
1203
1204 for match in install_queue:
1205 repoid = match[1]
1206 dbconn = self.open_repository(repoid)
1207 wl = repo_sys_data['license_whitelist'].get(repoid)
1208 if not wl:
1209 continue
1210 keys = dbconn.retrieveLicensedataKeys(match[0])
1211 for key in keys:
1212 if key not in wl:
1213 found = self.clientDbconn.isLicenseAccepted(key)
1214 if found:
1215 continue
1216 if not licenses.has_key(key):
1217 licenses[key] = set()
1218 licenses[key].add(match)
1219 return licenses
1220
1221 - def get_text_license(self, license_name, repoid):
1222 dbconn = self.open_repository(repoid)
1223 text = dbconn.retrieveLicenseText(license_name)
1224 tempfile = self.entropyTools.get_random_temp_file()
1225 f = open(tempfile,"w")
1226 f.write(text)
1227 f.flush()
1228 f.close()
1229 return tempfile
1230
1232 """
1233 Set new Entropy branch. This is NOT thread-safe.
1234 Please note that if you call this method all your
1235 repository instance references will become invalid.
1236 This is caused by close_all_repositories and SystemSettings
1237 clear methods.
1238 Once you changed branch, the repository databases won't be
1239 available until you fetch them (through Repositories class)
1240
1241 @param branch -- new branch
1242 @type branch basestring
1243 @return None
1244 """
1245 self.Cacher.discard()
1246 self.Cacher.stop()
1247 self.purge_cache(showProgress = False)
1248 self.close_all_repositories()
1249
1250
1251 etpConst['branch'] = branch
1252 self.entropyTools.write_new_branch(branch)
1253 self.SystemSettings.clear()
1254
1255
1256 self.reopen_client_repository()
1257 self.clientDbconn.resetTreeupdatesDigests()
1258 self.close_all_repositories()
1259 if self.xcache:
1260 self.Cacher.start()
1261
1262 - def get_meant_packages(self, search_term, from_installed = False,
1263 valid_repos = []):
1264
1265 pkg_data = []
1266 atom_srch = False
1267 if "/" in search_term:
1268 atom_srch = True
1269
1270 if not valid_repos:
1271 valid_repos = self.validRepositories
1272 if from_installed:
1273 valid_repos = []
1274 if hasattr(self,'clientDbconn'):
1275 valid_repos.append(self.clientDbconn)
1276
1277 for repo in valid_repos:
1278 if isinstance(repo, basestring):
1279 dbconn = self.open_repository(repo)
1280 elif isinstance(repo, EntropyRepository):
1281 dbconn = repo
1282 else:
1283 continue
1284 pkg_data.extend([(x,repo,) for x in \
1285 dbconn.searchSimilarPackages(search_term, atom = atom_srch)])
1286
1287 return pkg_data
1288
1290 categories = set()
1291 for repo in self.validRepositories:
1292 dbconn = self.open_repository(repo)
1293 catsdata = dbconn.listAllCategories()
1294 categories.update(set([x[1] for x in catsdata]))
1295 return categories
1296
1298 pkg_matches = []
1299 for repo in self.validRepositories:
1300 dbconn = self.open_repository(repo)
1301 branch = self.SystemSettings['repositories']['branch']
1302 catsdata = dbconn.searchPackagesByCategory(category, branch = branch)
1303 pkg_matches.extend([(x[1],repo,) for x in catsdata if (x[1],repo,) not in pkg_matches])
1304 return pkg_matches
1305
1307
1308 data = {}
1309 for repo in self.validRepositories:
1310 try:
1311 dbconn = self.open_repository(repo)
1312 except RepositoryError:
1313 continue
1314 try:
1315 data = dbconn.retrieveCategoryDescription(category)
1316 except (self.dbapi2.OperationalError, self.dbapi2.IntegrityError,):
1317 continue
1318 if data: break
1319
1320 return data
1321
1325
1327
1328 idpackage, repoid = match
1329 dbconn = self.open_repository(repoid)
1330 cl_id = self.sys_settings_client_plugin_id
1331 misc_data = self.SystemSettings[cl_id]['misc']
1332 if mask:
1333 config_protect = set(dbconn.retrieveProtectMask(idpackage).split())
1334 config_protect |= set(misc_data['configprotectmask'])
1335 else:
1336 config_protect = set(dbconn.retrieveProtect(idpackage).split())
1337 config_protect |= set(misc_data['configprotect'])
1338 config_protect = [etpConst['systemroot']+x for x in config_protect]
1339
1340 return sorted(config_protect)
1341
1343
1344 if self.clientDbconn == None:
1345 return []
1346 cl_id = self.sys_settings_client_plugin_id
1347 misc_data = self.SystemSettings[cl_id]['misc']
1348 if mask:
1349 _pmask = self.clientDbconn.retrieveProtectMask(idpackage).split()
1350 config_protect = set(_pmask)
1351 config_protect |= set(misc_data['configprotectmask'])
1352 else:
1353 _protect = self.clientDbconn.retrieveProtect(idpackage).split()
1354 config_protect = set(_protect)
1355 config_protect |= set(misc_data['configprotect'])
1356 config_protect = [etpConst['systemroot']+x for x in config_protect]
1357
1358 return sorted(config_protect)
1359
1361
1362 if self.clientDbconn == None:
1363 return []
1364
1365
1366
1367 cl_id = self.sys_settings_client_plugin_id
1368 misc_data = self.SystemSettings[cl_id]['misc']
1369 if mask:
1370 _pmask = self.clientDbconn.listConfigProtectDirectories(mask = True)
1371 config_protect = set(_pmask)
1372 config_protect |= set(misc_data['configprotectmask'])
1373 else:
1374 _protect = self.clientDbconn.listConfigProtectDirectories()
1375 config_protect = set(_protect)
1376 config_protect |= set(misc_data['configprotect'])
1377 config_protect = [etpConst['systemroot']+x for x in config_protect]
1378
1379 return sorted(config_protect)
1380
1392
1398
1399 - def quickpkg(self, atomstring, savedir = None):
1400 if savedir == None:
1401 savedir = etpConst['packagestmpdir']
1402 if not os.path.isdir(etpConst['packagestmpdir']):
1403 os.makedirs(etpConst['packagestmpdir'])
1404
1405 match = self.clientDbconn.atomMatch(atomstring)
1406 if match[0] == -1:
1407 return -1,None,None
1408 atom = self.clientDbconn.atomMatch(match[0])
1409 pkgdata = self.clientDbconn.getPackageData(match[0])
1410 resultfile = self.quickpkg_handler(pkgdata = pkgdata, dirpath = savedir)
1411 if resultfile == None:
1412 return -1,atom,None
1413 else:
1414 return 0,atom,resultfile
1415
1416 - def quickpkg_handler(self, pkgdata, dirpath, edb = True,
1417 portdbPath = None, fake = False, compression = "bz2", shiftpath = ""):
1418
1419 import stat
1420 import tarfile
1421
1422 if compression not in ("bz2","","gz"):
1423 compression = "bz2"
1424
1425
1426 pkgtag = ''
1427 pkgrev = "~"+str(pkgdata['revision'])
1428 if pkgdata['versiontag']: pkgtag = "#"+pkgdata['versiontag']
1429 pkgname = pkgdata['name']+"-"+pkgdata['version']+pkgrev+pkgtag
1430 pkgcat = pkgdata['category']
1431
1432 dirpath += "/"+pkgname+etpConst['packagesext']
1433 if os.path.isfile(dirpath):
1434 os.remove(dirpath)
1435 tar = tarfile.open(dirpath,"w:"+compression)
1436
1437 if not fake:
1438
1439 contents = sorted([x for x in pkgdata['content']])
1440
1441
1442 for path in contents:
1443
1444 encoded_path = path
1445 path = path.encode('raw_unicode_escape')
1446 path = shiftpath+path
1447 try:
1448 exist = os.lstat(path)
1449 except OSError:
1450 continue
1451 arcname = path[len(shiftpath):]
1452 if arcname.startswith("/"):
1453 arcname = arcname[1:]
1454 ftype = pkgdata['content'][encoded_path]
1455 if str(ftype) == '0': ftype = 'dir'
1456 if 'dir' == ftype and \
1457 not stat.S_ISDIR(exist.st_mode) and \
1458 os.path.isdir(path):
1459 path = os.path.realpath(path)
1460
1461 tarinfo = tar.gettarinfo(path, arcname)
1462
1463 if stat.S_ISREG(exist.st_mode):
1464 tarinfo.mode = stat.S_IMODE(exist.st_mode)
1465 tarinfo.type = tarfile.REGTYPE
1466 f = open(path)
1467 try:
1468 tar.addfile(tarinfo, f)
1469 finally:
1470 f.close()
1471 else:
1472 tar.addfile(tarinfo)
1473
1474 tar.close()
1475
1476
1477 import entropy.xpak as xpak
1478 Spm = self.Spm()
1479
1480 gentoo_name = self.entropyTools.remove_tag(pkgname)
1481 gentoo_name = self.entropyTools.remove_entropy_revision(gentoo_name)
1482 if portdbPath == None:
1483 dbdir = Spm.get_vdb_path()+"/"+pkgcat+"/"+gentoo_name+"/"
1484 else:
1485 dbdir = portdbPath+"/"+pkgcat+"/"+gentoo_name+"/"
1486 if os.path.isdir(dbdir):
1487 tbz2 = xpak.tbz2(dirpath)
1488 tbz2.recompose(dbdir)
1489
1490 if edb:
1491 self.inject_entropy_database_into_package(dirpath, pkgdata)
1492
1493 if os.path.isfile(dirpath):
1494 return dirpath
1495 return None
1496
1497
1499
1501 """
1502 @input: matched atom (idpackage,repoid)
1503 @output:
1504 upgrade: int(2)
1505 install: int(1)
1506 reinstall: int(0)
1507 downgrade: int(-1)
1508 """
1509 dbconn = self.open_repository(match[1])
1510 pkgkey, pkgslot = dbconn.retrieveKeySlot(match[0])
1511 results = self.clientDbconn.searchKeySlot(pkgkey, pkgslot)
1512 if not results: return 1
1513
1514 installed_idpackage = results[0][0]
1515 pkgver, pkgtag, pkgrev = dbconn.getVersioningData(match[0])
1516 installedVer, installedTag, installedRev = self.clientDbconn.getVersioningData(installed_idpackage)
1517 pkgcmp = self.entropyTools.entropy_compare_versions((pkgver,pkgtag,pkgrev),(installedVer,installedTag,installedRev))
1518 if pkgcmp == 0:
1519 return 0
1520 elif pkgcmp > 0:
1521 return 2
1522 return -1
1523
1525 idpackage, repoid = match
1526 dbconn = self.open_repository(repoid)
1527 idpackage, idreason = dbconn.idpackageValidator(idpackage)
1528 masked = False
1529 if idpackage == -1: masked = True
1530 return masked, idreason, self.SystemSettings['pkg_masking_reasons'].get(idreason)
1531
1533 m_id, m_repo = match
1534 dbconn = self.open_repository(m_repo)
1535 conflicts = dbconn.retrieveConflicts(m_id)
1536 found_conflicts = set()
1537 for conflict in conflicts:
1538 my_m_id, my_m_rc = self.clientDbconn.atomMatch(conflict)
1539 if my_m_id != -1:
1540
1541 match_data = dbconn.retrieveKeySlot(m_id)
1542 installed_match_data = self.clientDbconn.retrieveKeySlot(my_m_id)
1543 if match_data != installed_match_data:
1544 found_conflicts.add(my_m_id)
1545 return found_conflicts
1546
1548 m_id, m_repo = match
1549 dbconn = self.open_repository(m_repo)
1550 idpackage, idreason = dbconn.idpackageValidator(m_id, live = live_check)
1551 if idpackage != -1:
1552 return False
1553 return True
1554
1556
1557 m_id, m_repo = match
1558 if m_repo not in self.validRepositories: return False
1559 dbconn = self.open_repository(m_repo)
1560 idpackage, idreason = dbconn.idpackageValidator(m_id, live = live_check)
1561 if idpackage != -1: return False
1562 myr = self.SystemSettings['pkg_masking_reference']
1563 user_masks = [myr['user_package_mask'],myr['user_license_mask'],myr['user_live_mask']]
1564 if idreason in user_masks:
1565 return True
1566 return False
1567
1569
1570 m_id, m_repo = match
1571 if m_repo not in self.validRepositories: return False
1572 dbconn = self.open_repository(m_repo)
1573 idpackage, idreason = dbconn.idpackageValidator(m_id, live = live_check)
1574 if idpackage == -1: return False
1575 myr = self.SystemSettings['pkg_masking_reference']
1576 user_masks = [
1577 myr['user_package_unmask'],myr['user_live_unmask'],myr['user_package_keywords'],
1578 myr['user_repo_package_keywords_all'], myr['user_repo_package_keywords']
1579 ]
1580 if idreason in user_masks:
1581 return True
1582 return False
1583
1584 - def mask_match(self, match, method = 'atom', dry_run = False, clean_all_cache = False):
1595
1596 - def unmask_match(self, match, method = 'atom', dry_run = False, clean_all_cache = False):
1607
1608 - def _mask_unmask_match(self, match, method, methods_reference, dry_run = False, clean_all_cache = False):
1635
1641
1647
1653
1659
1664
1669
1671 exist = False
1672 if not os.path.isfile(m_file):
1673 if not os.access(os.path.dirname(m_file),os.W_OK):
1674 return False
1675 elif not os.access(m_file, os.W_OK):
1676 return False
1677 elif not dry_run:
1678 exist = True
1679
1680 if dry_run:
1681 return True
1682
1683 content = []
1684 if exist:
1685 f = open(m_file,"r")
1686 content = [x.strip() for x in f.readlines()]
1687 f.close()
1688 content.append(keyword)
1689 m_file_tmp = m_file+".tmp"
1690 f = open(m_file_tmp,"w")
1691 for line in content:
1692 f.write(line+"\n")
1693 f.flush()
1694 f.close()
1695 shutil.move(m_file_tmp,m_file)
1696 return True
1697
1699 setting_data = self.SystemSettings.get_setting_files_data()
1700 masking_list = [setting_data['mask'],setting_data['unmask']]
1701 return self._clear_match_generic(match, masking_list = masking_list, dry_run = dry_run)
1702
1704
1705 self.SystemSettings['live_packagemasking']['unmask_matches'].discard(match)
1706 self.SystemSettings['live_packagemasking']['mask_matches'].discard(match)
1707
1708 if dry_run: return
1709
1710 for mask_file in masking_list:
1711 if not (os.path.isfile(mask_file) and os.access(mask_file,os.W_OK)): continue
1712 f = open(mask_file,"r")
1713 newf = self.entropyTools.open_buffer()
1714 line = f.readline()
1715 while line:
1716 line = line.strip()
1717 if line.startswith("#"):
1718 newf.write(line+"\n")
1719 line = f.readline()
1720 continue
1721 elif not line:
1722 newf.write("\n")
1723 line = f.readline()
1724 continue
1725 mymatch = self.atom_match(line, packagesFilter = False)
1726 if mymatch == match:
1727 line = f.readline()
1728 continue
1729 newf.write(line+"\n")
1730 line = f.readline()
1731 f.close()
1732 tmpfile = mask_file+".w_tmp"
1733 f = open(tmpfile,"w")
1734 f.write(newf.getvalue())
1735 f.flush()
1736 f.close()
1737 newf.close()
1738 shutil.move(tmpfile,mask_file)
1739