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, EntropyRepository
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
424
425
427
428
429 self.__clear_cache()
430
431 self.Entropy.clientLog.log(ETP_LOGPRI_INFO,ETP_LOGLEVEL_NORMAL,"Removing package: %s" % (self.infoDict['removeatom'],))
432
433 protected_removable_config_files = {}
434
435 if self.infoDict['removeidpackage'] != -1:
436 mytxt = "%s: " % (_("Removing from Entropy"),)
437 self.Entropy.updateProgress(
438 blue(mytxt) + red(self.infoDict['removeatom']),
439 importance = 1,
440 type = "info",
441 header = red(" ## ")
442 )
443 protected_removable_config_files = self.Entropy.clientDbconn.retrieveAutomergefiles(
444 self.infoDict['removeidpackage'], get_dict = True
445 )
446 self.__remove_package_from_database()
447
448
449 spm_atom = self.entropyTools.remove_tag(self.infoDict['removeatom'])
450 self.Entropy.clientLog.log(ETP_LOGPRI_INFO,ETP_LOGLEVEL_NORMAL,"Removing from Spm: "+str(spm_atom))
451 self.__remove_package_from_spm_database(spm_atom)
452
453 self.__remove_content_from_system(protected_removable_config_files)
454 return 0
455
456 - def __remove_content_from_system(self, protected_removable_config_files):
457
458 sys_root = etpConst['systemroot']
459
460 sys_settings = self.Entropy.SystemSettings
461 protect = self.Entropy.get_installed_package_config_protect(
462 self.infoDict['idpackage'])
463 mask = self.Entropy.get_installed_package_config_protect(
464 self.infoDict['idpackage'], mask = True)
465 sys_set_plg_id = \
466 etpConst['system_settings_plugins_ids']['client_plugin']
467 col_protect = sys_settings[sys_set_plg_id]['misc']['collisionprotect']
468
469
470 directories = set()
471 not_removed_due_to_collisions = set()
472 remove_content = sorted(self.infoDict['removecontent'], reverse = True)
473 for item in remove_content:
474 sys_root_item = sys_root+item
475
476 if col_protect > 0:
477
478 if self.Entropy.clientDbconn.isFileAvailable(item) and os.path.isfile(sys_root_item):
479
480 mytxt = red(_("Collision found during removal of")) + " " + sys_root_item + " - "
481 mytxt += red(_("cannot overwrite"))
482 self.Entropy.updateProgress(
483 mytxt,
484 importance = 1,
485 type = "warning",
486 header = red(" ## ")
487 )
488 self.Entropy.clientLog.log(
489 ETP_LOGPRI_INFO,
490 ETP_LOGLEVEL_NORMAL,
491 "Collision found during remove of "+sys_root_item+" - cannot overwrite"
492 )
493 not_removed_due_to_collisions.add(item)
494 continue
495
496 protected = False
497 if (not self.infoDict['removeconfig']) and (not self.infoDict['diffremoval']):
498
499 protected_item_test = sys_root_item
500 if isinstance(protected_item_test,unicode):
501 protected_item_test = protected_item_test.encode('utf-8')
502
503 in_mask, protected, x, do_continue = self._handle_config_protect(
504 protect, mask, None, protected_item_test,
505 do_allocation_check = False, do_quiet = True)
506
507 if do_continue: protected = True
508
509
510
511
512 if in_mask:
513
514 oldprot_md5 = protected_removable_config_files.get(item)
515 if oldprot_md5 and os.path.exists(protected_item_test) and \
516 os.access(protected_item_test, os.R_OK):
517
518 in_system_md5 = self.entropyTools.md5sum(protected_item_test)
519 if oldprot_md5 == in_system_md5:
520 mytxt = "%s: %s" % (
521 darkgreen(_("Removing config file, never modified")),
522 blue(item),)
523 self.Entropy.updateProgress(
524 mytxt,
525 importance = 1,
526 type = "info",
527 header = red(" ## ")
528 )
529 protected = False
530 do_continue = False
531
532 if protected:
533 self.Entropy.clientLog.log(
534 ETP_LOGPRI_INFO,
535 ETP_LOGLEVEL_VERBOSE,
536 "[remove] Protecting config file: "+sys_root_item
537 )
538 mytxt = "[%s] %s: %s" % (
539 red(_("remove")),
540 brown(_("Protecting config file")),
541 sys_root_item,
542 )
543 self.Entropy.updateProgress(
544 mytxt,
545 importance = 1,
546 type = "warning",
547 header = red(" ## ")
548 )
549 else:
550 try:
551 os.lstat(sys_root_item)
552 except OSError:
553 continue
554 except UnicodeEncodeError:
555 mytxt = brown(_("This package contains a badly encoded file !!!"))
556 self.Entropy.updateProgress(
557 red("QA: ")+mytxt,
558 importance = 1,
559 type = "warning",
560 header = darkred(" ## ")
561 )
562 continue
563
564 if os.path.isdir(sys_root_item) and os.path.islink(sys_root_item):
565
566
567 directories.add((sys_root_item,"link"))
568 elif os.path.isdir(sys_root_item):
569
570 directories.add((sys_root_item,"dir"))
571 else:
572
573 try:
574 os.remove(sys_root_item)
575
576 dirfile = os.path.dirname(sys_root_item)
577 if os.path.isdir(dirfile) and os.path.islink(dirfile):
578 directories.add((dirfile,"link"))
579 elif os.path.isdir(dirfile):
580 directories.add((dirfile,"dir"))
581 except OSError:
582 pass
583
584
585
586
587
588
589
590 self.infoDict['removecontent'] -= not_removed_due_to_collisions
591
592
593 directories = sorted(directories, reverse = True)
594 while 1:
595 taint = False
596 for directory, dirtype in directories:
597 mydir = "%s%s" % (sys_root,directory,)
598 if dirtype == "link":
599 try:
600 mylist = os.listdir(mydir)
601 if not mylist:
602 try:
603 os.remove(mydir)
604 taint = True
605 except OSError:
606 pass
607 except OSError:
608 pass
609 elif dirtype == "dir":
610 try:
611 mylist = os.listdir(mydir)
612 if not mylist:
613 try:
614 os.rmdir(mydir)
615 taint = True
616 except OSError:
617 pass
618 except OSError:
619 pass
620
621 if not taint:
622 break
623 del directories
624
625
626 '''
627 @description: remove package entry from Spm database
628 @input spm package atom (cat/name+ver):
629 @output: 0 = all fine, <0 = error!
630 '''
632
633
634 try:
635 Spm = self.Entropy.Spm()
636 except:
637 return -1
638
639 portdb_dir = Spm.get_vdb_path()
640 remove_path = portdb_dir+atom
641 key = self.entropyTools.dep_getkey(atom)
642 others_installed = [x for x in Spm.search_keys(key) if \
643 self.entropyTools.dep_getkey(x) == key]
644 if atom in others_installed:
645 others_installed.remove(atom)
646 slot = self.infoDict['slot']
647 tag = self.infoDict['versiontag']
648 if (tag == slot) and tag: slot = "0"
649
650 def do_rm_path_atomic(xpath):
651 for my_el in os.listdir(xpath):
652 my_el = os.path.join(xpath, my_el)
653 try:
654 os.remove(my_el)
655 except OSError:
656 pass
657 try:
658 os.rmdir(xpath)
659 except OSError:
660 pass
661
662 if os.path.isdir(remove_path):
663 do_rm_path_atomic(remove_path)
664
665 if others_installed:
666
667 for myatom in others_installed:
668 myslot = Spm.get_installed_package_slot(myatom)
669 if myslot != slot:
670 continue
671 mydir = portdb_dir+myatom
672 if not os.path.isdir(mydir):
673 continue
674 do_rm_path_atomic(mydir)
675
676 else:
677
678 world_file = Spm.get_world_file()
679 world_file_tmp = world_file+".entropy.tmp"
680 if os.access(world_file,os.W_OK) and os.path.isfile(world_file):
681 new = open(world_file_tmp,"w")
682 old = open(world_file,"r")
683 line = old.readline()
684 while line:
685 if line.find(key) != -1:
686 line = old.readline()
687 continue
688 if line.find(key+":"+slot) != -1:
689 line = old.readline()
690 continue
691 new.write(line)
692 line = old.readline()
693 new.flush()
694 new.close()
695 old.close()
696 os.rename(world_file_tmp,world_file)
697
698 return 0
699
700 '''
701 @description: function that runs at the end of the package installation process, just removes data left by other steps
702 @output: 0 = all fine, >0 = error!
703 '''
705
706 shutil.rmtree(unpack_dir,True)
707 try: os.rmdir(unpack_dir)
708 except OSError: pass
709 return 0
710
712 self.error_on_not_prepared()
713 self.Entropy.clientDbconn.removePackage(self.infoDict['removeidpackage'],
714 do_commit = do_commit, do_cleanup = do_cleanup)
715 return 0
716
730
732
733
734 self.__clear_cache()
735
736 self.Entropy.clientLog.log(
737 ETP_LOGPRI_INFO,
738 ETP_LOGLEVEL_NORMAL,
739 "Installing package: %s" % (self.infoDict['atom'],)
740 )
741
742 already_protected_config_files = {}
743 if self.infoDict['removeidpackage'] != -1:
744 already_protected_config_files = self.Entropy.clientDbconn.retrieveAutomergefiles(
745 self.infoDict['removeidpackage'], get_dict = True
746 )
747
748
749
750 rc = self.__move_image_to_system(already_protected_config_files)
751 if rc != 0:
752 return rc
753 del already_protected_config_files
754
755
756 mytxt = "%s: %s" % (blue(_("Updating database")),red(self.infoDict['atom']),)
757 self.Entropy.updateProgress(
758 mytxt,
759 importance = 1,
760 type = "info",
761 header = red(" ## ")
762 )
763 newidpackage = self._install_package_into_database()
764
765
766 if self.infoDict['removeidpackage'] != -1:
767
768 self.Entropy.clientLog.log(
769 ETP_LOGPRI_INFO,
770 ETP_LOGLEVEL_NORMAL,
771 "Remove old package: %s" % (self.infoDict['removeatom'],)
772 )
773 self.infoDict['removeidpackage'] = -1
774
775 self.Entropy.clientLog.log(
776 ETP_LOGPRI_INFO,
777 ETP_LOGLEVEL_NORMAL,
778 "Removing Entropy and Spm database entry for %s" % (
779 self.infoDict['removeatom'],)
780 )
781
782 self.Entropy.updateProgress(
783 blue(_("Cleaning old package files...")),
784 importance = 1,
785 type = "info",
786 header = red(" ## ")
787 )
788 self.__remove_package()
789
790 self.Entropy.clientLog.log(
791 ETP_LOGPRI_INFO,
792 ETP_LOGLEVEL_NORMAL,
793 "Installing new Spm database entry: %s" % (self.infoDict['atom'],)
794 )
795 rc = self._install_package_into_spm_database(newidpackage)
796
797 return rc
798
799 '''
800 @description: inject the database information into the Gentoo database
801 @output: 0 = all fine, !=0 = error!
802 '''
804
805
806 try:
807 Spm = self.Entropy.Spm()
808 except:
809 return -1
810
811 portdb_dir = Spm.get_vdb_path()
812 if not os.path.isdir(portdb_dir):
813 os.makedirs(portdb_dir)
814
815 category = self.infoDict['category']
816 name = self.infoDict['name']
817 key = category + "/" + name
818
819 atomsfound = set()
820 dbdirs = os.listdir(portdb_dir)
821 if category in dbdirs:
822 catdirs = os.listdir(portdb_dir + "/" + category)
823 dirsfound = set([category + "/" + x for x in catdirs if \
824 key == self.entropyTools.dep_getkey(category + "/" + x)])
825 atomsfound.update(dirsfound)
826
827
828
829 if atomsfound:
830 pkg_to_remove = None
831 for atom in atomsfound:
832 atomslot = Spm.get_installed_package_slot(atom)
833
834 if atomslot == self.infoDict['slot']:
835 pkg_to_remove = atom
836 break
837 if pkg_to_remove:
838 remove_path = portdb_dir + pkg_to_remove
839 shutil.rmtree(remove_path, True)
840 try:
841 os.rmdir(remove_path)
842 except OSError:
843 pass
844 del atomsfound
845
846
847 xpak_rel_path = etpConst['entropyxpakdatarelativepath']
848 if ((self.infoDict['xpakstatus'] != None) and \
849 os.path.isdir( self.infoDict['xpakpath'] + "/" + xpak_rel_path)) or \
850 self.infoDict['merge_from']:
851
852 if self.infoDict['merge_from']:
853 copypath = self.infoDict['xpakdir']
854 if not os.path.isdir(copypath):
855 return 0
856 else:
857 copypath = self.infoDict['xpakpath'] + "/" + xpak_rel_path
858
859 if not os.path.isdir(portdb_dir + category):
860 os.makedirs(portdb_dir + category, 0755)
861 destination = portdb_dir + category + "/" + name + "-" + \
862 self.infoDict['version']
863
864 if os.path.isdir(destination):
865 shutil.rmtree(destination)
866
867 try:
868 shutil.copytree(copypath, destination)
869 except (IOError,), e:
870 mytxt = "%s: %s: %s: %s" % (red(_("QA")),
871 brown(_("Cannot update Portage database to destination")),
872 purple(destination),e,)
873 self.Entropy.updateProgress(
874 mytxt,
875 importance = 1,
876 type = "warning",
877 header = darkred(" ## ")
878 )
879
880
881 if os.path.isfile(etpConst['edbcounter']):
882 try:
883 f = open(etpConst['edbcounter'],"r")
884 counter = int(f.readline().strip())
885 f.close()
886 except:
887
888 counter = Spm.refill_counter()
889 else:
890 counter = Spm.refill_counter()
891
892
893 if os.path.isdir(destination):
894 counter += 1
895 f = open(destination+"/"+etpConst['spm']['xpak_entries']['counter'],"w")
896 f.write(str(counter))
897 f.flush()
898 f.close()
899 f = open(etpConst['edbcounter'],"w")
900 f.write(str(counter))
901 f.flush()
902 f.close()
903
904 self.Entropy.clientDbconn.insertCounter(newidpackage, counter)
905 else:
906 mytxt = brown(_("Cannot update Portage counter, destination %s does not exist.") % (destination,))
907 self.Entropy.updateProgress(
908 red("QA: ")+mytxt,
909 importance = 1,
910 type = "warning",
911 header = darkred(" ## ")
912 )
913
914 user_inst_source = etpConst['install_sources']['user']
915 if self.infoDict['install_source'] != user_inst_source:
916 self.Entropy.clientLog.log(
917 ETP_LOGPRI_INFO,
918 ETP_LOGLEVEL_NORMAL,
919 "Not updating Portage world file for: %s" % (self.infoDict['atom'],)
920 )
921
922 return 0
923
924
925
926
927 myslot = self.infoDict['slot']
928 if (self.infoDict['versiontag'] == self.infoDict['slot']) and self.infoDict['versiontag']:
929
930 myslot = "0"
931 keyslot = key+":"+myslot
932 world_file = Spm.get_world_file()
933 world_atoms = set()
934
935 if os.access(world_file,os.R_OK) and os.path.isfile(world_file):
936 f = open(world_file,"r")
937 world_atoms = set([x.strip() for x in f.readlines() if x.strip()])
938 f.close()
939 else:
940 mytxt = brown(_("Cannot update Portage world file, destination %s does not exist.") % (world_file,))
941 self.Entropy.updateProgress(
942 red("QA: ")+mytxt,
943 importance = 1,
944 type = "warning",
945 header = darkred(" ## ")
946 )
947 return 0
948
949 try:
950 if keyslot not in world_atoms and \
951 os.access(os.path.dirname(world_file),os.W_OK) and \
952 self.entropyTools.istextfile(world_file):
953 world_atoms.discard(key)
954 world_atoms.add(keyslot)
955 world_atoms = sorted(list(world_atoms))
956 world_file_tmp = world_file+".entropy_inst"
957 f = open(world_file_tmp,"w")
958 for item in world_atoms:
959 f.write(item+"\n")
960 f.flush()
961 f.close()
962 shutil.move(world_file_tmp,world_file)
963 except (UnicodeDecodeError,UnicodeEncodeError), e:
964 self.entropyTools.print_traceback(f = self.Entropy.clientLog)
965 mytxt = brown(_("Cannot update Portage world file, destination %s is corrupted.") % (world_file,))
966 self.Entropy.updateProgress(
967 red("QA: ")+mytxt+": "+unicode(e),
968 importance = 1,
969 type = "warning",
970 header = darkred(" ## ")
971 )
972
973 return 0
974
975 '''
976 @description: injects package info into the installed packages database
977 @output: 0 = all fine, >0 = error!
978 '''
980
981
982 smart_pkg = self.infoDict['smartpackage']
983 dbconn = self.Entropy.open_repository(self.infoDict['repository'])
984
985 if smart_pkg or self.infoDict['merge_from']:
986
987 data = dbconn.getPackageData(self.infoDict['idpackage'],
988 content_insert_formatted = True)
989
990 else:
991
992
993 data = dbconn.getPackageData(self.infoDict['idpackage'],
994 get_content = False)
995 pkg_dbconn = self.Entropy.open_generic_database(
996 self.infoDict['pkgdbpath'])
997
998
999 content = []
1000 for pkg_idpackage in pkg_dbconn.listAllIdpackages():
1001 content += pkg_dbconn.retrieveContent(
1002 pkg_idpackage, extended = True,
1003 formatted = True, insert_formatted = True
1004 )
1005 real_idpk = self.infoDict['idpackage']
1006 content = [(real_idpk, x, y,) for orig_idpk, x, y in content]
1007 data['content'] = content
1008 pkg_dbconn.closeDB()
1009
1010
1011 trigger_content = set((x[1] for x in data['content']))
1012 self.infoDict['triggers']['install']['content'] = trigger_content
1013
1014
1015
1016
1017
1018 data['injected'] = False
1019
1020 data['counter'] = -1
1021
1022
1023 data['branch'] = self.Entropy.SystemSettings['repositories']['branch']
1024
1025 if data.get('needed_paths'):
1026 del data['needed_paths']
1027
1028 idpackage, rev, x = self.Entropy.clientDbconn.handlePackage(
1029 etpData = data, forcedRevision = data['revision'],
1030 formattedContent = True)
1031
1032
1033 ctime = self.entropyTools.get_current_unix_time()
1034 self.Entropy.clientDbconn.setDateCreation(idpackage, str(ctime))
1035
1036
1037 self.Entropy.clientDbconn.removePackageFromInstalledTable(idpackage)
1038 self.Entropy.clientDbconn.addPackageToInstalledTable(idpackage,
1039 self.infoDict['repository'], self.infoDict['install_source'])
1040
1041 automerge_data = self.infoDict.get('configprotect_data')
1042 if automerge_data:
1043 self.Entropy.clientDbconn.insertAutomergefiles(idpackage,
1044 automerge_data)
1045
1046
1047
1048 self.Entropy.clientDbconn.clearDependsTable()
1049 return idpackage
1050
1052
1053 dbconn = self.Entropy.open_repository(self.infoDict['repository'])
1054
1055
1056
1057 package_content = dbconn.retrieveContent(
1058 self.infoDict['idpackage'], extended = True, formatted = True)
1059 contents = sorted(package_content)
1060
1061
1062 for path in contents:
1063
1064 encoded_path = path
1065 path = os.path.join(mergeFrom,encoded_path[1:])
1066 topath = os.path.join(imageDir,encoded_path[1:])
1067 path = path.encode('raw_unicode_escape')
1068 topath = topath.encode('raw_unicode_escape')
1069
1070 try:
1071 exist = os.lstat(path)
1072 except OSError:
1073 continue
1074 ftype = package_content[encoded_path]
1075
1076 if 'dir' == ftype and \
1077 not stat.S_ISDIR(exist.st_mode) and \
1078 os.path.isdir(path):
1079
1080 path = os.path.realpath(path)
1081
1082 copystat = False
1083
1084 if os.path.islink(path):
1085 tolink = os.readlink(path)
1086 if os.path.islink(topath):
1087 os.remove(topath)
1088 os.symlink(tolink,topath)
1089 elif os.path.isdir(path):
1090 if not os.path.isdir(topath):
1091 os.makedirs(topath)
1092 copystat = True
1093 elif os.path.isfile(path):
1094 if os.path.isfile(topath):
1095 os.remove(topath)
1096 shutil.copy2(path,topath)
1097 copystat = True
1098
1099 if copystat:
1100 user = os.stat(path)[stat.ST_UID]
1101 group = os.stat(path)[stat.ST_GID]
1102 os.chown(topath,user,group)
1103 shutil.copystat(path,topath)
1104
1105
1107
1108
1109 repoid = self.infoDict['repository']
1110 protect = self.Entropy.get_package_match_config_protect(
1111 self.matched_atom)
1112 mask = self.Entropy.get_package_match_config_protect(
1113 self.matched_atom, mask = True)
1114 sys_root = etpConst['systemroot']
1115 sys_set_plg_id = \
1116 etpConst['system_settings_plugins_ids']['client_plugin']
1117 col_protect = self.Entropy.SystemSettings[sys_set_plg_id]['misc']['collisionprotect']
1118 items_installed = set()
1119
1120
1121 imageDir = self.infoDict['imagedir']
1122 encoded_imageDir = imageDir.encode('utf-8')
1123 movefile = self.entropyTools.movefile
1124
1125
1126 for currentdir,subdirs,files in os.walk(encoded_imageDir):
1127
1128 for subdir in subdirs:
1129
1130 imagepathDir = "%s/%s" % (currentdir,subdir,)
1131 rootdir = "%s%s" % (sys_root,imagepathDir[len(imageDir):],)
1132
1133
1134 if os.path.islink(rootdir) and not os.path.exists(rootdir):
1135 os.remove(rootdir)
1136
1137
1138 elif os.path.isfile(rootdir):
1139 self.Entropy.clientLog.log(
1140 ETP_LOGPRI_INFO,
1141 ETP_LOGLEVEL_NORMAL,
1142 "WARNING!!! %s is a file when it should be a directory !! Removing in 20 seconds..." % (rootdir,)
1143 )
1144 mytxt = darkred(_("%s is a file when should be a directory !! Removing in 20 seconds...") % (rootdir,))
1145 self.Entropy.updateProgress(
1146 red("QA: ")+mytxt,
1147 importance = 1,
1148 type = "warning",
1149 header = red(" !!! ")
1150 )
1151 self.entropyTools.ebeep(20)
1152 os.remove(rootdir)
1153
1154
1155 if os.path.islink(imagepathDir):
1156
1157
1158
1159 if (not os.path.islink(rootdir)) and os.path.isdir(rootdir):
1160 self.Entropy.clientLog.log(
1161 ETP_LOGPRI_INFO,
1162 ETP_LOGLEVEL_NORMAL,
1163 "WARNING!!! %s is a directory when it should be a symlink !! Removing in 20 seconds..." % (rootdir,)
1164 )
1165 mytxt = darkred(_("%s is a directory when should be a symlink !! Removing in 20 seconds...") % (rootdir,))
1166 self.Entropy.updateProgress(
1167 red("QA: ")+mytxt,
1168 importance = 1,
1169 type = "warning",
1170 header = red(" !!! ")
1171 )
1172 self.entropyTools.ebeep(20)
1173 shutil.rmtree(rootdir, True)
1174 os.rmdir(rootdir)
1175
1176 tolink = os.readlink(imagepathDir)
1177 live_tolink = None
1178 if os.path.islink(rootdir):
1179 live_tolink = os.readlink(rootdir)
1180 if tolink != live_tolink:
1181 if os.path.lexists(rootdir):
1182
1183 os.remove(rootdir)
1184 os.symlink(tolink, rootdir)
1185
1186 elif (not os.path.isdir(rootdir)) and (not os.access(rootdir,os.R_OK)):
1187 try:
1188
1189 os.mkdir(rootdir)
1190 except OSError:
1191 os.makedirs(rootdir)
1192
1193
1194 if not os.path.islink(rootdir) and os.access(rootdir,os.W_OK):
1195
1196
1197
1198 user = os.stat(imagepathDir)[stat.ST_UID]
1199 group = os.stat(imagepathDir)[stat.ST_GID]
1200 os.chown(rootdir,user,group)
1201 shutil.copystat(imagepathDir,rootdir)
1202
1203 items_installed.add(os.path.join(os.path.realpath(os.path.dirname(rootdir)),os.path.basename(rootdir)))
1204
1205 for item in files:
1206
1207 fromfile = "%s/%s" % (currentdir,item,)
1208 tofile = "%s%s" % (sys_root,fromfile[len(imageDir):],)
1209
1210 if col_protect > 1:
1211 todbfile = fromfile[len(imageDir):]
1212 myrc = self._handle_install_collision_protect(tofile, todbfile)
1213 if not myrc:
1214 continue
1215
1216 prot_old_tofile = tofile[len(sys_root):]
1217 pre_tofile = tofile[:]
1218 in_mask, protected, tofile, do_continue = self._handle_config_protect(
1219 protect, mask, fromfile, tofile)
1220
1221
1222 if in_mask and os.path.exists(fromfile):
1223 try:
1224 prot_md5 = self.entropyTools.md5sum(fromfile)
1225 self.infoDict['configprotect_data'].append(
1226 (prot_old_tofile,prot_md5,))
1227 except (IOError,):
1228 pass
1229
1230
1231 if protected:
1232
1233 try:
1234
1235
1236 oldprot_md5 = already_protected_config_files.get(
1237 prot_old_tofile)
1238
1239 if oldprot_md5 and os.path.exists(pre_tofile) and \
1240 os.access(pre_tofile, os.R_OK):
1241
1242 in_system_md5 = self.entropyTools.md5sum(pre_tofile)
1243 if oldprot_md5 == in_system_md5:
1244
1245
1246
1247 mytxt = "%s: %s" % (
1248 darkgreen(_("Automerging config file, never modified")),
1249 blue(pre_tofile),)
1250 self.Entropy.updateProgress(
1251 mytxt,
1252 importance = 1,
1253 type = "info",
1254 header = red(" ## ")
1255 )
1256 protected = False
1257 do_continue = False
1258 tofile = pre_tofile
1259
1260 except (IOError,):
1261 pass
1262
1263 if do_continue:
1264 continue
1265
1266 try:
1267
1268 if os.path.realpath(fromfile) == os.path.realpath(tofile) and os.path.islink(tofile):
1269
1270 try:
1271 os.remove(tofile)
1272 except OSError:
1273 pass
1274
1275
1276 if os.path.isdir(tofile) and not os.path.islink(tofile):
1277 self.Entropy.clientLog.log(
1278 ETP_LOGPRI_INFO,
1279 ETP_LOGLEVEL_NORMAL,
1280 "WARNING!!! %s is a directory when it should be a file !! Removing in 20 seconds..." % (tofile,)
1281 )
1282 mytxt = _("%s is a directory when it should be a file !! Removing in 20 seconds...") % (tofile,)
1283 self.Entropy.updateProgress(
1284 red("QA: ")+darkred(mytxt),
1285 importance = 1,
1286 type = "warning",
1287 header = red(" !!! ")
1288 )
1289 self.entropyTools.ebeep(10)
1290 time.sleep(20)
1291 try:
1292 shutil.rmtree(tofile, True)
1293 os.rmdir(tofile)
1294 except:
1295 pass
1296 try:
1297 os.remove(tofile)
1298 except OSError:
1299 pass
1300
1301
1302
1303
1304 done = movefile(fromfile, tofile, src_basedir = encoded_imageDir)
1305 if not done:
1306 self.Entropy.clientLog.log(
1307 ETP_LOGPRI_INFO,
1308 ETP_LOGLEVEL_NORMAL,
1309 "WARNING!!! Error during file move to system: %s => %s" % (fromfile,tofile,)
1310 )
1311 mytxt = "%s: %s => %s, %s" % (_("File move error"),fromfile,tofile,_("please report"),)
1312 self.Entropy.updateProgress(
1313 red("QA: ")+darkred(mytxt),
1314 importance = 1,
1315 type = "warning",
1316 header = red(" !!! ")
1317 )
1318 return 4
1319
1320 except IOError, e:
1321
1322
1323 if e.errno != 2: raise
1324
1325 items_installed.add(os.path.join(os.path.realpath(os.path.dirname(tofile)),os.path.basename(tofile)))
1326 if protected:
1327
1328 self.Entropy.FileUpdates.add_to_cache(tofile, quiet = True)
1329
1330
1331
1332
1333
1334 if self.infoDict.get('removecontent'):
1335 my_remove_content = set([x for x in self.infoDict['removecontent'] \
1336 if os.path.join(os.path.realpath(
1337 os.path.dirname("%s%s" % (sys_root,x,))),os.path.basename(x)
1338 ) in items_installed])
1339 self.infoDict['removecontent'] -= my_remove_content
1340
1341 return 0
1342
1343 - def _handle_config_protect(self, protect, mask, fromfile, tofile,
1344 do_allocation_check = True, do_quiet = False):
1345
1346 protected = False
1347 tofile_before_protect = tofile
1348 do_continue = False
1349 in_mask = False
1350
1351 try:
1352 encoded_protect = [x.encode('raw_unicode_escape') for x in protect]
1353 if tofile in encoded_protect:
1354 protected = True
1355 in_mask = True
1356 elif os.path.dirname(tofile) in encoded_protect:
1357 protected = True
1358 in_mask = True
1359 else:
1360 tofile_testdir = os.path.dirname(tofile)
1361 old_tofile_testdir = None
1362 while tofile_testdir != old_tofile_testdir:
1363 if tofile_testdir in encoded_protect:
1364 protected = True
1365 in_mask = True
1366 break
1367 old_tofile_testdir = tofile_testdir
1368 tofile_testdir = os.path.dirname(tofile_testdir)
1369
1370 if protected:
1371 newmask = [x.encode('raw_unicode_escape') for x in mask]
1372 if tofile in newmask:
1373 protected = False
1374 in_mask = False
1375 elif os.path.dirname(tofile) in newmask:
1376 protected = False
1377 in_mask = False
1378 else:
1379 tofile_testdir = os.path.dirname(tofile)
1380 old_tofile_testdir = None
1381 while tofile_testdir != old_tofile_testdir:
1382 if tofile_testdir in newmask:
1383 protected = False
1384 in_mask = False
1385 break
1386 old_tofile_testdir = tofile_testdir
1387 tofile_testdir = os.path.dirname(tofile_testdir)
1388
1389 if not os.path.lexists(tofile):
1390 protected = False
1391
1392
1393 if (protected) and os.path.isfile(tofile):
1394 protected = self.entropyTools.istextfile(tofile)
1395 in_mask = protected
1396 else:
1397 protected = False
1398
1399
1400 if protected:
1401 sys_set_plg_id = \
1402 etpConst['system_settings_plugins_ids']['client_plugin']
1403 client_settings = self.Entropy.SystemSettings[sys_set_plg_id]['misc']
1404 if tofile not in client_settings['configprotectskip']:
1405 prot_status = True
1406 if do_allocation_check:
1407 tofile, prot_status = self.entropyTools.allocate_masked_file(tofile, fromfile)
1408 if not prot_status:
1409 protected = False
1410 else:
1411 oldtofile = tofile
1412 if oldtofile.find("._cfg") != -1:
1413 oldtofile = os.path.join(os.path.dirname(oldtofile),
1414 os.path.basename(oldtofile)[10:])
1415 if not do_quiet:
1416 self.Entropy.clientLog.log(
1417 ETP_LOGPRI_INFO,
1418 ETP_LOGLEVEL_NORMAL,
1419 "Protecting config file: %s" % (oldtofile,)
1420 )
1421 mytxt = red("%s: %s") % (_("Protecting config file"),oldtofile,)
1422 self.Entropy.updateProgress(
1423 mytxt,
1424 importance = 1,
1425 type = "warning",
1426 header = darkred(" ## ")
1427 )
1428 else:
1429 if not do_quiet:
1430 self.Entropy.clientLog.log(
1431 ETP_LOGPRI_INFO,
1432 ETP_LOGLEVEL_NORMAL,
1433 "Skipping config file installation/removal, as stated in client.conf: %s" % (tofile,)
1434 )
1435 mytxt = "%s: %s" % (_("Skipping file installation/removal"),tofile,)
1436 self.Entropy.updateProgress(
1437 mytxt,
1438 importance = 1,
1439 type = "warning",
1440 header = darkred(" ## ")
1441 )
1442 do_continue = True
1443
1444 except Exception, e:
1445 self.entropyTools.print_traceback()
1446 protected = False
1447 tofile = tofile_before_protect
1448 mytxt = darkred("%s: %s") % (_("Cannot check CONFIG PROTECTION. Error"),e,)
1449 self.Entropy.updateProgress(
1450 red("QA: ")+mytxt,
1451 importance = 1,
1452 type = "warning",
1453 header = darkred(" ## ")
1454 )
1455
1456 return in_mask, protected, tofile, do_continue
1457
1458
1460 avail = self.Entropy.clientDbconn.isFileAvailable(todbfile, get_id = True)
1461 if (self.infoDict['removeidpackage'] not in avail) and avail:
1462 mytxt = darkred(_("Collision found during install for"))
1463 mytxt += " %s - %s" % (blue(tofile),darkred(_("cannot overwrite")),)
1464 self.Entropy.updateProgress(
1465 red("QA: ")+mytxt,
1466 importance = 1,
1467 type = "warning",
1468 header = darkred(" ## ")
1469 )
1470 self.Entropy.clientLog.log(
1471 ETP_LOGPRI_INFO,
1472 ETP_LOGLEVEL_NORMAL,
1473 "WARNING!!! Collision found during install for %s - cannot overwrite" % (tofile,)
1474 )
1475 return False
1476 return True
1477
1479 self.error_on_not_prepared()
1480 down_data = self.infoDict['download']
1481 down_keys = down_data.keys()
1482 d_cache = set()
1483 rc = 0
1484 key_cache = [os.path.basename(x) for x in down_keys]
1485 for key in sorted(down_keys):
1486 key_name = os.path.basename(key)
1487 if key_name in d_cache: continue
1488
1489 for url in down_data[key]:
1490 file_name = os.path.basename(url)
1491 if self.infoDict.get('fetch_path'):
1492 dest_file = os.path.join(self.infoDict['fetch_path'],
1493 file_name)
1494 else:
1495 dest_file = os.path.join(self.infoDict['unpackdir'],
1496 file_name)
1497 rc = self._fetch_source(url, dest_file)
1498 if rc == 0:
1499 d_cache.add(key_name)
1500 break
1501 key_cache.remove(key_name)
1502 if rc != 0 and key_name not in key_cache:
1503 break
1504 rc = 0
1505
1506 return rc
1507
1509 rc = 1
1510 try:
1511 mytxt = "%s: %s" % (blue(_("Downloading")),brown(url),)
1512
1513 self.Entropy.updateProgress(
1514 mytxt,
1515 importance = 1,
1516 type = "info",
1517 header = red(" ## ")
1518 )
1519
1520 rc, data_transfer, resumed = self.Entropy.fetch_file(
1521 url,
1522 None,
1523 None,
1524 False,
1525 fetch_file_abort_function = self.fetch_abort_function,
1526 filepath = dest_file
1527 )
1528 if rc == 0:
1529 mytxt = blue("%s: ") % (_("Successfully downloaded from"),)
1530 mytxt += red(self.entropyTools.spliturl(url)[1])
1531 mytxt += " %s %s/%s" % (_("at"),self.entropyTools.bytes_into_human(data_transfer),_("second"),)
1532 self.Entropy.updateProgress(
1533 mytxt,
1534 importance = 1,
1535 type = "info",
1536 header = red(" ## ")
1537 )
1538 self.Entropy.updateProgress(
1539 "%s: %s" % (blue(_("Local path")),brown(dest_file),),
1540 importance = 1,
1541 type = "info",
1542 header = red(" # ")
1543 )
1544 else:
1545 error_message = blue("%s: %s") % (
1546 _("Error downloading from"),
1547 red(self.entropyTools.spliturl(url)[1]),
1548 )
1549
1550 if rc == -1:
1551 error_message += " - %s." % (_("file not available on this mirror"),)
1552 elif rc == -3:
1553 error_message += " - not found."
1554 elif rc == -100:
1555 error_message += " - %s." % (_("discarded download"),)
1556 else:
1557 error_message += " - %s: %s" % (_("unknown reason"),rc,)
1558 self.Entropy.updateProgress(
1559 error_message,
1560 importance = 1,
1561 type = "warning",
1562 header = red(" ## ")
1563 )
1564 except KeyboardInterrupt:
1565 pass
1566 return rc
1567
1569 self.error_on_not_prepared()
1570 mytxt = "%s: %s" % (blue(_("Downloading archive")),
1571 red(os.path.basename(self.infoDict['download'])),)
1572 self.Entropy.updateProgress(
1573 mytxt,
1574 importance = 1,
1575 type = "info",
1576 header = red(" ## ")
1577 )
1578
1579 rc = 0
1580 if not self.infoDict['verified']:
1581 rc = self.Entropy.fetch_file_on_mirrors(
1582 self.infoDict['repository'],
1583 self.Entropy.get_branch_from_download_relative_uri(self.infoDict['download']),
1584 self.infoDict['download'],
1585 self.infoDict['checksum'],
1586 fetch_abort_function = self.fetch_abort_function
1587 )
1588 if rc != 0:
1589 mytxt = "%s. %s: %s" % (
1590 red(_("Package cannot be fetched. Try to update repositories and retry")),
1591 blue(_("Error")),
1592 rc,
1593 )
1594 self.Entropy.updateProgress(
1595 mytxt,
1596 importance = 1,
1597 type = "error",
1598 header = darkred(" ## ")
1599 )
1600 return rc
1601
1603 self.error_on_not_prepared()
1604 m_fetch_len = len(self.infoDict['multi_fetch_list'])
1605 mytxt = "%s: %s %s" % (blue(_("Downloading")),darkred(str(m_fetch_len)),_("archives"),)
1606 self.Entropy.updateProgress(
1607 mytxt,
1608 importance = 1,
1609 type = "info",
1610 header = red(" ## ")
1611 )
1612
1613 rc, err_list = self.Entropy.fetch_files_on_mirrors(
1614 self.infoDict['multi_fetch_list'],
1615 self.infoDict['checksum'],
1616 fetch_abort_function = self.fetch_abort_function
1617 )
1618 if rc != 0:
1619 mytxt = "%s. %s: %s" % (
1620 red(_("Some packages cannot be fetched. Try to update repositories and retry")),
1621 blue(_("Error")),
1622 rc,
1623 )
1624 self.Entropy.updateProgress(
1625 mytxt,
1626 importance = 1,
1627 type = "error",
1628 header = darkred(" ## ")
1629 )
1630 for repo, branch, fname, cksum, signatures in err_list:
1631 self.Entropy.updateProgress(
1632 "[%s:%s|%s] %s" % (blue(repo),brown(branch),
1633 darkgreen(cksum),darkred(fname),),
1634 importance = 1,
1635 type = "error",
1636 header = darkred(" # ")
1637 )
1638 return rc
1639
1641 self.Entropy.updateProgress(
1642 blue(_("Fetch for the chosen package is not available, unknown error.")),
1643 importance = 1,
1644 type = "info",
1645 header = red(" ## ")
1646 )
1647 return 0
1648
1650 self.Entropy.updateProgress(
1651 blue(_("Installed package in queue vanished, skipping.")),
1652 importance = 1,
1653 type = "info",
1654 header = red(" ## ")
1655 )
1656 return 0
1657
1661
1665
1667 self.error_on_not_prepared()
1668
1669 if not self.infoDict['merge_from']:
1670 mytxt = "%s: %s" % (blue(_("Unpacking package")),red(os.path.basename(self.infoDict['download'])),)
1671 self.Entropy.updateProgress(
1672 mytxt,
1673 importance = 1,
1674 type = "info",
1675 header = red(" ## ")
1676 )
1677 else:
1678 mytxt = "%s: %s" % (blue(_("Merging package")),red(os.path.basename(self.infoDict['atom'])),)
1679 self.Entropy.updateProgress(
1680 mytxt,
1681 importance = 1,
1682 type = "info",
1683 header = red(" ## ")
1684 )
1685 rc = self.__unpack_package()
1686 if rc != 0:
1687 if rc == 512:
1688 errormsg = "%s. %s. %s: 512" % (
1689 red(_("You are running out of disk space")),
1690 red(_("I bet, you're probably Michele")),
1691 blue(_("Error")),
1692 )
1693 else:
1694 errormsg = "%s. %s. %s: %s" % (
1695 red(_("An error occured while trying to unpack the package")),
1696 red(_("Check if your system is healthy")),
1697 blue(_("Error")),
1698 rc,
1699 )
1700 self.Entropy.updateProgress(
1701 errormsg,
1702 importance = 1,
1703 type = "error",
1704 header = red(" ## ")
1705 )
1706 return rc
1707
1709 self.error_on_not_prepared()
1710 mytxt = "%s: %s" % (blue(_("Installing package")),red(self.infoDict['atom']),)
1711 self.Entropy.updateProgress(
1712 mytxt,
1713 importance = 1,
1714 type = "info",
1715 header = red(" ## ")
1716 )
1717 rc = self.__install_package()
1718 if rc != 0:
1719 mytxt = "%s. %s. %s: %s" % (
1720 red(_("An error occured while trying to install the package")),
1721 red(_("Check if your system is healthy")),
1722 blue(_("Error")),
1723 rc,
1724 )
1725 self.Entropy.updateProgress(
1726 mytxt,
1727 importance = 1,
1728 type = "error",
1729 header = red(" ## ")
1730 )
1731 return rc
1732
1734 self.error_on_not_prepared()
1735 mytxt = "%s: %s" % (blue(_("Removing data")),red(self.infoDict['removeatom']),)
1736 self.Entropy.updateProgress(
1737 mytxt,
1738 importance = 1,
1739 type = "info",
1740 header = red(" ## ")
1741 )
1742 rc = self.__remove_package()
1743 if rc != 0:
1744 mytxt = "%s. %s. %s: %s" % (
1745 red(_("An error occured while trying to remove the package")),
1746 red(_("Check if you have enough disk space on your hard disk")),
1747 blue(_("Error")),
1748 rc,
1749 )
1750 self.Entropy.updateProgress(
1751 mytxt,
1752 importance = 1,
1753 type = "error",
1754 header = red(" ## ")
1755 )
1756 return rc
1757
1759 self.error_on_not_prepared()
1760 mytxt = "%s: %s" % (blue(_("Cleaning")),red(self.infoDict['atom']),)
1761 self.Entropy.updateProgress(
1762 mytxt,
1763 importance = 1,
1764 type = "info",
1765 header = red(" ## ")
1766 )
1767 self._cleanup_package(self.infoDict['unpackdir'])
1768
1769 return 0
1770
1772 for msg in self.infoDict['messages']:
1773 self.Entropy.clientLog.write(">>> "+msg)
1774 return 0
1775
1776 - def postinstall_step(self):
1777 self.error_on_not_prepared()
1778 pkgdata = self.infoDict['triggers'].get('install')
1779 if pkgdata:
1780 trigger = self.Entropy.Triggers('postinstall',pkgdata, self.action)
1781 do = trigger.prepare()
1782 if do:
1783 trigger.run()
1784 trigger.kill()
1785 del pkgdata
1786 return 0
1787
1789 self.error_on_not_prepared()
1790 pkgdata = self.infoDict['triggers'].get('install')
1791 if pkgdata:
1792
1793 trigger = self.Entropy.Triggers('preinstall',pkgdata, self.action)
1794 do = trigger.prepare()
1795 if self.infoDict.get("diffremoval") and do:
1796
1797
1798 remdata = self.infoDict['triggers'].get('remove')
1799 if remdata:
1800 r_trigger = self.Entropy.Triggers('preremove',remdata, self.action)
1801 r_trigger.prepare()
1802 r_trigger.triggers = [x for x in trigger.triggers if x not in r_trigger.triggers]
1803 r_trigger.kill()
1804 del remdata
1805 if do:
1806 trigger.run()
1807 trigger.kill()
1808
1809 del pkgdata
1810 return 0
1811
1823
1824 - def postremove_step(self):
1825 self.error_on_not_prepared()
1826 remdata = self.infoDict['triggers'].get('remove')
1827 if remdata:
1828
1829 trigger = self.Entropy.Triggers('postremove',remdata, self.action)
1830 do = trigger.prepare()
1831 if self.infoDict['diffremoval'] and (self.infoDict.get("atom") != None) and do:
1832
1833 pkgdata = self.infoDict['triggers'].get('install')
1834 if pkgdata:
1835 i_trigger = self.Entropy.Triggers('postinstall',pkgdata, self.action)
1836 i_trigger.prepare()
1837 i_trigger.triggers = [x for x in trigger.triggers if x not in i_trigger.triggers]
1838 i_trigger.kill()
1839 del pkgdata
1840 if do:
1841 trigger.run()
1842 trigger.kill()
1843
1844 del remdata
1845 return 0
1846
1848 self.error_on_not_prepared()
1849 for idpackage in self.infoDict['conflicts']:
1850 if not self.Entropy.clientDbconn.isIDPackageAvailable(idpackage):
1851 continue
1852 pkg = self.Entropy.Package()
1853 pkg.prepare((idpackage,),"remove_conflict", self.infoDict['remove_metaopts'])
1854 rc = pkg.run(xterm_header = self.xterm_title)
1855 pkg.kill()
1856 if rc != 0:
1857 return rc
1858
1859 return 0
1860
1862 self.error_on_not_prepared()
1863 mytxt = "%s: %s" % (blue(_("Configuring package")),red(self.infoDict['atom']),)
1864 self.Entropy.updateProgress(
1865 mytxt,
1866 importance = 1,
1867 type = "info",
1868 header = red(" ## ")
1869 )
1870 rc = self.__configure_package()
1871 if rc == 1:
1872 mytxt = "%s. %s. %s: %s" % (
1873 red(_("An error occured while trying to configure the package")),
1874 red(_("Make sure that your system is healthy")),
1875 blue(_("Error")),
1876 rc,
1877 )
1878 self.Entropy.updateProgress(
1879 mytxt,
1880 importance = 1,
1881 type = "error",
1882 header = red(" ## ")
1883 )
1884 elif rc == 2:
1885 mytxt = "%s. %s. %s: %s" % (
1886 red(_("An error occured while trying to configure the package")),
1887 red(_("It seems that the Source Package Manager entry is missing")),
1888 blue(_("Error")),
1889 rc,
1890 )
1891 self.Entropy.updateProgress(
1892 mytxt,
1893 importance = 1,
1894 type = "error",
1895 header = red(" ## ")
1896 )
1897 return rc
1898
1900 if xterm_header == None:
1901 xterm_header = ""
1902
1903 if self.infoDict.has_key('remove_installed_vanished'):
1904 self.xterm_title += ' Installed package vanished'
1905 self.Entropy.setTitle(self.xterm_title)
1906 rc = self.vanished_step()
1907 return rc
1908
1909 if self.infoDict.has_key('fetch_not_available'):
1910 self.xterm_title += ' Fetch not available'
1911 self.Entropy.setTitle(self.xterm_title)
1912 rc = self.fetch_not_available_step()
1913 return rc
1914
1915 def do_fetch():
1916 self.xterm_title += ' %s: %s' % (_("Fetching"),os.path.basename(self.infoDict['download']),)
1917 self.Entropy.setTitle(self.xterm_title)
1918 return self.fetch_step()
1919
1920 def do_multi_fetch():
1921 self.xterm_title += ' %s: %s %s' % (_("Multi Fetching"),
1922 len(self.infoDict['multi_fetch_list']),_("packages"),)
1923 self.Entropy.setTitle(self.xterm_title)
1924 return self.multi_fetch_step()
1925
1926 def do_sources_fetch():
1927 self.xterm_title += ' %s: %s' % (_("Fetching sources"),os.path.basename(self.infoDict['atom']),)
1928 self.Entropy.setTitle(self.xterm_title)
1929 return self.sources_fetch_step()
1930
1931 def do_checksum():
1932 self.xterm_title += ' %s: %s' % (_("Verifying"),os.path.basename(self.infoDict['download']),)
1933 self.Entropy.setTitle(self.xterm_title)
1934 return self.checksum_step()
1935
1936 def do_multi_checksum():
1937 self.xterm_title += ' %s: %s %s' % (_("Multi Verification"),
1938 len(self.infoDict['multi_checksum_list']),_("packages"),)
1939 self.Entropy.setTitle(self.xterm_title)
1940 return self.multi_checksum_step()
1941
1942 def do_unpack():
1943 if not self.infoDict['merge_from']:
1944 mytxt = _("Unpacking")
1945 self.xterm_title += ' %s: %s' % (mytxt,os.path.basename(self.infoDict['download']),)
1946 else:
1947 mytxt = _("Merging")
1948 self.xterm_title += ' %s: %s' % (mytxt,os.path.basename(self.infoDict['atom']),)
1949 self.Entropy.setTitle(self.xterm_title)
1950 return self.unpack_step()
1951
1952 def do_remove_conflicts():
1953 return self.removeconflict_step()
1954
1955 def do_install():
1956 self.xterm_title += ' %s: %s' % (_("Installing"),self.infoDict['atom'],)
1957 self.Entropy.setTitle(self.xterm_title)
1958 return self.install_step()
1959
1960 def do_remove():
1961 self.xterm_title += ' %s: %s' % (_("Removing"),self.infoDict['removeatom'],)
1962 self.Entropy.setTitle(self.xterm_title)
1963 return self.remove_step()
1964
1965 def do_logmessages():
1966 return self.logmessages_step()
1967
1968 def do_cleanup():
1969 self.xterm_title += ' %s: %s' % (_("Cleaning"),self.infoDict['atom'],)
1970 self.Entropy.setTitle(self.xterm_title)
1971 return self.cleanup_step()
1972
1973 def do_postinstall():
1974 self.xterm_title += ' %s: %s' % (_("Postinstall"),self.infoDict['atom'],)
1975 self.Entropy.setTitle(self.xterm_title)
1976 return self.postinstall_step()
1977
1978 def do_preinstall():
1979 self.xterm_title += ' %s: %s' % (_("Preinstall"),self.infoDict['atom'],)
1980 self.Entropy.setTitle(self.xterm_title)
1981 return self.preinstall_step()
1982
1983 def do_preremove():
1984 self.xterm_title += ' %s: %s' % (_("Preremove"),self.infoDict['removeatom'],)
1985 self.Entropy.setTitle(self.xterm_title)
1986 return self.preremove_step()
1987
1988 def do_postremove():
1989 self.xterm_title += ' %s: %s' % (_("Postremove"),self.infoDict['removeatom'],)
1990 self.Entropy.setTitle(self.xterm_title)
1991 return self.postremove_step()
1992
1993 def do_config():
1994 self.xterm_title += ' %s: %s' % (_("Configuring"),self.infoDict['atom'],)
1995 self.Entropy.setTitle(self.xterm_title)
1996 return self.config_step()
1997
1998 steps_data = {
1999 "fetch": do_fetch,
2000 "multi_fetch": do_multi_fetch,
2001 "multi_checksum": do_multi_checksum,
2002 "sources_fetch": do_sources_fetch,
2003 "checksum": do_checksum,
2004 "unpack": do_unpack,
2005 "remove_conflicts": do_remove_conflicts,
2006 "install": do_install,
2007 "remove": do_remove,
2008 "logmessages": do_logmessages,
2009 "cleanup": do_cleanup,
2010 "postinstall": do_postinstall,
2011 "preinstall": do_preinstall,
2012 "postremove": do_postremove,
2013 "preremove": do_preremove,
2014 "config": do_config,
2015 }
2016
2017 rc = 0
2018 for step in self.infoDict['steps']:
2019 self.xterm_title = xterm_header
2020 rc = steps_data.get(step)()
2021 if rc != 0: break
2022 return rc
2023
2024
2025 '''
2026 @description: execute the requested steps
2027 @input xterm_header: purely optional
2028 '''
2029 - def run(self, xterm_header = None):
2061
2062 '''
2063 Install/Removal process preparation function
2064 - will generate all the metadata needed to run the action steps, creating infoDict automatically
2065 @input matched_atom(tuple): is what is returned by EquoInstance.atom_match:
2066 (idpackage,repoid):
2067 (2000,u'sabayonlinux.org')
2068 NOTE: in case of remove action, matched_atom must be:
2069 (idpackage,)
2070 NOTE: in case of multi_fetch, matched_atom can be a list of matches
2071 @input action(string): is an action to take, which must be one in self.valid_actions
2072 '''
2073 - def prepare(self, matched_atom, action, metaopts = {}):
2083
2101
2131
2145
2294
2366
2433