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 try:
1175 os.rmdir(rootdir)
1176 except OSError:
1177 pass
1178
1179 tolink = os.readlink(imagepathDir)
1180 live_tolink = None
1181 if os.path.islink(rootdir):
1182 live_tolink = os.readlink(rootdir)
1183 if tolink != live_tolink:
1184 if os.path.lexists(rootdir):
1185
1186 os.remove(rootdir)
1187 os.symlink(tolink, rootdir)
1188
1189 elif (not os.path.isdir(rootdir)) and (not os.access(rootdir,os.R_OK)):
1190 try:
1191
1192 os.mkdir(rootdir)
1193 except OSError:
1194 os.makedirs(rootdir)
1195
1196
1197 if not os.path.islink(rootdir) and os.access(rootdir,os.W_OK):
1198
1199
1200
1201 user = os.stat(imagepathDir)[stat.ST_UID]
1202 group = os.stat(imagepathDir)[stat.ST_GID]
1203 os.chown(rootdir,user,group)
1204 shutil.copystat(imagepathDir,rootdir)
1205
1206 items_installed.add(os.path.join(os.path.realpath(os.path.dirname(rootdir)),os.path.basename(rootdir)))
1207
1208 for item in files:
1209
1210 fromfile = "%s/%s" % (currentdir,item,)
1211 tofile = "%s%s" % (sys_root,fromfile[len(imageDir):],)
1212
1213 if col_protect > 1:
1214 todbfile = fromfile[len(imageDir):]
1215 myrc = self._handle_install_collision_protect(tofile, todbfile)
1216 if not myrc:
1217 continue
1218
1219 prot_old_tofile = tofile[len(sys_root):]
1220 pre_tofile = tofile[:]
1221 in_mask, protected, tofile, do_continue = self._handle_config_protect(
1222 protect, mask, fromfile, tofile)
1223
1224
1225 if in_mask and os.path.exists(fromfile):
1226 try:
1227 prot_md5 = self.entropyTools.md5sum(fromfile)
1228 self.infoDict['configprotect_data'].append(
1229 (prot_old_tofile,prot_md5,))
1230 except (IOError,):
1231 pass
1232
1233
1234 if protected:
1235
1236 try:
1237
1238
1239 oldprot_md5 = already_protected_config_files.get(
1240 prot_old_tofile)
1241
1242 if oldprot_md5 and os.path.exists(pre_tofile) and \
1243 os.access(pre_tofile, os.R_OK):
1244
1245 in_system_md5 = self.entropyTools.md5sum(pre_tofile)
1246 if oldprot_md5 == in_system_md5:
1247
1248
1249
1250 mytxt = "%s: %s" % (
1251 darkgreen(_("Automerging config file, never modified")),
1252 blue(pre_tofile),)
1253 self.Entropy.updateProgress(
1254 mytxt,
1255 importance = 1,
1256 type = "info",
1257 header = red(" ## ")
1258 )
1259 protected = False
1260 do_continue = False
1261 tofile = pre_tofile
1262
1263 except (IOError,):
1264 pass
1265
1266 if do_continue:
1267 continue
1268
1269 try:
1270
1271 if os.path.realpath(fromfile) == os.path.realpath(tofile) and os.path.islink(tofile):
1272
1273 try:
1274 os.remove(tofile)
1275 except OSError:
1276 pass
1277
1278
1279 if os.path.isdir(tofile) and not os.path.islink(tofile):
1280 self.Entropy.clientLog.log(
1281 ETP_LOGPRI_INFO,
1282 ETP_LOGLEVEL_NORMAL,
1283 "WARNING!!! %s is a directory when it should be a file !! Removing in 20 seconds..." % (tofile,)
1284 )
1285 mytxt = _("%s is a directory when it should be a file !! Removing in 20 seconds...") % (tofile,)
1286 self.Entropy.updateProgress(
1287 red("QA: ")+darkred(mytxt),
1288 importance = 1,
1289 type = "warning",
1290 header = red(" !!! ")
1291 )
1292 self.entropyTools.ebeep(10)
1293 time.sleep(20)
1294 try:
1295 shutil.rmtree(tofile, True)
1296 os.rmdir(tofile)
1297 except:
1298 pass
1299 try:
1300 os.remove(tofile)
1301 except OSError:
1302 pass
1303
1304
1305
1306
1307 done = movefile(fromfile, tofile, src_basedir = encoded_imageDir)
1308 if not done:
1309 self.Entropy.clientLog.log(
1310 ETP_LOGPRI_INFO,
1311 ETP_LOGLEVEL_NORMAL,
1312 "WARNING!!! Error during file move to system: %s => %s" % (fromfile,tofile,)
1313 )
1314 mytxt = "%s: %s => %s, %s" % (_("File move error"),fromfile,tofile,_("please report"),)
1315 self.Entropy.updateProgress(
1316 red("QA: ")+darkred(mytxt),
1317 importance = 1,
1318 type = "warning",
1319 header = red(" !!! ")
1320 )
1321 return 4
1322
1323 except IOError, e:
1324
1325
1326 if e.errno != 2: raise
1327
1328 items_installed.add(os.path.join(os.path.realpath(os.path.dirname(tofile)),os.path.basename(tofile)))
1329 if protected:
1330
1331 self.Entropy.FileUpdates.add_to_cache(tofile, quiet = True)
1332
1333
1334
1335
1336
1337 if self.infoDict.get('removecontent'):
1338 my_remove_content = set([x for x in self.infoDict['removecontent'] \
1339 if os.path.join(os.path.realpath(
1340 os.path.dirname("%s%s" % (sys_root,x,))),os.path.basename(x)
1341 ) in items_installed])
1342 self.infoDict['removecontent'] -= my_remove_content
1343
1344 return 0
1345
1346 - def _handle_config_protect(self, protect, mask, fromfile, tofile,
1347 do_allocation_check = True, do_quiet = False):
1348
1349 protected = False
1350 tofile_before_protect = tofile
1351 do_continue = False
1352 in_mask = False
1353
1354 try:
1355 encoded_protect = [x.encode('raw_unicode_escape') for x in protect]
1356 if tofile in encoded_protect:
1357 protected = True
1358 in_mask = True
1359 elif os.path.dirname(tofile) in encoded_protect:
1360 protected = True
1361 in_mask = True
1362 else:
1363 tofile_testdir = os.path.dirname(tofile)
1364 old_tofile_testdir = None
1365 while tofile_testdir != old_tofile_testdir:
1366 if tofile_testdir in encoded_protect:
1367 protected = True
1368 in_mask = True
1369 break
1370 old_tofile_testdir = tofile_testdir
1371 tofile_testdir = os.path.dirname(tofile_testdir)
1372
1373 if protected:
1374 newmask = [x.encode('raw_unicode_escape') for x in mask]
1375 if tofile in newmask:
1376 protected = False
1377 in_mask = False
1378 elif os.path.dirname(tofile) in newmask:
1379 protected = False
1380 in_mask = False
1381 else:
1382 tofile_testdir = os.path.dirname(tofile)
1383 old_tofile_testdir = None
1384 while tofile_testdir != old_tofile_testdir:
1385 if tofile_testdir in newmask:
1386 protected = False
1387 in_mask = False
1388 break
1389 old_tofile_testdir = tofile_testdir
1390 tofile_testdir = os.path.dirname(tofile_testdir)
1391
1392 if not os.path.lexists(tofile):
1393 protected = False
1394
1395
1396 if (protected) and os.path.isfile(tofile):
1397 protected = self.entropyTools.istextfile(tofile)
1398 in_mask = protected
1399 else:
1400 protected = False
1401
1402
1403 if protected:
1404 sys_set_plg_id = \
1405 etpConst['system_settings_plugins_ids']['client_plugin']
1406 client_settings = self.Entropy.SystemSettings[sys_set_plg_id]['misc']
1407 if tofile not in client_settings['configprotectskip']:
1408 prot_status = True
1409 if do_allocation_check:
1410 tofile, prot_status = self.entropyTools.allocate_masked_file(tofile, fromfile)
1411 if not prot_status:
1412 protected = False
1413 else:
1414 oldtofile = tofile
1415 if oldtofile.find("._cfg") != -1:
1416 oldtofile = os.path.join(os.path.dirname(oldtofile),
1417 os.path.basename(oldtofile)[10:])
1418 if not do_quiet:
1419 self.Entropy.clientLog.log(
1420 ETP_LOGPRI_INFO,
1421 ETP_LOGLEVEL_NORMAL,
1422 "Protecting config file: %s" % (oldtofile,)
1423 )
1424 mytxt = red("%s: %s") % (_("Protecting config file"),oldtofile,)
1425 self.Entropy.updateProgress(
1426 mytxt,
1427 importance = 1,
1428 type = "warning",
1429 header = darkred(" ## ")
1430 )
1431 else:
1432 if not do_quiet:
1433 self.Entropy.clientLog.log(
1434 ETP_LOGPRI_INFO,
1435 ETP_LOGLEVEL_NORMAL,
1436 "Skipping config file installation/removal, as stated in client.conf: %s" % (tofile,)
1437 )
1438 mytxt = "%s: %s" % (_("Skipping file installation/removal"),tofile,)
1439 self.Entropy.updateProgress(
1440 mytxt,
1441 importance = 1,
1442 type = "warning",
1443 header = darkred(" ## ")
1444 )
1445 do_continue = True
1446
1447 except Exception, e:
1448 self.entropyTools.print_traceback()
1449 protected = False
1450 tofile = tofile_before_protect
1451 mytxt = darkred("%s: %s") % (_("Cannot check CONFIG PROTECTION. Error"),e,)
1452 self.Entropy.updateProgress(
1453 red("QA: ")+mytxt,
1454 importance = 1,
1455 type = "warning",
1456 header = darkred(" ## ")
1457 )
1458
1459 return in_mask, protected, tofile, do_continue
1460
1461
1463 avail = self.Entropy.clientDbconn.isFileAvailable(todbfile, get_id = True)
1464 if (self.infoDict['removeidpackage'] not in avail) and avail:
1465 mytxt = darkred(_("Collision found during install for"))
1466 mytxt += " %s - %s" % (blue(tofile),darkred(_("cannot overwrite")),)
1467 self.Entropy.updateProgress(
1468 red("QA: ")+mytxt,
1469 importance = 1,
1470 type = "warning",
1471 header = darkred(" ## ")
1472 )
1473 self.Entropy.clientLog.log(
1474 ETP_LOGPRI_INFO,
1475 ETP_LOGLEVEL_NORMAL,
1476 "WARNING!!! Collision found during install for %s - cannot overwrite" % (tofile,)
1477 )
1478 return False
1479 return True
1480
1482 self.error_on_not_prepared()
1483 down_data = self.infoDict['download']
1484 down_keys = down_data.keys()
1485 d_cache = set()
1486 rc = 0
1487 key_cache = [os.path.basename(x) for x in down_keys]
1488 for key in sorted(down_keys):
1489 key_name = os.path.basename(key)
1490 if key_name in d_cache: continue
1491
1492 for url in down_data[key]:
1493 file_name = os.path.basename(url)
1494 if self.infoDict.get('fetch_path'):
1495 dest_file = os.path.join(self.infoDict['fetch_path'],
1496 file_name)
1497 else:
1498 dest_file = os.path.join(self.infoDict['unpackdir'],
1499 file_name)
1500 rc = self._fetch_source(url, dest_file)
1501 if rc == 0:
1502 d_cache.add(key_name)
1503 break
1504 key_cache.remove(key_name)
1505 if rc != 0 and key_name not in key_cache:
1506 break
1507 rc = 0
1508
1509 return rc
1510
1512 rc = 1
1513 try:
1514 mytxt = "%s: %s" % (blue(_("Downloading")),brown(url),)
1515
1516 self.Entropy.updateProgress(
1517 mytxt,
1518 importance = 1,
1519 type = "info",
1520 header = red(" ## ")
1521 )
1522
1523 rc, data_transfer, resumed = self.Entropy.fetch_file(
1524 url,
1525 None,
1526 None,
1527 False,
1528 fetch_file_abort_function = self.fetch_abort_function,
1529 filepath = dest_file
1530 )
1531 if rc == 0:
1532 mytxt = blue("%s: ") % (_("Successfully downloaded from"),)
1533 mytxt += red(self.entropyTools.spliturl(url)[1])
1534 mytxt += " %s %s/%s" % (_("at"),self.entropyTools.bytes_into_human(data_transfer),_("second"),)
1535 self.Entropy.updateProgress(
1536 mytxt,
1537 importance = 1,
1538 type = "info",
1539 header = red(" ## ")
1540 )
1541 self.Entropy.updateProgress(
1542 "%s: %s" % (blue(_("Local path")),brown(dest_file),),
1543 importance = 1,
1544 type = "info",
1545 header = red(" # ")
1546 )
1547 else:
1548 error_message = blue("%s: %s") % (
1549 _("Error downloading from"),
1550 red(self.entropyTools.spliturl(url)[1]),
1551 )
1552
1553 if rc == -1:
1554 error_message += " - %s." % (_("file not available on this mirror"),)
1555 elif rc == -3:
1556 error_message += " - not found."
1557 elif rc == -100:
1558 error_message += " - %s." % (_("discarded download"),)
1559 else:
1560 error_message += " - %s: %s" % (_("unknown reason"),rc,)
1561 self.Entropy.updateProgress(
1562 error_message,
1563 importance = 1,
1564 type = "warning",
1565 header = red(" ## ")
1566 )
1567 except KeyboardInterrupt:
1568 pass
1569 return rc
1570
1572 self.error_on_not_prepared()
1573 mytxt = "%s: %s" % (blue(_("Downloading archive")),
1574 red(os.path.basename(self.infoDict['download'])),)
1575 self.Entropy.updateProgress(
1576 mytxt,
1577 importance = 1,
1578 type = "info",
1579 header = red(" ## ")
1580 )
1581
1582 rc = 0
1583 if not self.infoDict['verified']:
1584 rc = self.Entropy.fetch_file_on_mirrors(
1585 self.infoDict['repository'],
1586 self.Entropy.get_branch_from_download_relative_uri(self.infoDict['download']),
1587 self.infoDict['download'],
1588 self.infoDict['checksum'],
1589 fetch_abort_function = self.fetch_abort_function
1590 )
1591 if rc != 0:
1592 mytxt = "%s. %s: %s" % (
1593 red(_("Package cannot be fetched. Try to update repositories and retry")),
1594 blue(_("Error")),
1595 rc,
1596 )
1597 self.Entropy.updateProgress(
1598 mytxt,
1599 importance = 1,
1600 type = "error",
1601 header = darkred(" ## ")
1602 )
1603 return rc
1604
1606 self.error_on_not_prepared()
1607 m_fetch_len = len(self.infoDict['multi_fetch_list'])
1608 mytxt = "%s: %s %s" % (blue(_("Downloading")),darkred(str(m_fetch_len)),_("archives"),)
1609 self.Entropy.updateProgress(
1610 mytxt,
1611 importance = 1,
1612 type = "info",
1613 header = red(" ## ")
1614 )
1615
1616 rc, err_list = self.Entropy.fetch_files_on_mirrors(
1617 self.infoDict['multi_fetch_list'],
1618 self.infoDict['checksum'],
1619 fetch_abort_function = self.fetch_abort_function
1620 )
1621 if rc != 0:
1622 mytxt = "%s. %s: %s" % (
1623 red(_("Some packages cannot be fetched. Try to update repositories and retry")),
1624 blue(_("Error")),
1625 rc,
1626 )
1627 self.Entropy.updateProgress(
1628 mytxt,
1629 importance = 1,
1630 type = "error",
1631 header = darkred(" ## ")
1632 )
1633 for repo, branch, fname, cksum, signatures in err_list:
1634 self.Entropy.updateProgress(
1635 "[%s:%s|%s] %s" % (blue(repo),brown(branch),
1636 darkgreen(cksum),darkred(fname),),
1637 importance = 1,
1638 type = "error",
1639 header = darkred(" # ")
1640 )
1641 return rc
1642
1644 self.Entropy.updateProgress(
1645 blue(_("Fetch for the chosen package is not available, unknown error.")),
1646 importance = 1,
1647 type = "info",
1648 header = red(" ## ")
1649 )
1650 return 0
1651
1653 self.Entropy.updateProgress(
1654 blue(_("Installed package in queue vanished, skipping.")),
1655 importance = 1,
1656 type = "info",
1657 header = red(" ## ")
1658 )
1659 return 0
1660
1664
1668
1670 self.error_on_not_prepared()
1671
1672 if not self.infoDict['merge_from']:
1673 mytxt = "%s: %s" % (blue(_("Unpacking package")),red(os.path.basename(self.infoDict['download'])),)
1674 self.Entropy.updateProgress(
1675 mytxt,
1676 importance = 1,
1677 type = "info",
1678 header = red(" ## ")
1679 )
1680 else:
1681 mytxt = "%s: %s" % (blue(_("Merging package")),red(os.path.basename(self.infoDict['atom'])),)
1682 self.Entropy.updateProgress(
1683 mytxt,
1684 importance = 1,
1685 type = "info",
1686 header = red(" ## ")
1687 )
1688 rc = self.__unpack_package()
1689 if rc != 0:
1690 if rc == 512:
1691 errormsg = "%s. %s. %s: 512" % (
1692 red(_("You are running out of disk space")),
1693 red(_("I bet, you're probably Michele")),
1694 blue(_("Error")),
1695 )
1696 else:
1697 errormsg = "%s. %s. %s: %s" % (
1698 red(_("An error occured while trying to unpack the package")),
1699 red(_("Check if your system is healthy")),
1700 blue(_("Error")),
1701 rc,
1702 )
1703 self.Entropy.updateProgress(
1704 errormsg,
1705 importance = 1,
1706 type = "error",
1707 header = red(" ## ")
1708 )
1709 return rc
1710
1712 self.error_on_not_prepared()
1713 mytxt = "%s: %s" % (
1714 blue(_("Installing package")),
1715 red(self.infoDict['atom']),
1716 )
1717 self.Entropy.updateProgress(
1718 mytxt,
1719 importance = 1,
1720 type = "info",
1721 header = red(" ## ")
1722 )
1723 if self.infoDict.get('description'):
1724 mytxt = "[%s]" % (purple(self.infoDict.get('description')),)
1725 self.Entropy.updateProgress(
1726 mytxt,
1727 importance = 1,
1728 type = "info",
1729 header = red(" ## ")
1730 )
1731
1732 rc = self.__install_package()
1733 if rc != 0:
1734 mytxt = "%s. %s. %s: %s" % (
1735 red(_("An error occured while trying to install the package")),
1736 red(_("Check if your system is healthy")),
1737 blue(_("Error")),
1738 rc,
1739 )
1740 self.Entropy.updateProgress(
1741 mytxt,
1742 importance = 1,
1743 type = "error",
1744 header = red(" ## ")
1745 )
1746 return rc
1747
1749 self.error_on_not_prepared()
1750 mytxt = "%s: %s" % (blue(_("Removing data")),red(self.infoDict['removeatom']),)
1751 self.Entropy.updateProgress(
1752 mytxt,
1753 importance = 1,
1754 type = "info",
1755 header = red(" ## ")
1756 )
1757 rc = self.__remove_package()
1758 if rc != 0:
1759 mytxt = "%s. %s. %s: %s" % (
1760 red(_("An error occured while trying to remove the package")),
1761 red(_("Check if you have enough disk space on your hard disk")),
1762 blue(_("Error")),
1763 rc,
1764 )
1765 self.Entropy.updateProgress(
1766 mytxt,
1767 importance = 1,
1768 type = "error",
1769 header = red(" ## ")
1770 )
1771 return rc
1772
1774 self.error_on_not_prepared()
1775 mytxt = "%s: %s" % (blue(_("Cleaning")),red(self.infoDict['atom']),)
1776 self.Entropy.updateProgress(
1777 mytxt,
1778 importance = 1,
1779 type = "info",
1780 header = red(" ## ")
1781 )
1782 self._cleanup_package(self.infoDict['unpackdir'])
1783
1784 return 0
1785
1787 for msg in self.infoDict['messages']:
1788 self.Entropy.clientLog.write(">>> "+msg)
1789 return 0
1790
1791 - def postinstall_step(self):
1792 self.error_on_not_prepared()
1793 pkgdata = self.infoDict['triggers'].get('install')
1794 if pkgdata:
1795 trigger = self.Entropy.Triggers('postinstall',pkgdata, self.action)
1796 do = trigger.prepare()
1797 if do:
1798 trigger.run()
1799 trigger.kill()
1800 del pkgdata
1801 return 0
1802
1804 self.error_on_not_prepared()
1805 pkgdata = self.infoDict['triggers'].get('install')
1806 if pkgdata:
1807
1808 trigger = self.Entropy.Triggers('preinstall',pkgdata, self.action)
1809 do = trigger.prepare()
1810 if self.infoDict.get("diffremoval") and do:
1811
1812
1813 remdata = self.infoDict['triggers'].get('remove')
1814 if remdata:
1815 r_trigger = self.Entropy.Triggers('preremove',remdata, self.action)
1816 r_trigger.prepare()
1817 r_trigger.triggers = [x for x in trigger.triggers if x not in r_trigger.triggers]
1818 r_trigger.kill()
1819 del remdata
1820 if do:
1821 trigger.run()
1822 trigger.kill()
1823
1824 del pkgdata
1825 return 0
1826
1838
1839 - def postremove_step(self):
1840 self.error_on_not_prepared()
1841 remdata = self.infoDict['triggers'].get('remove')
1842 if remdata:
1843
1844 trigger = self.Entropy.Triggers('postremove',remdata, self.action)
1845 do = trigger.prepare()
1846 if self.infoDict['diffremoval'] and (self.infoDict.get("atom") != None) and do:
1847
1848 pkgdata = self.infoDict['triggers'].get('install')
1849 if pkgdata:
1850 i_trigger = self.Entropy.Triggers('postinstall',pkgdata, self.action)
1851 i_trigger.prepare()
1852 i_trigger.triggers = [x for x in trigger.triggers if x not in i_trigger.triggers]
1853 i_trigger.kill()
1854 del pkgdata
1855 if do:
1856 trigger.run()
1857 trigger.kill()
1858
1859 del remdata
1860 return 0
1861
1863 self.error_on_not_prepared()
1864 for idpackage in self.infoDict['conflicts']:
1865 if not self.Entropy.clientDbconn.isIDPackageAvailable(idpackage):
1866 continue
1867 pkg = self.Entropy.Package()
1868 pkg.prepare((idpackage,),"remove_conflict", self.infoDict['remove_metaopts'])
1869 rc = pkg.run(xterm_header = self.xterm_title)
1870 pkg.kill()
1871 if rc != 0:
1872 return rc
1873
1874 return 0
1875
1877 self.error_on_not_prepared()
1878 mytxt = "%s: %s" % (blue(_("Configuring package")),red(self.infoDict['atom']),)
1879 self.Entropy.updateProgress(
1880 mytxt,
1881 importance = 1,
1882 type = "info",
1883 header = red(" ## ")
1884 )
1885 rc = self.__configure_package()
1886 if rc == 1:
1887 mytxt = "%s. %s. %s: %s" % (
1888 red(_("An error occured while trying to configure the package")),
1889 red(_("Make sure that your system is healthy")),
1890 blue(_("Error")),
1891 rc,
1892 )
1893 self.Entropy.updateProgress(
1894 mytxt,
1895 importance = 1,
1896 type = "error",
1897 header = red(" ## ")
1898 )
1899 elif rc == 2:
1900 mytxt = "%s. %s. %s: %s" % (
1901 red(_("An error occured while trying to configure the package")),
1902 red(_("It seems that the Source Package Manager entry is missing")),
1903 blue(_("Error")),
1904 rc,
1905 )
1906 self.Entropy.updateProgress(
1907 mytxt,
1908 importance = 1,
1909 type = "error",
1910 header = red(" ## ")
1911 )
1912 return rc
1913
1915 if xterm_header == None:
1916 xterm_header = ""
1917
1918 if self.infoDict.has_key('remove_installed_vanished'):
1919 self.xterm_title += ' Installed package vanished'
1920 self.Entropy.setTitle(self.xterm_title)
1921 rc = self.vanished_step()
1922 return rc
1923
1924 if self.infoDict.has_key('fetch_not_available'):
1925 self.xterm_title += ' Fetch not available'
1926 self.Entropy.setTitle(self.xterm_title)
1927 rc = self.fetch_not_available_step()
1928 return rc
1929
1930 def do_fetch():
1931 self.xterm_title += ' %s: %s' % (_("Fetching"),os.path.basename(self.infoDict['download']),)
1932 self.Entropy.setTitle(self.xterm_title)
1933 return self.fetch_step()
1934
1935 def do_multi_fetch():
1936 self.xterm_title += ' %s: %s %s' % (_("Multi Fetching"),
1937 len(self.infoDict['multi_fetch_list']),_("packages"),)
1938 self.Entropy.setTitle(self.xterm_title)
1939 return self.multi_fetch_step()
1940
1941 def do_sources_fetch():
1942 self.xterm_title += ' %s: %s' % (_("Fetching sources"),os.path.basename(self.infoDict['atom']),)
1943 self.Entropy.setTitle(self.xterm_title)
1944 return self.sources_fetch_step()
1945
1946 def do_checksum():
1947 self.xterm_title += ' %s: %s' % (_("Verifying"),os.path.basename(self.infoDict['download']),)
1948 self.Entropy.setTitle(self.xterm_title)
1949 return self.checksum_step()
1950
1951 def do_multi_checksum():
1952 self.xterm_title += ' %s: %s %s' % (_("Multi Verification"),
1953 len(self.infoDict['multi_checksum_list']),_("packages"),)
1954 self.Entropy.setTitle(self.xterm_title)
1955 return self.multi_checksum_step()
1956
1957 def do_unpack():
1958 if not self.infoDict['merge_from']:
1959 mytxt = _("Unpacking")
1960 self.xterm_title += ' %s: %s' % (mytxt,os.path.basename(self.infoDict['download']),)
1961 else:
1962 mytxt = _("Merging")
1963 self.xterm_title += ' %s: %s' % (mytxt,os.path.basename(self.infoDict['atom']),)
1964 self.Entropy.setTitle(self.xterm_title)
1965 return self.unpack_step()
1966
1967 def do_remove_conflicts():
1968 return self.removeconflict_step()
1969
1970 def do_install():
1971 self.xterm_title += ' %s: %s' % (_("Installing"),self.infoDict['atom'],)
1972 self.Entropy.setTitle(self.xterm_title)
1973 return self.install_step()
1974
1975 def do_remove():
1976 self.xterm_title += ' %s: %s' % (_("Removing"),self.infoDict['removeatom'],)
1977 self.Entropy.setTitle(self.xterm_title)
1978 return self.remove_step()
1979
1980 def do_logmessages():
1981 return self.logmessages_step()
1982
1983 def do_cleanup():
1984 self.xterm_title += ' %s: %s' % (_("Cleaning"),self.infoDict['atom'],)
1985 self.Entropy.setTitle(self.xterm_title)
1986 return self.cleanup_step()
1987
1988 def do_postinstall():
1989 self.xterm_title += ' %s: %s' % (_("Postinstall"),self.infoDict['atom'],)
1990 self.Entropy.setTitle(self.xterm_title)
1991 return self.postinstall_step()
1992
1993 def do_preinstall():
1994 self.xterm_title += ' %s: %s' % (_("Preinstall"),self.infoDict['atom'],)
1995 self.Entropy.setTitle(self.xterm_title)
1996 return self.preinstall_step()
1997
1998 def do_preremove():
1999 self.xterm_title += ' %s: %s' % (_("Preremove"),self.infoDict['removeatom'],)
2000 self.Entropy.setTitle(self.xterm_title)
2001 return self.preremove_step()
2002
2003 def do_postremove():
2004 self.xterm_title += ' %s: %s' % (_("Postremove"),self.infoDict['removeatom'],)
2005 self.Entropy.setTitle(self.xterm_title)
2006 return self.postremove_step()
2007
2008 def do_config():
2009 self.xterm_title += ' %s: %s' % (_("Configuring"),self.infoDict['atom'],)
2010 self.Entropy.setTitle(self.xterm_title)
2011 return self.config_step()
2012
2013 steps_data = {
2014 "fetch": do_fetch,
2015 "multi_fetch": do_multi_fetch,
2016 "multi_checksum": do_multi_checksum,
2017 "sources_fetch": do_sources_fetch,
2018 "checksum": do_checksum,
2019 "unpack": do_unpack,
2020 "remove_conflicts": do_remove_conflicts,
2021 "install": do_install,
2022 "remove": do_remove,
2023 "logmessages": do_logmessages,
2024 "cleanup": do_cleanup,
2025 "postinstall": do_postinstall,
2026 "preinstall": do_preinstall,
2027 "postremove": do_postremove,
2028 "preremove": do_preremove,
2029 "config": do_config,
2030 }
2031
2032 rc = 0
2033 for step in self.infoDict['steps']:
2034 self.xterm_title = xterm_header
2035 rc = steps_data.get(step)()
2036 if rc != 0: break
2037 return rc
2038
2039
2040 '''
2041 @description: execute the requested steps
2042 @input xterm_header: purely optional
2043 '''
2044 - def run(self, xterm_header = None):
2076
2077 '''
2078 Install/Removal process preparation function
2079 - will generate all the metadata needed to run the action steps, creating infoDict automatically
2080 @input matched_atom(tuple): is what is returned by EquoInstance.atom_match:
2081 (idpackage,repoid):
2082 (2000,u'sabayonlinux.org')
2083 NOTE: in case of remove action, matched_atom must be:
2084 (idpackage,)
2085 NOTE: in case of multi_fetch, matched_atom can be a list of matches
2086 @input action(string): is an action to take, which must be one in self.valid_actions
2087 '''
2088 - def prepare(self, matched_atom, action, metaopts = {}):
2098
2116
2146
2160
2315
2387
2454