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