1
2 '''
3 # DESCRIPTION:
4 # Entropy Object Oriented Interface
5
6 Copyright (C) 2007-2009 Fabio Erculiani
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 '''
22
23 import os
24 from entropy.const import etpConst
25 from entropy.output import blue, darkgreen, red, darkred, bold, purple, brown
26 from entropy.exceptions import IncorrectParameter, PermissionDenied
27 from entropy.i18n import _
28 from entropy.core import SystemSettings
29
31
32 import entropy.tools as entropyTools
33 from entropy.misc import Lifo
35
36 self.Output = OutputInterface
37 self.SystemSettings = SystemSettings()
38
39 if not hasattr(self.Output, 'updateProgress'):
40 mytxt = _("Output interface has no updateProgress method")
41 raise IncorrectParameter("IncorrectParameter: %s" % (mytxt,))
42 elif not callable(self.Output.updateProgress):
43 mytxt = _("Output interface has no updateProgress method")
44 raise IncorrectParameter("IncorrectParameter: %s" % (mytxt,))
45
47
48 repo = self.SystemSettings['repositories']['default_repository']
49
50 scan_msg = blue(_("Now searching for broken depends"))
51 self.Output.updateProgress(
52 "[repo:%s] %s..." % (
53 darkgreen(repo),
54 scan_msg,
55 ),
56 importance = 1,
57 type = "info",
58 header = red(" @@ ")
59 )
60
61 broken = False
62
63 count = 0
64 maxcount = len(idpackages)
65 for idpackage in idpackages:
66 count += 1
67 atom = dbconn.retrieveAtom(idpackage)
68 scan_msg = "%s, %s:" % (
69 blue(_("scanning for broken depends")),
70 darkgreen(atom),
71 )
72 self.Output.updateProgress(
73 "[repo:%s] %s" % (
74 darkgreen(repo),
75 scan_msg,
76 ),
77 importance = 1,
78 type = "info",
79 header = blue(" @@ "),
80 back = True,
81 count = (count, maxcount,)
82 )
83 mydepends = dbconn.retrieveDepends(idpackage)
84 if not mydepends:
85 continue
86 for mydepend in mydepends:
87 myatom = dbconn.retrieveAtom(mydepend)
88 self.Output.updateProgress(
89 "[repo:%s] %s => %s" % (
90 darkgreen(repo),
91 darkgreen(atom),
92 darkred(myatom),
93 ),
94 importance = 0,
95 type = "info",
96 header = blue(" @@ "),
97 back = True,
98 count = (count, maxcount,)
99 )
100 mycontent = dbconn.retrieveContent(mydepend)
101 mybreakages = self.content_test(mycontent)
102 if not mybreakages:
103 continue
104 broken = True
105 self.Output.updateProgress(
106 "[repo:%s] %s %s => %s" % (
107 darkgreen(repo),
108 darkgreen(atom),
109 darkred(myatom),
110 bold(_("broken libraries detected")),
111 ),
112 importance = 1,
113 type = "warning",
114 header = purple(" @@ "),
115 count = (count, maxcount,)
116 )
117 for mylib in mybreakages:
118 self.Output.updateProgress(
119 "%s %s:" % (
120 darkgreen(mylib),
121 red(_("needs")),
122 ),
123 importance = 1,
124 type = "warning",
125 header = brown(" ## ")
126 )
127 for needed in mybreakages[mylib]:
128 self.Output.updateProgress(
129 "%s" % (
130 red(needed),
131 ),
132 importance = 1,
133 type = "warning",
134 header = purple(" # ")
135 )
136 return broken
137
138
139 - def scan_missing_dependencies(self, idpackages, dbconn, ask = True,
140 self_check = False, repo = None, black_list = None,
141 black_list_adder = None):
142
143 if repo == None:
144 repo = self.SystemSettings['repositories']['default_repository']
145
146 if not isinstance(black_list, set):
147 black_list = set()
148
149 taint = False
150 scan_msg = blue(_("Now searching for missing RDEPENDs"))
151 self.Output.updateProgress(
152 "[repo:%s] %s..." % (
153 darkgreen(repo),
154 scan_msg,
155 ),
156 importance = 1,
157 type = "info",
158 header = red(" @@ ")
159 )
160 scan_msg = blue(_("scanning for missing RDEPENDs"))
161 count = 0
162 maxcount = len(idpackages)
163 for idpackage in idpackages:
164 count += 1
165 atom = dbconn.retrieveAtom(idpackage)
166 if not atom:
167 continue
168 self.Output.updateProgress(
169 "[repo:%s] %s: %s" % (
170 darkgreen(repo),
171 scan_msg,
172 darkgreen(atom),
173 ),
174 importance = 1,
175 type = "info",
176 header = blue(" @@ "),
177 back = True,
178 count = (count, maxcount,)
179 )
180 missing_extended, missing = self.get_missing_rdepends(dbconn,
181 idpackage, self_check = self_check)
182 missing -= black_list
183 for item in missing_extended.keys():
184 missing_extended[item] -= black_list
185 if not missing_extended[item]:
186 del missing_extended[item]
187 if (not missing) or (not missing_extended):
188 continue
189 self.Output.updateProgress(
190 "[repo:%s] %s: %s %s:" % (
191 darkgreen(repo),
192 blue("package"),
193 darkgreen(atom),
194 blue(_("is missing the following dependencies")),
195 ),
196 importance = 1,
197 type = "info",
198 header = red(" @@ "),
199 count = (count, maxcount,)
200 )
201 for missing_data in missing_extended:
202 self.Output.updateProgress(
203 "%s:" % (brown(unicode(missing_data)),),
204 importance = 0,
205 type = "info",
206 header = purple(" ## ")
207 )
208 for dependency in missing_extended[missing_data]:
209 self.Output.updateProgress(
210 "%s" % (darkred(dependency),),
211 importance = 0,
212 type = "info",
213 header = blue(" # ")
214 )
215 if ask:
216 rc_ask = self.Output.askQuestion(_("Do you want to add them?"))
217 if rc_ask == "No":
218 continue
219 rc_ask = self.Output.askQuestion(_("Selectively?"))
220 if rc_ask == "Yes":
221 newmissing = set()
222 new_blacklist = set()
223 for dependency in missing:
224 self.Output.updateProgress(
225 "[repo:%s|%s] %s" % (
226 darkgreen(repo),
227 brown(atom),
228 blue(dependency),
229 ),
230 importance = 0,
231 type = "info",
232 header = blue(" @@ ")
233 )
234 rc_ask = self.Output.askQuestion(_("Want to add?"))
235 if rc_ask == "Yes":
236 newmissing.add(dependency)
237 else:
238 rc_ask = self.Output.askQuestion(
239 _("Want to blacklist?"))
240 if rc_ask == "Yes":
241 new_blacklist.add(dependency)
242 if new_blacklist and (black_list_adder != None):
243 black_list_adder(new_blacklist, repo = repo)
244 missing = newmissing
245 if missing:
246 taint = True
247 dbconn.insertDependencies(idpackage, missing)
248 dbconn.commitChanges()
249 self.Output.updateProgress(
250 "[repo:%s] %s: %s" % (
251 darkgreen(repo),
252 darkgreen(atom),
253 blue(_("missing dependencies added")),
254 ),
255 importance = 1,
256 type = "info",
257 header = red(" @@ "),
258 count = (count, maxcount,)
259 )
260
261 return taint
262
263 - def content_test(self, mycontent):
264
265 def is_contained(needed, content):
266 for item in content:
267 if os.path.basename(item) == needed:
268 return True
269 return False
270
271 mylibs = {}
272 for myfile in mycontent:
273 myfile = myfile.encode('raw_unicode_escape')
274 if not os.access(myfile, os.R_OK):
275 continue
276 if not os.path.isfile(myfile):
277 continue
278 if not self.entropyTools.is_elf_file(myfile):
279 continue
280 mylibs[myfile] = self.entropyTools.read_elf_dynamic_libraries(
281 myfile)
282
283 broken_libs = {}
284 for mylib in mylibs:
285 for myneeded in mylibs[mylib]:
286
287 if is_contained(myneeded, mycontent):
288 continue
289 found = self.resolve_dynamic_library(myneeded, mylib)
290 if found:
291 continue
292 if not broken_libs.has_key(mylib):
293 broken_libs[mylib] = set()
294 broken_libs[mylib].add(myneeded)
295
296 return broken_libs
297
299
300 def do_resolve(mypaths):
301 found_path = None
302 for mypath in mypaths:
303 mypath = os.path.join(etpConst['systemroot']+mypath, library)
304 if not os.access(mypath, os.R_OK):
305 continue
306 if os.path.isdir(mypath):
307 continue
308 if not self.entropyTools.is_elf_file(mypath):
309 continue
310 found_path = mypath
311 break
312 return found_path
313
314 mypaths = self.entropyTools.collect_linker_paths()
315 found_path = do_resolve(mypaths)
316
317 if not found_path:
318 mypaths = self.entropyTools.read_elf_linker_paths(
319 requiring_executable)
320 found_path = do_resolve(mypaths)
321
322 return found_path
323
325
326 rdepends = {}
327 rdepends_plain = set()
328 neededs = dbconn.retrieveNeeded(idpackage, extended = True)
329 ldpaths = set(self.entropyTools.collect_linker_paths())
330 deps_content = set()
331 dependencies = self.get_deep_dependency_list(dbconn, idpackage,
332 atoms = True)
333 scope_cache = set()
334
335 def update_depscontent(mycontent, dbconn, ldpaths):
336 return set( \
337 [x for x in mycontent if os.path.dirname(x) in ldpaths \
338 and (dbconn.isNeededAvailable(os.path.basename(x)) > 0) ])
339
340 def is_in_content(myneeded, content):
341 for item in content:
342 item = os.path.basename(item)
343 if myneeded == item:
344 return True
345 return False
346
347 for dependency in dependencies:
348 match = dbconn.atomMatch(dependency)
349 if match[0] != -1:
350 mycontent = dbconn.retrieveContent(match[0])
351 deps_content |= update_depscontent(mycontent, dbconn, ldpaths)
352 key, slot = dbconn.retrieveKeySlot(match[0])
353 scope_cache.add((key, slot))
354
355 key, slot = dbconn.retrieveKeySlot(idpackage)
356 mycontent = dbconn.retrieveContent(idpackage)
357 deps_content |= update_depscontent(mycontent, dbconn, ldpaths)
358 scope_cache.add((key, slot))
359
360 idpackages_cache = set()
361 idpackage_map = {}
362 idpackage_map_reverse = {}
363 for needed, elfclass in neededs:
364 data_solved = dbconn.resolveNeeded(needed, elfclass)
365 data_size = len(data_solved)
366 data_solved = set([x for x in data_solved if x[0] \
367 not in idpackages_cache])
368 if not data_solved or (data_size != len(data_solved)):
369 continue
370
371 if self_check:
372 if is_in_content(needed, mycontent):
373 continue
374
375 found = False
376 for data in data_solved:
377 if data[1] in deps_content:
378 found = True
379 break
380 if not found:
381 for data in data_solved:
382 r_idpackage = data[0]
383 key, slot = dbconn.retrieveKeySlot(r_idpackage)
384 if (key, slot) not in scope_cache:
385 if not dbconn.isSystemPackage(r_idpackage):
386 if not rdepends.has_key((needed, elfclass)):
387 rdepends[(needed, elfclass)] = set()
388 if not idpackage_map.has_key((needed, elfclass)):
389 idpackage_map[(needed, elfclass)] = set()
390 keyslot = "%s:%s" % (key, slot,)
391 obj = idpackage_map_reverse.setdefault(
392 keyslot, set())
393 obj.add((needed, elfclass,))
394 rdepends[(needed, elfclass)].add(keyslot)
395 idpackage_map[(needed, elfclass)].add(r_idpackage)
396 rdepends_plain.add(keyslot)
397 idpackages_cache.add(r_idpackage)
398
399
400
401 r_deplist = set()
402 for key in idpackage_map:
403 r_idpackages = idpackage_map.get(key)
404 for r_idpackage in r_idpackages:
405 r_deplist |= dbconn.retrieveDependencies(r_idpackage)
406
407 r_keyslots = set()
408 for r_dep in r_deplist:
409 m_idpackage, m_rc = dbconn.atomMatch(r_dep)
410 if m_rc != 0:
411 continue
412 keyslot = dbconn.retrieveKeySlotAggregated(m_idpackage)
413 if keyslot in rdepends_plain:
414 r_keyslots.add(keyslot)
415
416 rdepends_plain -= r_keyslots
417 for r_keyslot in r_keyslots:
418 keys = [x for x in idpackage_map_reverse.get(keyslot, set()) if \
419 x in rdepends]
420 for key in keys:
421 rdepends[key].discard(r_keyslot)
422 if not rdepends[key]:
423 del rdepends[key]
424
425 return rdepends, rdepends_plain
426
428
429 mybuffer = self.Lifo()
430 matchcache = set()
431 depcache = set()
432 mydeps = dbconn.retrieveDependencies(idpackage)
433 for mydep in mydeps:
434 mybuffer.push(mydep)
435 mydep = mybuffer.pop()
436
437 while mydep:
438
439 if mydep in depcache:
440 mydep = mybuffer.pop()
441 continue
442
443 my_idpackage, my_rc = dbconn.atomMatch(mydep)
444 if atoms:
445 matchcache.add(mydep)
446 else:
447 matchcache.add(my_idpackage)
448
449 if my_idpackage != -1:
450 owndeps = dbconn.retrieveDependencies(my_idpackage)
451 for owndep in owndeps:
452 mybuffer.push(owndep)
453
454 depcache.add(mydep)
455 mydep = mybuffer.pop()
456
457
458 matchcache.discard(-1)
459 return matchcache
460
462
463 import entropy.tools as entropyTools
465 from entropy.misc import MultipartPostHandler
466 import urllib2
467 self.url = post_url
468 self.opener = urllib2.build_opener(MultipartPostHandler)
469 self.generated = False
470 self.params = {}
471
472 sys_settings = SystemSettings()
473 proxy_settings = sys_settings['system']['proxy']
474 mydict = {}
475 if proxy_settings['ftp']:
476 mydict['ftp'] = proxy_settings['ftp']
477 if proxy_settings['http']:
478 mydict['http'] = proxy_settings['http']
479 if mydict:
480 mydict['username'] = proxy_settings['username']
481 mydict['password'] = proxy_settings['password']
482 self.entropyTools.add_proxy_opener(urllib2, mydict)
483 else:
484
485 urllib2._opener = None
486
487 - def prepare(self, tb_text, name, email, report_data = "", description = ""):
488
489 import sys
490 from entropy.tools import getstatusoutput
491 self.params['arch'] = etpConst['currentarch']
492 self.params['stacktrace'] = tb_text
493 self.params['name'] = name
494 self.params['email'] = email
495 self.params['version'] = etpConst['entropyversion']
496 self.params['errordata'] = report_data
497 self.params['description'] = description
498 self.params['arguments'] = ' '.join(sys.argv)
499 self.params['uid'] = etpConst['uid']
500 self.params['system_version'] = "N/A"
501 if os.access(etpConst['systemreleasefile'], os.R_OK):
502 f_rel = open(etpConst['systemreleasefile'], "r")
503 self.params['system_version'] = f_rel.readline().strip()
504 f_rel.close()
505
506 self.params['processes'] = getstatusoutput('ps auxf')[1]
507 self.params['lspci'] = getstatusoutput('/usr/sbin/lspci')[1]
508 self.params['dmesg'] = getstatusoutput('dmesg')[1]
509 self.params['locale'] = getstatusoutput('locale -v')[1]
510
511 self.generated = True
512
513
515 if self.generated:
516 result = self.opener.open(self.url, self.params).read()
517 if result.strip() == "1":
518 return True
519 return False
520 else:
521 mytxt = _("Not prepared yet")
522 raise PermissionDenied("PermissionDenied: %s" % (mytxt,))
523