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