1
2
3 '''
4 # DESCRIPTION:
5 # Entropy Object Oriented Interface
6
7 Copyright (C) 2007-2009 Fabio Erculiani
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 '''
23 from __future__ import with_statement
24 import os
25 import subprocess
26 import time
27 import shutil
28 from entropy.const import *
29 from entropy.exceptions import *
30 from entropy.i18n import _
31 from entropy.output import TextInterface, brown, blue, bold, darkgreen, \
32 darkblue, red, purple, darkred, print_info, print_error, print_warning
33 from entropy.misc import TimeScheduled
34 from entropy.db import dbapi2, LocalRepository
35 from entropy.client.interfaces.client import Client
36 from entropy.cache import EntropyCacher
37
39
40 import entropy.tools as entropyTools
41 import entropy.dump as dumpTools
43
44 if not isinstance(EquoInstance,Client):
45 mytxt = _("A valid Client instance or subclass is needed")
46 raise IncorrectParameter("IncorrectParameter: %s" % (mytxt,))
47 self.Entropy = EquoInstance
48
49 self.Cacher = EntropyCacher()
50 self.infoDict = {}
51 self.prepared = False
52 self.matched_atom = ()
53 self.valid_actions = ("source","fetch","multi_fetch","remove",
54 "remove_conflict","install","config"
55 )
56 self.action = None
57 self.fetch_abort_function = None
58 self.xterm_title = ''
59
61 self.infoDict.clear()
62 self.matched_atom = ()
63 self.valid_actions = ()
64 self.action = None
65 self.prepared = False
66 self.fetch_abort_function = None
67
69 if self.prepared:
70 mytxt = _("Already prepared")
71 raise PermissionDenied("PermissionDenied: %s" % (mytxt,))
72
74 if not self.prepared:
75 mytxt = _("Not yet prepared")
76 raise PermissionDenied("PermissionDenied: %s" % (mytxt,))
77
79 if action not in self.valid_actions:
80 mytxt = _("Action must be in")
81 raise InvalidData("InvalidData: %s %s" % (mytxt,self.valid_actions,))
82
83 - def match_checksum(self, repository = None, checksum = None,
84 download = None, signatures = None):
85
86 self.error_on_not_prepared()
87
88 if repository == None:
89 repository = self.infoDict['repository']
90 if checksum == None:
91 checksum = self.infoDict['checksum']
92 if download == None:
93 download = self.infoDict['download']
94 if signatures == None:
95 signatures = self.infoDict['signatures']
96
97 def do_signatures_validation(signatures):
98
99 if isinstance(signatures,dict):
100 for hash_type in sorted(signatures):
101 hash_val = signatures[hash_type]
102
103
104 if hash_val in signatures:
105 continue
106 elif hash_val == None:
107 continue
108 elif not hasattr(self.entropyTools,
109 'compare_%s' % (hash_type,)):
110 continue
111
112 self.Entropy.updateProgress(
113 "%s: %s" % (blue(_("Checking package hash")),
114 purple(hash_type.upper()),),
115 importance = 0,
116 type = "info",
117 header = red(" ## "),
118 back = True
119 )
120 cmp_func = getattr(self.entropyTools,
121 'compare_%s' % (hash_type,))
122 mydownload = os.path.join(etpConst['entropyworkdir'],
123 download)
124 valid = cmp_func(mydownload, hash_val)
125 if not valid:
126 self.Entropy.updateProgress(
127 "%s: %s %s" % (
128 darkred(_("Package hash")),
129 purple(hash_type.upper()),
130 darkred(_("does not match the recorded one")),
131 ),
132 importance = 0,
133 type = "warning",
134 header = darkred(" ## ")
135 )
136 return 1
137 self.Entropy.updateProgress(
138 "%s %s" % (
139 purple(hash_type.upper()),
140 darkgreen(_("matches")),
141 ),
142 importance = 0,
143 type = "info",
144 header = " : "
145 )
146 return 0
147
148 dlcount = 0
149 match = False
150 while dlcount <= 5:
151
152 self.Entropy.updateProgress(
153 blue(_("Checking package checksum...")),
154 importance = 0,
155 type = "info",
156 header = red(" ## "),
157 back = True
158 )
159
160 dlcheck = self.Entropy.check_needed_package_download(download,
161 checksum = checksum)
162 if dlcheck == 0:
163 basef = os.path.basename(download)
164 self.Entropy.updateProgress(
165 "%s: %s" % (
166 blue(_("Package checksum matches")),
167 darkgreen(basef),
168 ),
169 importance = 0,
170 type = "info",
171 header = red(" ## ")
172 )
173
174 dlcheck = do_signatures_validation(signatures)
175 if dlcheck == 0:
176 self.infoDict['verified'] = True
177 match = True
178 break
179
180 if dlcheck != 0:
181 dlcount += 1
182 self.Entropy.updateProgress(
183 darkred(_("Package checksum does not match. Redownloading... attempt #%s") % (dlcount,)),
184 importance = 0,
185 type = "warning",
186 header = darkred(" ## ")
187 )
188 fetch = self.Entropy.fetch_file_on_mirrors(
189 repository,
190 self.Entropy.get_branch_from_download_relative_uri(download),
191 download,
192 checksum,
193 fetch_abort_function = self.fetch_abort_function
194 )
195 if fetch != 0:
196 self.Entropy.updateProgress(
197 blue(_("Cannot properly fetch package! Quitting.")),
198 importance = 0,
199 type = "error",
200 header = darkred(" ## ")
201 )
202 return fetch
203
204
205
206 continue
207
208 if not match:
209 mytxt = _("Cannot properly fetch package or checksum does not match. Try download latest repositories.")
210 self.Entropy.updateProgress(
211 blue(mytxt),
212 importance = 0,
213 type = "info",
214 header = red(" ## ")
215 )
216 return 1
217
218 return 0
219
226
228
229 if not self.infoDict['merge_from']:
230 self.Entropy.clientLog.log(ETP_LOGPRI_INFO,ETP_LOGLEVEL_NORMAL,"Unpacking package: "+str(self.infoDict['atom']))
231 else:
232 self.Entropy.clientLog.log(ETP_LOGPRI_INFO,ETP_LOGLEVEL_NORMAL,"Merging package: "+str(self.infoDict['atom']))
233
234 if os.path.isdir(self.infoDict['unpackdir']):
235 shutil.rmtree(self.infoDict['unpackdir'].encode('raw_unicode_escape'))
236 elif os.path.isfile(self.infoDict['unpackdir']):
237 os.remove(self.infoDict['unpackdir'].encode('raw_unicode_escape'))
238 os.makedirs(self.infoDict['imagedir'])
239
240 if not os.path.isfile(self.infoDict['pkgpath']) and not self.infoDict['merge_from']:
241 if os.path.isdir(self.infoDict['pkgpath']):
242 shutil.rmtree(self.infoDict['pkgpath'])
243 if os.path.islink(self.infoDict['pkgpath']):
244 os.remove(self.infoDict['pkgpath'])
245 self.infoDict['verified'] = False
246 rc = self.fetch_step()
247 if rc != 0:
248 return rc
249
250 if not self.infoDict['merge_from']:
251
252
253
254
255
256 pkg_dbdir = os.path.dirname(self.infoDict['pkgdbpath'])
257 if not os.path.isdir(pkg_dbdir):
258 os.makedirs(pkg_dbdir, 0755)
259
260 self.entropyTools.extract_edb(self.infoDict['pkgpath'],
261 self.infoDict['pkgdbpath'])
262
263 unpack_tries = 3
264 while 1:
265 unpack_tries -= 1
266 try:
267 rc = self.entropyTools.spawn_function(
268 self.entropyTools.uncompress_tar_bz2,
269 self.infoDict['pkgpath'],
270 self.infoDict['imagedir'],
271 catchEmpty = True
272 )
273 except EOFError:
274 self.Entropy.clientLog.log(
275 ETP_LOGPRI_INFO, ETP_LOGLEVEL_NORMAL,
276 "EOFError on " + self.infoDict['pkgpath']
277 )
278 rc = 1
279 except:
280
281
282 self.Entropy.clientLog.log(
283 ETP_LOGPRI_INFO,
284 ETP_LOGLEVEL_NORMAL,
285 "Raising Unicode/Pickling Error for " + \
286 self.infoDict['pkgpath']
287 )
288 rc = self.entropyTools.uncompress_tar_bz2(
289 self.infoDict['pkgpath'],self.infoDict['imagedir'],
290 catchEmpty = True
291 )
292 if rc == 0:
293 break
294 if unpack_tries <= 0:
295 return rc
296
297 self.infoDict['verified'] = False
298 f_rc = self.fetch_step()
299 if f_rc != 0:
300 return f_rc
301
302 else:
303
304 pid = os.fork()
305 if pid > 0:
306 os.waitpid(pid, 0)
307 else:
308 self.__fill_image_dir(self.infoDict['merge_from'],
309 self.infoDict['imagedir'])
310 os._exit(0)
311
312
313 if os.path.isdir(self.infoDict['xpakpath']):
314 shutil.rmtree(self.infoDict['xpakpath'])
315 try:
316 os.rmdir(self.infoDict['xpakpath'])
317 except OSError:
318 pass
319
320
321 os.makedirs(self.infoDict['xpakpath']+"/"+etpConst['entropyxpakdatarelativepath'],0755)
322
323 xpakPath = self.infoDict['xpakpath']+"/"+etpConst['entropyxpakfilename']
324
325 if not self.infoDict['merge_from']:
326 if (self.infoDict['smartpackage']):
327
328 xdbconn = self.Entropy.open_repository(self.infoDict['repository'])
329 xpakdata = xdbconn.retrieveXpakMetadata(self.infoDict['idpackage'])
330 if xpakdata:
331
332 f = open(xpakPath,"wb")
333 f.write(xpakdata)
334 f.flush()
335 f.close()
336 self.infoDict['xpakstatus'] = self.entropyTools.unpack_xpak(
337 xpakPath,
338 self.infoDict['xpakpath']+"/"+etpConst['entropyxpakdatarelativepath']
339 )
340 else:
341 self.infoDict['xpakstatus'] = None
342 del xpakdata
343 else:
344 self.infoDict['xpakstatus'] = self.entropyTools.extract_xpak(
345 self.infoDict['pkgpath'],
346 self.infoDict['xpakpath']+"/"+etpConst['entropyxpakdatarelativepath']
347 )
348 else:
349
350 tolink_dir = self.infoDict['xpakpath']+"/"+etpConst['entropyxpakdatarelativepath']
351 if os.path.isdir(tolink_dir):
352 shutil.rmtree(tolink_dir,True)
353
354 os.symlink(self.infoDict['xpakdir'],tolink_dir)
355
356
357 portage_db_fakedir = os.path.join(
358 self.infoDict['unpackdir'],
359 "portage/"+self.infoDict['category'] + "/" + self.infoDict['name'] + "-" + self.infoDict['version']
360 )
361
362 os.makedirs(portage_db_fakedir,0755)
363
364 os.symlink(self.infoDict['imagedir'],os.path.join(portage_db_fakedir,"image"))
365
366 return 0
367
423
424
426
427
428 self.__clear_cache()
429
430 self.Entropy.clientLog.log(ETP_LOGPRI_INFO,ETP_LOGLEVEL_NORMAL,"Removing package: %s" % (self.infoDict['removeatom'],))
431
432 protected_removable_config_files = {}
433
434 if self.infoDict['removeidpackage'] != -1:
435 mytxt = "%s: " % (_("Removing from Entropy"),)
436 self.Entropy.updateProgress(
437 blue(mytxt) + red(self.infoDict['removeatom']),
438 importance = 1,
439 type = "info",
440 header = red(" ## ")
441 )
442 protected_removable_config_files = self.Entropy.clientDbconn.retrieveAutomergefiles(
443 self.infoDict['removeidpackage'], get_dict = True
444 )
445 self.__remove_package_from_database()
446
447
448 spm_atom = self.entropyTools.remove_tag(self.infoDict['removeatom'])
449 self.Entropy.clientLog.log(ETP_LOGPRI_INFO,ETP_LOGLEVEL_NORMAL,"Removing from Spm: "+str(spm_atom))
450 self.__remove_package_from_spm_database(spm_atom)
451
452 self.__remove_content_from_system(protected_removable_config_files)
453 return 0
454
455 - def __remove_content_from_system(self, protected_removable_config_files):
456
457 sys_root = etpConst['systemroot']
458
459 sys_settings = self.Entropy.SystemSettings
460 protect = self.Entropy.get_installed_package_config_protect(
461 self.infoDict['idpackage'])
462 mask = self.Entropy.get_installed_package_config_protect(
463 self.infoDict['idpackage'], mask = True)
464 sys_set_plg_id = \
465 etpConst['system_settings_plugins_ids']['client_plugin']
466 col_protect = sys_settings[sys_set_plg_id]['misc']['collisionprotect']
467
468
469 directories = set()
470 not_removed_due_to_collisions = set()
471 remove_content = sorted(self.infoDict['removecontent'], reverse = True)
472 for item in remove_content:
473 sys_root_item = sys_root+item
474
475 if col_protect > 0:
476
477 if self.Entropy.clientDbconn.isFileAvailable(item) and os.path.isfile(sys_root_item):
478
479 mytxt = red(_("Collision found during removal of")) + " " + sys_root_item + " - "
480 mytxt += red(_("cannot overwrite"))
481 self.Entropy.updateProgress(
482 mytxt,
483 importance = 1,
484 type = "warning",
485 header = red(" ## ")
486 )
487 self.Entropy.clientLog.log(
488 ETP_LOGPRI_INFO,
489 ETP_LOGLEVEL_NORMAL,
490 "Collision found during remove of "+sys_root_item+" - cannot overwrite"
491 )
492 not_removed_due_to_collisions.add(item)
493 continue
494
495 protected = False
496 if (not self.infoDict['removeconfig']) and (not self.infoDict['diffremoval']):
497
498 protected_item_test = sys_root_item
499 if isinstance(protected_item_test,unicode):
500 protected_item_test = protected_item_test.encode('utf-8')
501
502 in_mask, protected, x, do_continue = self._handle_config_protect(
503 protect, mask, None, protected_item_test,
504 do_allocation_check = False, do_quiet = True)
505
506 if do_continue: protected = True
507
508
509
510
511 if in_mask:
512
513 oldprot_md5 = protected_removable_config_files.get(item)
514 if oldprot_md5 and os.path.exists(protected_item_test) and \
515 os.access(protected_item_test, os.R_OK):
516
517 in_system_md5 = self.entropyTools.md5sum(protected_item_test)
518 if oldprot_md5 == in_system_md5:
519 mytxt = "%s: %s" % (
520 darkgreen(_("Removing config file, never modified")),
521 blue(item),)
522 self.Entropy.updateProgress(
523 mytxt,
524 importance = 1,
525 type = "info",
526 header = red(" ## ")
527 )
528 protected = False
529 do_continue = False
530
531 if protected:
532 self.Entropy.clientLog.log(
533 ETP_LOGPRI_INFO,
534 ETP_LOGLEVEL_VERBOSE,
535 "[remove] Protecting config file: "+sys_root_item
536 )
537 mytxt = "[%s] %s: %s" % (
538 red(_("remove")),
539 brown(_("Protecting config file")),
540 sys_root_item,
541 )
542 self.Entropy.updateProgress(
543 mytxt,
544 importance = 1,
545 type = "warning",
546 header = red(" ## ")
547 )
548 else:
549 try:
550 os.lstat(sys_root_item)
551 except OSError:
552 continue
553 except UnicodeEncodeError:
554 mytxt = brown(_("This package contains a badly encoded file !!!"))
555 self.Entropy.updateProgress(
556 red("QA: ")+mytxt,
557 importance = 1,
558 type = "warning",
559 header = darkred(" ## ")
560 )
561 continue
562
563 if os.path.isdir(sys_root_item) and os.path.islink(sys_root_item):
564
565
566 directories.add((sys_root_item,"link"))
567 elif os.path.isdir(sys_root_item):
568
569 directories.add((sys_root_item,"dir"))
570 else:
571
572 try:
573 os.remove(sys_root_item)
574
575 dirfile = os.path.dirname(sys_root_item)
576 if os.path.isdir(dirfile) and os.path.islink(dirfile):
577 directories.add((dirfile,"link"))
578 elif os.path.isdir(dirfile):
579 directories.add((dirfile,"dir"))
580 except OSError:
581 pass
582
583
584
585
586
587
588
589 self.infoDict['removecontent'] -= not_removed_due_to_collisions
590
591
592 directories = sorted(directories, reverse = True)
593 while 1:
594 taint = False
595 for directory, dirtype in directories:
596 mydir = "%s%s" % (sys_root,directory,)
597 if dirtype == "link":
598 try:
599 mylist = os.listdir(mydir)
600 if not mylist:
601 try:
602 os.remove(mydir)
603 taint = True
604 except OSError:
605 pass
606 except OSError:
607 pass
608 elif dirtype == "dir":
609 try:
610 mylist = os.listdir(mydir)
611 if not mylist:
612 try:
613 os.rmdir(mydir)
614 taint = True
615 except OSError:
616 pass
617 except OSError:
618 pass
619
620 if not taint:
621 break
622 del directories
623
624
625 '''
626 @description: remove package entry from Spm database
627 @input spm package atom (cat/name+ver):
628 @output: 0 = all fine, <0 = error!
629 '''
631
632
633 try:
634 Spm = self.Entropy.Spm()
635 except:
636 return -1
637
638 portdb_dir = Spm.get_vdb_path()
639 remove_path = portdb_dir+atom
640 key = self.entropyTools.dep_getkey(atom)
641 others_installed = [x for x in Spm.search_keys(key) if \
642 self.entropyTools.dep_getkey(x) == key]
643 if atom in others_installed:
644 others_installed.remove(atom)
645 slot = self.infoDict['slot']
646 tag = self.infoDict['versiontag']
647 if (tag == slot) and tag: slot = "0"
648
649 def do_rm_path_atomic(xpath):
650 for my_el in os.listdir(xpath):
651 my_el = os.path.join(xpath, my_el)
652 try:
653 os.remove(my_el)
654 except OSError:
655 pass
656 try:
657 os.rmdir(xpath)
658 except OSError:
659 pass
660
661 if os.path.isdir(remove_path):
662 do_rm_path_atomic(remove_path)
663
664 if others_installed:
665
666 for myatom in others_installed:
667 myslot = Spm.get_installed_package_slot(myatom)
668 if myslot != slot:
669 continue
670 mydir = portdb_dir+myatom
671 if not os.path.isdir(mydir):
672 continue
673 do_rm_path_atomic(mydir)
674
675 else:
676
677 world_file = Spm.get_world_file()
678 world_file_tmp = world_file+".entropy.tmp"
679 if os.access(world_file,os.W_OK) and os.path.isfile(world_file):
680 new = open(world_file_tmp,"w")
681 old = open(world_file,"r")
682 line = old.readline()
683 while line:
684 if line.find(key) != -1:
685 line = old.readline()
686 continue
687 if line.find(key+":"+slot) != -1:
688 line = old.readline()
689 continue
690 new.write(line)
691 line = old.readline()
692 new.flush()
693 new.close()
694 old.close()
695 os.rename(world_file_tmp,world_file)
696
697 return 0
698
699 '''
700 @description: function that runs at the end of the package installation process, just removes data left by other steps
701 @output: 0 = all fine, >0 = error!
702 '''
704
705 shutil.rmtree(unpack_dir,True)
706 try: os.rmdir(unpack_dir)
707 except OSError: pass
708 return 0
709
711 self.error_on_not_prepared()
712 self.Entropy.clientDbconn.removePackage(self.infoDict['removeidpackage'],
713 do_commit = do_commit, do_cleanup = do_cleanup)
714 return 0
715
729
731
732
733 self.__clear_cache()
734
735 self.Entropy.clientLog.log(
736 ETP_LOGPRI_INFO,
737 ETP_LOGLEVEL_NORMAL,
738 "Installing package: %s" % (self.infoDict['atom'],)
739 )
740
741 already_protected_config_files = {}
742 if self.infoDict['removeidpackage'] != -1:
743 already_protected_config_files = self.Entropy.clientDbconn.retrieveAutomergefiles(
744 self.infoDict['removeidpackage'], get_dict = True
745 )
746
747
748
749 rc = self.__move_image_to_system(already_protected_config_files)
750 if rc != 0:
751 return rc
752 del already_protected_config_files
753
754
755 mytxt = "%s: %s" % (blue(_("Updating database")),red(self.infoDict['atom']),)
756 self.Entropy.updateProgress(
757 mytxt,
758 importance = 1,
759 type = "info",
760 header = red(" ## ")
761 )
762 newidpackage = self._install_package_into_database()
763
764
765 if self.infoDict['removeidpackage'] != -1:
766
767 self.Entropy.clientLog.log(
768 ETP_LOGPRI_INFO,
769 ETP_LOGLEVEL_NORMAL,
770 "Remove old package: %s" % (self.infoDict['removeatom'],)
771 )
772 self.infoDict['removeidpackage'] = -1
773
774 self.Entropy.clientLog.log(
775 ETP_LOGPRI_INFO,
776 ETP_LOGLEVEL_NORMAL,
777 "Removing Entropy and Spm database entry for %s" % (
778 self.infoDict['removeatom'],)
779 )
780
781 self.Entropy.updateProgress(
782 blue(_("Cleaning old package files...")),
783 importance = 1,
784 type = "info",
785 header = red(" ## ")
786 )
787 self.__remove_package()
788
789 self.Entropy.clientLog.log(
790 ETP_LOGPRI_INFO,
791 ETP_LOGLEVEL_NORMAL,
792 "Installing new Spm database entry: %s" % (self.infoDict['atom'],)
793 )
794 rc = self._install_package_into_spm_database(newidpackage)
795
796 return rc
797
798 '''
799 @description: inject the database information into the Gentoo database
800 @output: 0 = all fine, !=0 = error!
801 '''
803
804
805 try:
806 Spm = self.Entropy.Spm()
807 except:
808 return -1
809
810 portdb_dir = Spm.get_vdb_path()
811 if not os.path.isdir(portdb_dir):
812 os.makedirs(portdb_dir)
813
814 category = self.infoDict['category']
815 name = self.infoDict['name']
816 key = category + "/" + name
817
818 atomsfound = set()
819 dbdirs = os.listdir(portdb_dir)
820 if category in dbdirs:
821 catdirs = os.listdir(portdb_dir + "/" + category)
822 dirsfound = set([category + "/" + x for x in catdirs if \
823 key == self.entropyTools.dep_getkey(category + "/" + x)])
824 atomsfound.update(dirsfound)
825
826
827
828 if atomsfound:
829 pkg_to_remove = None
830 for atom in atomsfound:
831 atomslot = Spm.get_installed_package_slot(atom)
832
833 if atomslot == self.infoDict['slot']:
834 pkg_to_remove = atom
835 break
836 if pkg_to_remove:
837 remove_path = portdb_dir + pkg_to_remove
838 shutil.rmtree(remove_path, True)
839 try:
840 os.rmdir(remove_path)
841 except OSError:
842 pass
843 del atomsfound
844
845
846 xpak_rel_path = etpConst['entropyxpakdatarelativepath']
847 if ((self.infoDict['xpakstatus'] != None) and \
848 os.path.isdir( self.infoDict['xpakpath'] + "/" + xpak_rel_path)) or \
849 self.infoDict['merge_from']:
850
851 if self.infoDict['merge_from']:
852 copypath = self.infoDict['xpakdir']
853 if not os.path.isdir(copypath):
854 return 0
855 else:
856 copypath = self.infoDict['xpakpath'] + "/" + xpak_rel_path
857
858 if not os.path.isdir(portdb_dir + category):
859 os.makedirs(portdb_dir + category, 0755)
860 destination = portdb_dir + category + "/" + name + "-" + \
861 self.infoDict['version']
862
863 if os.path.isdir(destination):
864 shutil.rmtree(destination)
865
866 try:
867 shutil.copytree(copypath, destination)
868 except (IOError,), e:
869 mytxt = "%s: %s: %s: %s" % (red(_("QA")),
870 brown(_("Cannot update Portage database to destination")),
871 purple(destination),e,)
872 self.Entropy.updateProgress(
873 mytxt,
874 importance = 1,
875 type = "warning",
876 header = darkred(" ## ")
877 )
878
879
880 if os.path.isfile(etpConst['edbcounter']):
881 try:
882 f = open(etpConst['edbcounter'],"r")
883 counter = int(f.readline().strip())
884 f.close()
885 except:
886
887 counter = Spm.refill_counter()
888 else:
889 counter = Spm.refill_counter()
890
891
892 if os.path.isdir(destination):
893 counter += 1
894 f = open(destination+"/"+etpConst['spm']['xpak_entries']['counter'],"w")
895 f.write(str(counter))
896 f.flush()
897 f.close()
898 f = open(etpConst['edbcounter'],"w")
899 f.write(str(counter))
900 f.flush()
901 f.close()
902
903 self.Entropy.clientDbconn.insertCounter(newidpackage, counter)
904 else:
905 mytxt = brown(_("Cannot update Portage counter, destination %s does not exist.") % (destination,))
906 self.Entropy.updateProgress(
907 red("QA: ")+mytxt,
908 importance = 1,
909 type = "warning",
910 header = darkred(" ## ")
911 )
912
913 user_inst_source = etpConst['install_sources']['user']
914 if self.infoDict['install_source'] != user_inst_source:
915 self.Entropy.clientLog.log(
916 ETP_LOGPRI_INFO,
917 ETP_LOGLEVEL_NORMAL,
918 "Not updating Portage world file for: %s" % (self.infoDict['atom'],)
919 )
920
921 return 0
922
923
924
925
926 myslot = self.infoDict['slot']
927 if (self.infoDict['versiontag'] == self.infoDict['slot']) and self.infoDict['versiontag']:
928
929 myslot = "0"
930 keyslot = key+":"+myslot
931 world_file = Spm.get_world_file()
932 world_atoms = set()
933
934 if os.access(world_file,os.R_OK) and os.path.isfile(world_file):
935 f = open(world_file,"r")
936 world_atoms = set([x.strip() for x in f.readlines() if x.strip()])
937 f.close()
938 else:
939 mytxt = brown(_("Cannot update Portage world file, destination %s does not exist.") % (world_file,))
940 self.Entropy.updateProgress(
941 red("QA: ")+mytxt,
942 importance = 1,
943 type = "warning",
944 header = darkred(" ## ")
945 )
946 return 0
947
948 try:
949 if keyslot not in world_atoms and \
950 os.access(os.path.dirname(world_file),os.W_OK) and \
951 self.entropyTools.istextfile(world_file):
952 world_atoms.discard(key)
953 world_atoms.add(keyslot)
954 world_atoms = sorted(list(world_atoms))
955 world_file_tmp = world_file+".entropy_inst"
956 f = open(world_file_tmp,"w")
957 for item in world_atoms:
958 f.write(item+"\n")
959 f.flush()
960 f.close()
961 shutil.move(world_file_tmp,world_file)
962 except (UnicodeDecodeError,UnicodeEncodeError), e:
963 self.entropyTools.print_traceback(f = self.Entropy.clientLog)
964 mytxt = brown(_("Cannot update Portage world file, destination %s is corrupted.") % (world_file,))
965 self.Entropy.updateProgress(
966 red("QA: ")+mytxt+": "+unicode(e),
967 importance = 1,
968 type = "warning",
969 header = darkred(" ## ")
970 )
971
972 return 0
973
974 '''
975 @description: injects package info into the installed packages database
976 @output: 0 = all fine, >0 = error!
977 '''
979
980
981 smart_pkg = self.infoDict['smartpackage']
982 dbconn = self.Entropy.open_repository(self.infoDict['repository'])
983
984 if smart_pkg or self.infoDict['merge_from']:
985
986 data = dbconn.getPackageData(self.infoDict['idpackage'],
987 content_insert_formatted = True)
988
989 else:
990
991
992 data = dbconn.getPackageData(self.infoDict['idpackage'],
993 get_content = False)
994 pkg_dbconn = self.Entropy.open_generic_database(
995 self.infoDict['pkgdbpath'])
996
997
998 content = []
999 for pkg_idpackage in pkg_dbconn.listAllIdpackages():
1000 content += pkg_dbconn.retrieveContent(
1001 pkg_idpackage, extended = True,
1002 formatted = True, insert_formatted = True
1003 )
1004 real_idpk = self.infoDict['idpackage']
1005 content = [(real_idpk, x, y,) for orig_idpk, x, y in content]
1006 data['content'] = content
1007 pkg_dbconn.closeDB()
1008
1009
1010 trigger_content = set((x[1] for x in data['content']))
1011 self.infoDict['triggers']['install']['content'] = trigger_content
1012
1013
1014
1015
1016
1017 data['injected'] = False
1018
1019 data['counter'] = -1
1020
1021
1022 data['branch'] = self.Entropy.SystemSettings['repositories']['branch']
1023
1024 if data.get('needed_paths'):
1025 del data['needed_paths']
1026
1027 idpackage, rev, x = self.Entropy.clientDbconn.handlePackage(
1028 etpData = data, forcedRevision = data['revision'],
1029 formattedContent = True)
1030
1031
1032 ctime = self.entropyTools.get_current_unix_time()
1033 self.Entropy.clientDbconn.setDateCreation(idpackage, str(ctime))
1034
1035
1036 self.Entropy.clientDbconn.removePackageFromInstalledTable(idpackage)
1037 self.Entropy.clientDbconn.addPackageToInstalledTable(idpackage,
1038 self.infoDict['repository'], self.infoDict['install_source'])
1039
1040 automerge_data = self.infoDict.get('configprotect_data')
1041 if automerge_data:
1042 self.Entropy.clientDbconn.insertAutomergefiles(idpackage,
1043 automerge_data)
1044
1045
1046
1047 self.Entropy.clientDbconn.clearDependsTable()
1048 return idpackage
1049
1051
1052 dbconn = self.Entropy.open_repository(self.infoDict['repository'])
1053
1054
1055
1056 package_content = dbconn.retrieveContent(
1057 self.infoDict['idpackage'], extended = True, formatted = True)
1058 contents = sorted(package_content)
1059
1060
1061 for path in contents:
1062
1063 encoded_path = path
1064 path = os.path.join(mergeFrom,encoded_path[1:])
1065 topath = os.path.join(imageDir,encoded_path[1:])
1066 path = path.encode('raw_unicode_escape')
1067 topath = topath.encode('raw_unicode_escape')
1068
1069 try:
1070 exist = os.lstat(path)
1071 except OSError:
1072 continue
1073 ftype = package_content[encoded_path]
1074
1075 if 'dir' == ftype and \
1076 not stat.S_ISDIR(exist.st_mode) and \
1077 os.path.isdir(path):
1078
1079 path = os.path.realpath(path)
1080
1081 copystat = False
1082
1083 if os.path.islink(path):
1084 tolink = os.readlink(path)
1085 if os.path.islink(topath):
1086 os.remove(topath)
1087 os.symlink(tolink,topath)
1088 elif os.path.isdir(path):
1089 if not os.path.isdir(topath):
1090 os.makedirs(topath)
1091 copystat = True
1092 elif os.path.isfile(path):
1093 if os.path.isfile(topath):
1094 os.remove(topath)
1095 shutil.copy2(path,topath)
1096 copystat = True
1097
1098 if copystat:
1099 user = os.stat(path)[stat.ST_UID]
1100 group = os.stat(path)[stat.ST_GID]
1101 os.chown(topath,user,group)
1102 shutil.copystat(path,topath)
1103
1104
1106
1107
1108 repoid = self.infoDict['repository']
1109 protect = self.Entropy.get_package_match_config_protect(
1110 self.matched_atom)
1111 mask = self.Entropy.get_package_match_config_protect(
1112 self.matched_atom, mask = True)
1113 sys_root = etpConst['systemroot']
1114 sys_set_plg_id = \
1115 etpConst['system_settings_plugins_ids']['client_plugin']
1116 col_protect = self.Entropy.SystemSettings[sys_set_plg_id]['misc']['collisionprotect']
1117 items_installed = set()
1118
1119
1120 imageDir = self.infoDict['imagedir']
1121 encoded_imageDir = imageDir.encode('utf-8')
1122 movefile = self.entropyTools.movefile
1123
1124
1125 for currentdir,subdirs,files in os.walk(encoded_imageDir):
1126
1127 for subdir in subdirs:
1128
1129 imagepathDir = "%s/%s" % (currentdir,subdir,)
1130 rootdir = "%s%s" % (sys_root,imagepathDir[len(imageDir):],)
1131
1132
1133 if os.path.islink(rootdir) and not os.path.exists(rootdir):
1134 os.remove(rootdir)
1135
1136
1137 elif os.path.isfile(rootdir):
1138 self.Entropy.clientLog.log(
1139 ETP_LOGPRI_INFO,
1140 ETP_LOGLEVEL_NORMAL,
1141 "WARNING!!! %s is a file when it should be a directory !! Removing in 20 seconds..." % (rootdir,)
1142 )
1143 mytxt = darkred(_("%s is a file when should be a directory !! Removing in 20 seconds...") % (rootdir,))
1144 self.Entropy.updateProgress(
1145 red("QA: ")+mytxt,
1146 importance = 1,
1147 type = "warning",
1148 header = red(" !!! ")
1149 )
1150 self.entropyTools.ebeep(20)
1151 os.remove(rootdir)
1152
1153
1154 if os.path.islink(imagepathDir):
1155
1156
1157
1158 if (not os.path.islink(rootdir)) and os.path.isdir(rootdir):
1159 self.Entropy.clientLog.log(
1160 ETP_LOGPRI_INFO,
1161 ETP_LOGLEVEL_NORMAL,
1162 "WARNING!!! %s is a directory when it should be a symlink !! Removing in 20 seconds..." % (rootdir,)
1163 )
1164 mytxt = darkred(_("%s is a directory when should be a symlink !! Removing in 20 seconds...") % (rootdir,))
1165 self.Entropy.updateProgress(
1166 red("QA: ")+mytxt,
1167 importance = 1,
1168 type = "warning",
1169 header = red(" !!! ")
1170 )
1171 self.entropyTools.ebeep(20)
1172 shutil.rmtree(rootdir, True)
1173 os.rmdir(rootdir)
1174
1175 tolink = os.readlink(imagepathDir)
1176 live_tolink = None
1177 if os.path.islink(rootdir):
1178 live_tolink = os.readlink(rootdir)
1179 if tolink != live_tolink:
1180 if os.path.lexists(rootdir):
1181
1182 os.remove(rootdir)
1183 os.symlink(tolink, rootdir)
1184
1185 elif (not os.path.isdir(rootdir)) and (not os.access(rootdir,os.R_OK)):
1186 try:
1187
1188 os.mkdir(rootdir)
1189 except OSError:
1190 os.makedirs(rootdir)
1191
1192
1193 if not os.path.islink(rootdir) and os.access(rootdir,os.W_OK):
1194
1195
1196
1197 user = os.stat(imagepathDir)[stat.ST_UID]
1198 group = os.stat(imagepathDir)[stat.ST_GID]
1199 os.chown(rootdir,user,group)
1200 shutil.copystat(imagepathDir,rootdir)
1201
1202 items_installed.add(os.path.join(os.path.realpath(os.path.dirname(rootdir)),os.path.basename(rootdir)))
1203
1204 for item in files:
1205
1206 fromfile = "%s/%s" % (currentdir,item,)
1207 tofile = "%s%s" % (sys_root,fromfile[len(imageDir):],)
1208
1209 if col_protect > 1:
1210 todbfile = fromfile[len(imageDir):]
1211 myrc = self._handle_install_collision_protect(tofile, todbfile)
1212 if not myrc:
1213 continue
1214
1215 prot_old_tofile = tofile[len(sys_root):]
1216 pre_tofile = tofile[:]
1217 in_mask, protected, tofile, do_continue = self._handle_config_protect(
1218 protect, mask, fromfile, tofile)
1219
1220
1221 if in_mask and os.path.exists(fromfile):
1222 try:
1223 prot_md5 = self.entropyTools.md5sum(fromfile)
1224 self.infoDict['configprotect_data'].append(
1225 (prot_old_tofile,prot_md5,))
1226 except (IOError,):
1227 pass
1228
1229
1230 if protected:
1231
1232 try:
1233
1234
1235 oldprot_md5 = already_protected_config_files.get(
1236 prot_old_tofile)
1237
1238 if oldprot_md5 and os.path.exists(pre_tofile) and \
1239 os.access(pre_tofile, os.R_OK):
1240
1241 in_system_md5 = self.entropyTools.md5sum(pre_tofile)
1242 if oldprot_md5 == in_system_md5:
1243
1244
1245
1246 mytxt = "%s: %s" % (
1247 darkgreen(_("Automerging config file, never modified")),
1248 blue(pre_tofile),)
1249 self.Entropy.updateProgress(
1250 mytxt,
1251 importance = 1,
1252 type = "info",
1253 header = red(" ## ")
1254 )
1255 protected = False
1256 do_continue = False
1257 tofile = pre_tofile
1258
1259 except (IOError,):
1260 pass
1261
1262 if do_continue:
1263 continue
1264
1265 try:
1266
1267 if os.path.realpath(fromfile) == os.path.realpath(tofile) and os.path.islink(tofile):
1268
1269 try:
1270 os.remove(tofile)
1271 except OSError:
1272 pass
1273
1274
1275 if os.path.isdir(tofile) and not os.path.islink(tofile):
1276 self.Entropy.clientLog.log(
1277 ETP_LOGPRI_INFO,
1278 ETP_LOGLEVEL_NORMAL,
1279 "WARNING!!! %s is a directory when it should be a file !! Removing in 20 seconds..." % (tofile,)
1280 )
1281 mytxt = _("%s is a directory when it should be a file !! Removing in 20 seconds...") % (tofile,)
1282 self.Entropy.updateProgress(
1283 red("QA: ")+darkred(mytxt),
1284 importance = 1,
1285 type = "warning",
1286 header = red(" !!! ")
1287 )
1288 self.entropyTools.ebeep(10)
1289 time.sleep(20)
1290 try:
1291 shutil.rmtree(tofile, True)
1292 os.rmdir(tofile)
1293 except:
1294 pass
1295 try:
1296 os.remove(tofile)
1297 except OSError:
1298 pass
1299
1300
1301
1302
1303 done = movefile(fromfile, tofile, src_basedir = encoded_imageDir)
1304 if not done:
1305 self.Entropy.clientLog.log(
1306 ETP_LOGPRI_INFO,
1307 ETP_LOGLEVEL_NORMAL,
1308 "WARNING!!! Error during file move to system: %s => %s" % (fromfile,tofile,)
1309 )
1310 mytxt = "%s: %s => %s, %s" % (_("File move error"),fromfile,tofile,_("please report"),)
1311 self.Entropy.updateProgress(
1312 red("QA: ")+darkred(mytxt),
1313 importance = 1,
1314 type = "warning",
1315 header = red(" !!! ")
1316 )
1317 return 4
1318
1319 except IOError, e:
1320
1321
1322 if e.errno != 2: raise
1323
1324 items_installed.add(os.path.join(os.path.realpath(os.path.dirname(tofile)),os.path.basename(tofile)))
1325 if protected:
1326
1327 self.Entropy.FileUpdates.add_to_cache(tofile, quiet = True)
1328
1329
1330
1331
1332
1333 if self.infoDict.get('removecontent'):
1334 my_remove_content = set([x for x in self.infoDict['removecontent'] \
1335 if os.path.join(os.path.realpath(
1336 os.path.dirname("%s%s" % (sys_root,x,))),os.path.basename(x)
1337 ) in items_installed])
1338 self.infoDict['removecontent'] -= my_remove_content
1339
1340 return 0
1341
1342 - def _handle_config_protect(self, protect, mask, fromfile, tofile,
1343 do_allocation_check = True, do_quiet = False):
1344
1345 protected = False
1346 tofile_before_protect = tofile
1347 do_continue = False
1348 in_mask = False
1349
1350 try:
1351 encoded_protect = [x.encode('raw_unicode_escape') for x in protect]
1352 if tofile in encoded_protect:
1353 protected = True
1354 in_mask = True
1355 elif os.path.dirname(tofile) in encoded_protect:
1356 protected = True
1357 in_mask = True
1358 else:
1359 tofile_testdir = os.path.dirname(tofile)
1360 old_tofile_testdir = None
1361 while tofile_testdir != old_tofile_testdir:
1362 if tofile_testdir in encoded_protect:
1363 protected = True
1364 in_mask = True
1365 break
1366 old_tofile_testdir = tofile_testdir
1367 tofile_testdir = os.path.dirname(tofile_testdir)
1368
1369 if protected:
1370 newmask = [x.encode('raw_unicode_escape') for x in mask]
1371 if tofile in newmask:
1372 protected = False
1373 in_mask = False
1374 elif os.path.dirname(tofile) in newmask:
1375 protected = False
1376 in_mask = False
1377 else:
1378 tofile_testdir = os.path.dirname(tofile)
1379 old_tofile_testdir = None
1380 while tofile_testdir != old_tofile_testdir:
1381 if tofile_testdir in newmask:
1382 protected = False
1383 in_mask = False
1384 break
1385 old_tofile_testdir = tofile_testdir
1386 tofile_testdir = os.path.dirname(tofile_testdir)
1387
1388 if not os.path.lexists(tofile):
1389 protected = False
1390
1391
1392 if (protected) and os.path.isfile(tofile):
1393 protected = self.entropyTools.istextfile(tofile)
1394 in_mask = protected
1395 else:
1396 protected = False
1397
1398
1399 if protected:
1400 sys_set_plg_id = \
1401 etpConst['system_settings_plugins_ids']['client_plugin']
1402 client_settings = self.Entropy.SystemSettings[sys_set_plg_id]['misc']
1403 if tofile not in client_settings['configprotectskip']:
1404 prot_status = True
1405 if do_allocation_check:
1406 tofile, prot_status = self.entropyTools.allocate_masked_file(tofile, fromfile)
1407 if not prot_status:
1408 protected = False
1409 else:
1410 oldtofile = tofile
1411 if oldtofile.find("._cfg") != -1:
1412 oldtofile = os.path.join(os.path.dirname(oldtofile),
1413 os.path.basename(oldtofile)[10:])
1414 if not do_quiet:
1415 self.Entropy.clientLog.log(
1416 ETP_LOGPRI_INFO,
1417 ETP_LOGLEVEL_NORMAL,
1418 "Protecting config file: %s" % (oldtofile,)
1419 )
1420 mytxt = red("%s: %s") % (_("Protecting config file"),oldtofile,)
1421 self.Entropy.updateProgress(
1422 mytxt,
1423 importance = 1,
1424 type = "warning",
1425 header = darkred(" ## ")
1426 )
1427 else:
1428 if not do_quiet:
1429 self.Entropy.clientLog.log(
1430 ETP_LOGPRI_INFO,
1431 ETP_LOGLEVEL_NORMAL,
1432 "Skipping config file installation/removal, as stated in client.conf: %s" % (tofile,)
1433 )
1434 mytxt = "%s: %s" % (_("Skipping file installation/removal"),tofile,)
1435 self.Entropy.updateProgress(
1436 mytxt,
1437 importance = 1,
1438 type = "warning",
1439 header = darkred(" ## ")
1440 )
1441 do_continue = True
1442
1443 except Exception, e:
1444 self.entropyTools.print_traceback()
1445 protected = False
1446 tofile = tofile_before_protect
1447 mytxt = darkred("%s: %s") % (_("Cannot check CONFIG PROTECTION. Error"),e,)
1448 self.Entropy.updateProgress(
1449 red("QA: ")+mytxt,
1450 importance = 1,
1451 type = "warning",
1452 header = darkred(" ## ")
1453 )
1454
1455 return in_mask, protected, tofile, do_continue
1456
1457
1459 avail = self.Entropy.clientDbconn.isFileAvailable(todbfile, get_id = True)
1460 if (self.infoDict['removeidpackage'] not in avail) and avail:
1461 mytxt = darkred(_("Collision found during install for"))
1462 mytxt += " %s - %s" % (blue(tofile),darkred(_("cannot overwrite")),)
1463 self.Entropy.updateProgress(
1464 red("QA: ")+mytxt,
1465 importance = 1,
1466 type = "warning",
1467 header = darkred(" ## ")
1468 )
1469 self.Entropy.clientLog.log(
1470 ETP_LOGPRI_INFO,
1471 ETP_LOGLEVEL_NORMAL,
1472 "WARNING!!! Collision found during install for %s - cannot overwrite" % (tofile,)
1473 )
1474 return False
1475 return True
1476
1478 self.error_on_not_prepared()
1479 down_data = self.infoDict['download']
1480 down_keys = down_data.keys()
1481 d_cache = set()
1482 rc = 0
1483 key_cache = [os.path.basename(x) for x in down_keys]
1484 for key in sorted(down_keys):
1485 key_name = os.path.basename(key)
1486 if key_name in d_cache: continue
1487
1488 for url in down_data[key]:
1489 file_name = os.path.basename(url)
1490 if self.infoDict.get('fetch_path'):
1491 dest_file = os.path.join(self.infoDict['fetch_path'],
1492 file_name)
1493 else:
1494 dest_file = os.path.join(self.infoDict['unpackdir'],
1495 file_name)
1496 rc = self._fetch_source(url, dest_file)
1497 if rc == 0:
1498 d_cache.add(key_name)
1499 break
1500 key_cache.remove(key_name)
1501 if rc != 0 and key_name not in key_cache:
1502 break
1503 rc = 0
1504
1505 return rc
1506
1508 rc = 1
1509 try:
1510 mytxt = "%s: %s" % (blue(_("Downloading")),brown(url),)
1511
1512 self.Entropy.updateProgress(
1513 mytxt,
1514 importance = 1,
1515 type = "info",
1516 header = red(" ## ")
1517 )
1518
1519 rc, data_transfer, resumed = self.Entropy.fetch_file(
1520 url,
1521 None,
1522 None,
1523 False,
1524 fetch_file_abort_function = self.fetch_abort_function,
1525 filepath = dest_file
1526 )
1527 if rc == 0:
1528 mytxt = blue("%s: ") % (_("Successfully downloaded from"),)
1529 mytxt += red(self.entropyTools.spliturl(url)[1])
1530 mytxt += " %s %s/%s" % (_("at"),self.entropyTools.bytes_into_human(data_transfer),_("second"),)
1531 self.Entropy.updateProgress(
1532 mytxt,
1533 importance = 1,
1534 type = "info",
1535 header = red(" ## ")
1536 )
1537 self.Entropy.updateProgress(
1538 "%s: %s" % (blue(_("Local path")),brown(dest_file),),
1539 importance = 1,
1540 type = "info",
1541 header = red(" # ")
1542 )
1543 else:
1544 error_message = blue("%s: %s") % (
1545 _("Error downloading from"),
1546 red(self.entropyTools.spliturl(url)[1]),
1547 )
1548
1549 if rc == -1:
1550 error_message += " - %s." % (_("file not available on this mirror"),)
1551 elif rc == -3:
1552 error_message += " - not found."
1553 elif rc == -100:
1554 error_message += " - %s." % (_("discarded download"),)
1555 else:
1556 error_message += " - %s: %s" % (_("unknown reason"),rc,)
1557 self.Entropy.updateProgress(
1558 error_message,
1559 importance = 1,
1560 type = "warning",
1561 header = red(" ## ")
1562 )
1563 except KeyboardInterrupt:
1564 pass
1565 return rc
1566
1568 self.error_on_not_prepared()
1569 mytxt = "%s: %s" % (blue(_("Downloading archive")),
1570 red(os.path.basename(self.infoDict['download'])),)
1571 self.Entropy.updateProgress(
1572 mytxt,
1573 importance = 1,
1574 type = "info",
1575 header = red(" ## ")
1576 )
1577
1578 rc = 0
1579 if not self.infoDict['verified']:
1580 rc = self.Entropy.fetch_file_on_mirrors(
1581 self.infoDict['repository'],
1582 self.Entropy.get_branch_from_download_relative_uri(self.infoDict['download']),
1583 self.infoDict['download'],
1584 self.infoDict['checksum'],
1585 fetch_abort_function = self.fetch_abort_function
1586 )
1587 if rc != 0:
1588 mytxt = "%s. %s: %s" % (
1589 red(_("Package cannot be fetched. Try to update repositories and retry")),
1590 blue(_("Error")),
1591 rc,
1592 )
1593 self.Entropy.updateProgress(
1594 mytxt,
1595 importance = 1,
1596 type = "error",
1597 header = darkred(" ## ")
1598 )
1599 return rc
1600
1602 self.error_on_not_prepared()
1603 m_fetch_len = len(self.infoDict['multi_fetch_list'])
1604 mytxt = "%s: %s %s" % (blue(_("Downloading")),darkred(str(m_fetch_len)),_("archives"),)
1605 self.Entropy.updateProgress(
1606 mytxt,
1607 importance = 1,
1608 type = "info",
1609 header = red(" ## ")
1610 )
1611
1612 rc, err_list = self.Entropy.fetch_files_on_mirrors(
1613 self.infoDict['multi_fetch_list'],
1614 self.infoDict['checksum'],
1615 fetch_abort_function = self.fetch_abort_function
1616 )
1617 if rc != 0:
1618 mytxt = "%s. %s: %s" % (
1619 red(_("Some packages cannot be fetched. Try to update repositories and retry")),
1620 blue(_("Error")),
1621 rc,
1622 )
1623 self.Entropy.updateProgress(
1624 mytxt,
1625 importance = 1,
1626 type = "error",
1627 header = darkred(" ## ")
1628 )
1629 for repo, branch, fname, cksum, signatures in err_list:
1630 self.Entropy.updateProgress(
1631 "[%s:%s|%s] %s" % (blue(repo),brown(branch),
1632 darkgreen(cksum),darkred(fname),),
1633 importance = 1,
1634 type = "error",
1635 header = darkred(" # ")
1636 )
1637 return rc
1638
1640 self.Entropy.updateProgress(
1641 blue(_("Fetch for the chosen package is not available, unknown error.")),
1642 importance = 1,
1643 type = "info",
1644 header = red(" ## ")
1645 )
1646 return 0
1647
1649 self.Entropy.updateProgress(
1650 blue(_("Installed package in queue vanished, skipping.")),
1651 importance = 1,
1652 type = "info",
1653 header = red(" ## ")
1654 )
1655 return 0
1656
1660
1664
1666 self.error_on_not_prepared()
1667
1668 if not self.infoDict['merge_from']:
1669 mytxt = "%s: %s" % (blue(_("Unpacking package")),red(os.path.basename(self.infoDict['download'])),)
1670 self.Entropy.updateProgress(
1671 mytxt,
1672 importance = 1,
1673 type = "info",
1674 header = red(" ## ")
1675 )
1676 else:
1677 mytxt = "%s: %s" % (blue(_("Merging package")),red(os.path.basename(self.infoDict['atom'])),)
1678 self.Entropy.updateProgress(
1679 mytxt,
1680 importance = 1,
1681 type = "info",
1682 header = red(" ## ")
1683 )
1684 rc = self.__unpack_package()
1685 if rc != 0:
1686 if rc == 512:
1687 errormsg = "%s. %s. %s: 512" % (
1688 red(_("You are running out of disk space")),
1689 red(_("I bet, you're probably Michele")),
1690 blue(_("Error")),
1691 )
1692 else:
1693 errormsg = "%s. %s. %s: %s" % (
1694 red(_("An error occured while trying to unpack the package")),
1695 red(_("Check if your system is healthy")),
1696 blue(_("Error")),
1697 rc,
1698 )
1699 self.Entropy.updateProgress(
1700 errormsg,
1701 importance = 1,
1702 type = "error",
1703 header = red(" ## ")
1704 )
1705 return rc
1706
1708 self.error_on_not_prepared()
1709 mytxt = "%s: %s" % (blue(_("Installing package")),red(self.infoDict['atom']),)
1710 self.Entropy.updateProgress(
1711 mytxt,
1712 importance = 1,
1713 type = "info",
1714 header = red(" ## ")
1715 )
1716 rc = self.__install_package()
1717 if rc != 0:
1718 mytxt = "%s. %s. %s: %s" % (
1719 red(_("An error occured while trying to install the package")),
1720 red(_("Check if your system is healthy")),
1721 blue(_("Error")),
1722 rc,
1723 )
1724 self.Entropy.updateProgress(
1725 mytxt,
1726 importance = 1,
1727 type = "error",
1728 header = red(" ## ")
1729 )
1730 return rc
1731
1733 self.error_on_not_prepared()
1734 mytxt = "%s: %s" % (blue(_("Removing data")),red(self.infoDict['removeatom']),)
1735 self.Entropy.updateProgress(
1736 mytxt,
1737 importance = 1,
1738 type = "info",
1739 header = red(" ## ")
1740 )
1741 rc = self.__remove_package()
1742 if rc != 0:
1743 mytxt = "%s. %s. %s: %s" % (
1744 red(_("An error occured while trying to remove the package")),
1745 red(_("Check if you have enough disk space on your hard disk")),
1746 blue(_("Error")),
1747 rc,
1748 )
1749 self.Entropy.updateProgress(
1750 mytxt,
1751 importance = 1,
1752 type = "error",
1753 header = red(" ## ")
1754 )
1755 return rc
1756
1758 self.error_on_not_prepared()
1759 mytxt = "%s: %s" % (blue(_("Cleaning")),red(self.infoDict['atom']),)
1760 self.Entropy.updateProgress(
1761 mytxt,
1762 importance = 1,
1763 type = "info",
1764 header = red(" ## ")
1765 )
1766 self._cleanup_package(self.infoDict['unpackdir'])
1767
1768 return 0
1769
1771 for msg in self.infoDict['messages']:
1772 self.Entropy.clientLog.write(">>> "+msg)
1773 return 0
1774
1775 - def postinstall_step(self):
1776 self.error_on_not_prepared()
1777 pkgdata = self.infoDict['triggers'].get('install')
1778 if pkgdata:
1779 trigger = self.Entropy.Triggers('postinstall',pkgdata, self.action)
1780 do = trigger.prepare()
1781 if do:
1782 trigger.run()
1783 trigger.kill()
1784 del pkgdata
1785 return 0
1786
1788 self.error_on_not_prepared()
1789 pkgdata = self.infoDict['triggers'].get('install')
1790 if pkgdata:
1791
1792 trigger = self.Entropy.Triggers('preinstall',pkgdata, self.action)
1793 do = trigger.prepare()
1794 if self.infoDict.get("diffremoval") and do:
1795
1796
1797 remdata = self.infoDict['triggers'].get('remove')
1798 if remdata:
1799 r_trigger = self.Entropy.Triggers('preremove',remdata, self.action)
1800 r_trigger.prepare()
1801 r_trigger.triggers = [x for x in trigger.triggers if x not in r_trigger.triggers]
1802 r_trigger.kill()
1803 del remdata
1804 if do:
1805 trigger.run()
1806 trigger.kill()
1807
1808 del pkgdata
1809 return 0
1810
1822
1823 - def postremove_step(self):
1824 self.error_on_not_prepared()
1825 remdata = self.infoDict['triggers'].get('remove')
1826 if remdata:
1827
1828 trigger = self.Entropy.Triggers('postremove',remdata, self.action)
1829 do = trigger.prepare()
1830 if self.infoDict['diffremoval'] and (self.infoDict.get("atom") != None) and do:
1831
1832 pkgdata = self.infoDict['triggers'].get('install')
1833 if pkgdata:
1834 i_trigger = self.Entropy.Triggers('postinstall',pkgdata, self.action)
1835 i_trigger.prepare()
1836 i_trigger.triggers = [x for x in trigger.triggers if x not in i_trigger.triggers]
1837 i_trigger.kill()
1838 del pkgdata
1839 if do:
1840 trigger.run()
1841 trigger.kill()
1842
1843 del remdata
1844 return 0
1845
1847 self.error_on_not_prepared()
1848 for idpackage in self.infoDict['conflicts']:
1849 if not self.Entropy.clientDbconn.isIDPackageAvailable(idpackage):
1850 continue
1851 pkg = self.Entropy.Package()
1852 pkg.prepare((idpackage,),"remove_conflict", self.infoDict['remove_metaopts'])
1853 rc = pkg.run(xterm_header = self.xterm_title)
1854 pkg.kill()
1855 if rc != 0:
1856 return rc
1857
1858 return 0
1859
1861 self.error_on_not_prepared()
1862 mytxt = "%s: %s" % (blue(_("Configuring package")),red(self.infoDict['atom']),)
1863 self.Entropy.updateProgress(
1864 mytxt,
1865 importance = 1,
1866 type = "info",
1867 header = red(" ## ")
1868 )
1869 rc = self.__configure_package()
1870 if rc == 1:
1871 mytxt = "%s. %s. %s: %s" % (
1872 red(_("An error occured while trying to configure the package")),
1873 red(_("Make sure that your system is healthy")),
1874 blue(_("Error")),
1875 rc,
1876 )
1877 self.Entropy.updateProgress(
1878 mytxt,
1879 importance = 1,
1880 type = "error",
1881 header = red(" ## ")
1882 )
1883 elif rc == 2:
1884 mytxt = "%s. %s. %s: %s" % (
1885 red(_("An error occured while trying to configure the package")),
1886 red(_("It seems that the Source Package Manager entry is missing")),
1887 blue(_("Error")),
1888 rc,
1889 )
1890 self.Entropy.updateProgress(
1891 mytxt,
1892 importance = 1,
1893 type = "error",
1894 header = red(" ## ")
1895 )
1896 return rc
1897
1899 if xterm_header == None:
1900 xterm_header = ""
1901
1902 if self.infoDict.has_key('remove_installed_vanished'):
1903 self.xterm_title += ' Installed package vanished'
1904 self.Entropy.setTitle(self.xterm_title)
1905 rc = self.vanished_step()
1906 return rc
1907
1908 if self.infoDict.has_key('fetch_not_available'):
1909 self.xterm_title += ' Fetch not available'
1910 self.Entropy.setTitle(self.xterm_title)
1911 rc = self.fetch_not_available_step()
1912 return rc
1913
1914 def do_fetch():
1915 self.xterm_title += ' %s: %s' % (_("Fetching"),os.path.basename(self.infoDict['download']),)
1916 self.Entropy.setTitle(self.xterm_title)
1917 return self.fetch_step()
1918
1919 def do_multi_fetch():
1920 self.xterm_title += ' %s: %s %s' % (_("Multi Fetching"),
1921 len(self.infoDict['multi_fetch_list']),_("packages"),)
1922 self.Entropy.setTitle(self.xterm_title)
1923 return self.multi_fetch_step()
1924
1925 def do_sources_fetch():
1926 self.xterm_title += ' %s: %s' % (_("Fetching sources"),os.path.basename(self.infoDict['atom']),)
1927 self.Entropy.setTitle(self.xterm_title)
1928 return self.sources_fetch_step()
1929
1930 def do_checksum():
1931 self.xterm_title += ' %s: %s' % (_("Verifying"),os.path.basename(self.infoDict['download']),)
1932 self.Entropy.setTitle(self.xterm_title)
1933 return self.checksum_step()
1934
1935 def do_multi_checksum():
1936 self.xterm_title += ' %s: %s %s' % (_("Multi Verification"),
1937 len(self.infoDict['multi_checksum_list']),_("packages"),)
1938 self.Entropy.setTitle(self.xterm_title)
1939 return self.multi_checksum_step()
1940
1941 def do_unpack():
1942 if not self.infoDict['merge_from']:
1943 mytxt = _("Unpacking")
1944 self.xterm_title += ' %s: %s' % (mytxt,os.path.basename(self.infoDict['download']),)
1945 else:
1946 mytxt = _("Merging")
1947 self.xterm_title += ' %s: %s' % (mytxt,os.path.basename(self.infoDict['atom']),)
1948 self.Entropy.setTitle(self.xterm_title)
1949 return self.unpack_step()
1950
1951 def do_remove_conflicts():
1952 return self.removeconflict_step()
1953
1954 def do_install():
1955 self.xterm_title += ' %s: %s' % (_("Installing"),self.infoDict['atom'],)
1956 self.Entropy.setTitle(self.xterm_title)
1957 return self.install_step()
1958
1959 def do_remove():
1960 self.xterm_title += ' %s: %s' % (_("Removing"),self.infoDict['removeatom'],)
1961 self.Entropy.setTitle(self.xterm_title)
1962 return self.remove_step()
1963
1964 def do_logmessages():
1965 return self.logmessages_step()
1966
1967 def do_cleanup():
1968 self.xterm_title += ' %s: %s' % (_("Cleaning"),self.infoDict['atom'],)
1969 self.Entropy.setTitle(self.xterm_title)
1970 return self.cleanup_step()
1971
1972 def do_postinstall():
1973 self.xterm_title += ' %s: %s' % (_("Postinstall"),self.infoDict['atom'],)
1974 self.Entropy.setTitle(self.xterm_title)
1975 return self.postinstall_step()
1976
1977 def do_preinstall():
1978 self.xterm_title += ' %s: %s' % (_("Preinstall"),self.infoDict['atom'],)
1979 self.Entropy.setTitle(self.xterm_title)
1980 return self.preinstall_step()
1981
1982 def do_preremove():
1983 self.xterm_title += ' %s: %s' % (_("Preremove"),self.infoDict['removeatom'],)
1984 self.Entropy.setTitle(self.xterm_title)
1985 return self.preremove_step()
1986
1987 def do_postremove():
1988 self.xterm_title += ' %s: %s' % (_("Postremove"),self.infoDict['removeatom'],)
1989 self.Entropy.setTitle(self.xterm_title)
1990 return self.postremove_step()
1991
1992 def do_config():
1993 self.xterm_title += ' %s: %s' % (_("Configuring"),self.infoDict['atom'],)
1994 self.Entropy.setTitle(self.xterm_title)
1995 return self.config_step()
1996
1997 steps_data = {
1998 "fetch": do_fetch,
1999 "multi_fetch": do_multi_fetch,
2000 "multi_checksum": do_multi_checksum,
2001 "sources_fetch": do_sources_fetch,
2002 "checksum": do_checksum,
2003 "unpack": do_unpack,
2004 "remove_conflicts": do_remove_conflicts,
2005 "install": do_install,
2006 "remove": do_remove,
2007 "logmessages": do_logmessages,
2008 "cleanup": do_cleanup,
2009 "postinstall": do_postinstall,
2010 "preinstall": do_preinstall,
2011 "postremove": do_postremove,
2012 "preremove": do_preremove,
2013 "config": do_config,
2014 }
2015
2016 rc = 0
2017 for step in self.infoDict['steps']:
2018 self.xterm_title = xterm_header
2019 rc = steps_data.get(step)()
2020 if rc != 0: break
2021 return rc
2022
2023
2024 '''
2025 @description: execute the requested steps
2026 @input xterm_header: purely optional
2027 '''
2028 - def run(self, xterm_header = None):
2060
2061 '''
2062 Install/Removal process preparation function
2063 - will generate all the metadata needed to run the action steps, creating infoDict automatically
2064 @input matched_atom(tuple): is what is returned by EquoInstance.atom_match:
2065 (idpackage,repoid):
2066 (2000,u'sabayonlinux.org')
2067 NOTE: in case of remove action, matched_atom must be:
2068 (idpackage,)
2069 NOTE: in case of multi_fetch, matched_atom can be a list of matches
2070 @input action(string): is an action to take, which must be one in self.valid_actions
2071 '''
2072 - def prepare(self, matched_atom, action, metaopts = {}):
2082
2100
2130
2143
2292
2364
2431