5d60d8d41578ad59a02840387114d25ab2c9dcb6
[portpeek.git] / portpeek
1 #!/usr/bin/python
2 #
3 # Copyright 2006 Mike Pagano
4 # Distributed under the terms of the GNU General Public License v2
5 #
6 # $Header$
7 # Author: Mike Pagano <mpagano@gentoo.org>
8 #
9 # Portions written ripped from
10 # - equery, by Karl Trygve Kalleberg <karltk@gentoo.org>
11 # - gentoolkit.py, by Karl Trygve Kalleberg <karltk@gentoo.org>
12 # - portage.py
13 # - emerge
14 #
15 #
16
17 __author__ = "Michael Pagano"
18 __email__ = "mpagano@gentoo.org"
19 __version__ = "2.1.22"
20 __productname__ = "portpeek"
21 __description__ = "Displays user unmasked ebuilds and installable options from the portage tree"
22
23 import sys, os, portage, fileinput, re, gentoolkit
24 from gentoolkit.versionmatch import VersionMatch,errors
25 from portage.const import USER_CONFIG_PATH
26 from portage.versions import catpkgsplit,pkgcmp,pkgsplit
27 from portage.exception import InvalidAtom
28 from gentoolkit.cpv import CPV
29 from gentoolkit.package import Package
30 from gentoolkit.query import Query
31 from gentoolkit.flag import get_iuse
32
33 # support python 2
34 try:
35     input = raw_input
36 except NameError:
37     pass
38
39 porttree = portage.db[portage.root]["porttree"]
40 settings = portage.config(clone=portage.settings)
41 #settings = portage.config(local_config=False)
42
43 show_changes_only_flag = False
44 checking_package_unmask = False
45 checking_package_mask = False
46 print_overlay_flag = False
47 info = 0
48 debug = 1
49 logLevel = info
50 show_removable_only_flag = False
51 stable_list = []
52 stable_listNg = [] # handle package.accept_keywords
53 unmask_list = []
54 tilde = 0
55 processing_package_use = False
56 using_gentoo_as_overlay = False
57 overlay_list = []
58 fix_confirm = True
59 fix_asked = False
60 use_flag_dict = {}
61 useremove_display = ""
62 invalid_flag_found = False
63
64 try:
65     PORTAGE_CONFIGROOT
66 except NameError:
67     PORTAGE_CONFIGROOT="/"
68
69 USER_CONFIG_PATH=PORTAGE_CONFIGROOT + USER_CONFIG_PATH
70
71 #parameters
72 options = [
73 "--keyword",
74 "--unmask",
75 "--mask",
76 "--all",
77 "--changes-only",
78 "--version",
79 "--version",
80 "--help",
81 "--removable-only",
82 "--debug",
83 "--fix",
84 "--tilde-check",
85 "--no-color",
86 "--package-use",
87 "--fix-confirm"
88 ]
89
90 mappings = {
91 "k":"--keyword",
92 "u":"--unmask",
93 "m":"--mask",
94 "a":"--all",
95 "c":"--changes-only",
96 "V":"--version",
97 "v":"--version",
98 "h":"--help",
99 "r":"--removable-only",
100 "d":"--debug",
101 "f":"--fix",
102 "t":"--tilde-check",
103 "n":"--no-color",
104 "s":"--package-use",
105 "q":"--fix-confirm"
106 }
107
108 cmdline = []
109 overlays = [settings["PORTDIR_OVERLAY"]]
110
111 def print_usage():
112     # Print full usage information for this tool to the console.
113     print ("\nUsage: " + portage.output.turquoise(__productname__) +  portage.output.yellow(" command "))
114     print ("       " + portage.output.turquoise(__productname__) + portage.output.green(" [ options ]") +  portage.output.yellow(" command "))
115     print ("       " + portage.output.turquoise(__productname__) + portage.output.green(" [-c]") + portage.output.yellow(" [akmu]"))
116     print ("       " + portage.output.turquoise(__productname__) + portage.output.green(" [-r]") + portage.output.yellow(" [akmu]"))
117     print ("       " + portage.output.turquoise(__productname__) + portage.output.green(" [-f]") + portage.output.yellow(" [akmu]"))
118     print ("       " + portage.output.turquoise(__productname__) + portage.output.green(" [-F]") + portage.output.yellow(" [akmu]"))
119     print (portage.output.yellow(" command ") + " can be ")
120     print (portage.output.yellow(" -a, --all") + "       - show all matches")
121     print (portage.output.yellow(" -k, --keyword") + "       - show matches from package.keywords and package.accept_keywords only")
122     print (portage.output.yellow(" -m, --mask") + "      - show matches from package.mask only")
123     print (portage.output.yellow(" -u, --unmask") + "        - show matched from package.unmask only")
124     print (portage.output.yellow(" -s, --package.use") + "   - show matches from package.use only")
125
126     print (portage.output.yellow(" -f, --fix") + "       - will remove the stabled and invalid packages without asking for confirmation")
127     print (portage.output.yellow(" -q, --confirm-fix") +"    - will remove the stabled and invalid packages asking for confirmation before doing so")
128     print (portage.output.yellow(" -h, --help") + "      - display this message")
129     print (portage.output.yellow(" -d, --debug") + "         - display more verbose output for debugging")
130     print (portage.output.yellow(" -V, --version") + "       - display version info")
131     print (portage.output.green("options") + " are ")
132     print (portage.output.green(" -c, --changes-only") + \
133         "   - show all matches that have upgrade option, use with " + \
134         "<" + portage.output.yellow(" k ") + "|" + portage.output.yellow(" u ") + \
135         "|" + portage.output.yellow(" m ") + "|" + \
136         portage.output.yellow(" a ") + ">")
137     print (portage.output.green(" -n, --no-color") + \
138         "   - suppress color output")
139     print (portage.output.green(" -r, --removable-only") + \
140         "   - show all matches that can be removed from package files, use with " + \
141         "<" + portage.output.yellow(" k ") + "|" + portage.output.yellow(" u ") + \
142         "|" + portage.output.yellow(" m ") + "|" + \
143         portage.output.yellow(" a ") + ">\n")
144
145 def get_keywords(package, var):
146     mytree = porttree
147     filtered_keywords = ""
148     try:
149         keywords = package.environment("KEYWORDS").split()
150     except KeyError as error:
151         print ("!!! Portpeek caught Exception:" + format(error))
152         print ("!!! This package/version seems to be no longer available, " + \
153         "please check and update/unmerge it")
154         return "Not Available/Deprecated"
155
156     #filtered_keywords = filter_keywords(keywords[0])
157     filtered_keywords = filter_keywords(keywords)
158     return filtered_keywords
159
160
161
162 # this is the main function for portpeek
163 # TODO comment this code!
164 def parse_line(line, filename):
165     global info,debug,using_gentoo_as_overlay
166
167     using_gentoo_as_overlay = False
168     pkgs = None
169     ebuild_output = ""
170     check_pkg = ""
171     not_installed_pkgs = 0
172     pkg_length = 0
173     atom_check="<>=~"
174     original_line = line
175     has_asterick = False
176
177     # if the line has special characters, we need to make sure the original line is used for matching
178     special_line = False
179
180     pattern=r'[<>:*]'
181
182     if ( (re.search(pattern,line) != None) ):
183         special_line = True
184
185     if check_pkg.endswith('*'):
186         has_asterick = True
187
188     print_output(debug,portage.output.blue("Analyzing line: " + line))
189
190     diffs_found = False
191     display_done = False
192
193     fields = line.replace("\t", " ").split(" ")
194
195     if len(fields) > 0:
196         #if the line does not start with an atom such as (= or >), do not validate
197         #status as this tool is for check specific versions and not entire packages
198         # a ~cpv should be handled like an =cpv if requested bythe parameter -t
199         check_pkg = fields[0] # this should be one of <>=~
200         orig_pkg_name = check_pkg
201         overlay_index = check_pkg.find("::")
202         if ( overlay_index >= 0):
203             overlay_list = check_pkg.rsplit("::")
204             if (len(overlay_list) > 0):
205                 overlay_name = overlay_list[1]
206                 if (overlay_name == "gentoo"):
207                     using_gentoo_as_overlay = True
208             check_pkg = check_pkg[0:check_pkg.find("::")]
209
210         if check_pkg[0] not in atom_check:
211
212             # if this is package_unmask, then check the non-atom containing package to see if any version is masked
213
214             if (checking_package_unmask == True):
215
216                 print_output(debug,portage.output.blue("check_pkg is " + check_pkg + " found"))
217                 if (is_any_cpv_keyword_masked(check_pkg) == False):
218                     print_output(info,portage.output.red("No masked versions of " + check_pkg + " found. Tagged for removal."))
219                     unmask_list.append(str(check_pkg))
220             return
221         if (tilde == 1):
222             if check_pkg[0] in "~":
223                 check_tilde_masked_pkg(check_pkg, filename)
224                 return
225
226         # determine if the package exists
227         try:
228             package_exists = portage.portdb.xmatch("match-all", fields[0])
229         except InvalidAtom:
230             package_exists = False
231
232         if package_exists:
233             # return a Package List based on the cpv
234             query = Query(check_pkg)
235             #query = Query(fields[0])
236             pkgs = []
237
238             try:
239                 pkgs = query.smart_find(True,True,True,True,False,True)
240             except errors.GentoolkitException as err:
241                 pass
242
243             if (pkgs != None):
244                 pkg_length = len(pkgs)
245                 not_installed_pkgs = 0
246                 display_done = False
247
248                 # go through each package version for a specific version found above
249                 for current_package in pkgs:
250                     if not current_package.is_installed():
251
252                         # we have found a package that is in our file, but not installed
253                         not_installed_pkgs = not_installed_pkgs + 1
254
255                         # check to see if specific version of pkg is not installed
256                         # and display if true
257                         check_pkg = fields[0]
258                         if check_pkg[0] in atom_check:
259                             check_pkg = check_pkg[1:]
260
261                         if (check_pkg == str(current_package.cpv)):
262                             if (not checking_package_mask):
263                                 # package is not installed
264                                 print_output(info,portage.output.yellow("\n" + orig_pkg_name + ": ") + portage.output.red("Not Installed") , current_package, filename)
265                                 if "package.keywords" in filename:
266                                     stable_list.append(str(current_package.cpv))
267                                 if "package.accept_keywords" in filename:
268                                     stable_listNg.append(str(current_package.cpv))
269                                 unmask_list.append(str(current_package.cpv))
270                             else:
271                                 # package is masked, and not installed, this is normal use of package.mask
272                                 print_output(info,portage.output.green("" + orig_pkg_name + ": ") + portage.output.yellow("Package Masked"),current_package, filename)
273                             display_done = True
274                         continue
275
276                     # package is installed
277                     # retrieve the keywords for a file
278                     keywords = "%s" % (get_keywords(current_package,"KEYWORDS").split())
279                     if (keywords.find("Available/Deprecated") >= 0):
280                         continue
281
282                     #retrieve the mask status of a specific package
283                     pkgmask = _get_mask_status(current_package, False)
284
285                     #determine if installed package is unmasked, if so, display keywords as green
286                     stable = check_for_stable_release(current_package)
287
288                     # do not display if keywords don't exist
289                     if keywords == "[]":
290                         continue
291
292                     if stable:
293                         if ( not has_asterick): # if it has an asterick, then we don't remove
294                             ebuild_output = portage.output.green("Installed: ") + \
295                                 portage.output.turquoise(orig_pkg_name) + \
296                                 portage.output.green("  Keywords " + keywords)
297                             if "package.unmask" in filename:
298                                 unmask_list.append(str(current_package.cpv))
299                             if "package.keywords" in filename:
300                                 stable_list.append(str(current_package.cpv))
301                             if "package.accept_keywords" in filename:
302                                 stable_listNg.append(str(current_package.cpv))
303                     else:
304                         if (not show_removable_only_flag):
305                             if (not checking_package_unmask):
306                                 ebuild_output = portage.output.green("Installed: ") + \
307                                 portage.output.turquoise(orig_pkg_name) + \
308                                 portage.output.yellow("  Keywords " + keywords)
309                         else:
310                             ebuild_output = portage.output.yellow(str(current_package.cpv))
311
312                     # check package.unmask
313                     if (checking_package_unmask):
314                         if (not is_any_cpv_file_masked(str(current_package.cpv))):
315
316                             # package is in package.unmask unnecessarily
317                             ebuild_output = portage.output.yellow("\n" + orig_pkg_name  + ": ") + portage.output.green("Not package masked")
318                             if "package.unmask" in filename:
319                                 unmask_list.append(orig_pkg_name)
320                                 print_output (info, "" +  ebuild_output,None, filename)
321                                 continue
322
323                     # print once
324                     ebuild_search_key_printed = False
325                     if ( not has_asterick): # if it has an asterick, then we don't remove
326                         if stable:
327                             diffs_found = False
328                             ebuild_search_key_printed = True
329                             print_output(info,"\n" + ebuild_output,current_package, filename)
330                         elif not show_changes_only_flag and not show_removable_only_flag:
331                             diffs_found = False
332                             ebuild_search_key_printed = True
333                             print_output(info,"\n" + ebuild_output,current_package)
334
335                     # go through all versions of a package
336                     query = Query(current_package.category + "/" + current_package.name)
337
338                     all_pkgs = []
339
340                     try:
341                         all_pkgs = query.smart_find(True,True,True,True,False,True)
342                     except errors.GentoolkitException as err:
343                         print_output(debug,portage.output.blue("Package " + current_package.category + "/" + current_package.name + " not found."))
344
345                     for a_package in all_pkgs:
346                         if not a_package.is_installed():
347                             # a_package is not installed
348                             pkgmask = _get_mask_status(a_package, False)
349                             # print status line of package we are now checking
350                             print_output(debug,portage.output.blue("Checking package: " + str(a_package.cpv) +".pkgmask is " + str(pkgmask)))
351                             # if package versions are different
352                             if (VersionMatch(CPV(current_package.cpv)).match(CPV(a_package.cpv))):
353                                 diffs_found = True
354                                 keylist = a_package.environment("KEYWORDS")
355                                 keywords = "%s" % (filter_keywords(keylist)).split()
356                                 #if a_package is masked
357                                 if pkgmask > 0 and not show_removable_only_flag:
358                                     if show_changes_only_flag and not ebuild_search_key_printed:
359                                         print_output (info, "\n" +  ebuild_output, current_package)
360                                         ebuild_search_key_printed = True
361                                         check_for_stable_release(current_package)
362                                     if (pkgmask >= 3):
363                                         print_output (info,portage.output.red("Available: " + str(a_package.cpv) + " [M] Keywords: " + keywords),a_package)
364                                     else:
365                                         print_output (info,portage.output.brown("Available: " + str(a_package.cpv) + " Keywords: " + keywords),a_package)
366                                 else:
367                                     if show_changes_only_flag and not ebuild_search_key_printed:
368                                         print_output (info,"\n" + ebuild_output,current_package)
369                                         ebuild_search_key_printed = True
370                                         print_output(info,portage.output.green("Available: " + str(a_package.cpv) + " Keywords: " + keywords),a_package)
371                 #else:
372                     #print (portage.output.red ("\nCannot find package: " + check_pkg))
373
374                 # if package does not exist, and current_package is None
375                 # then make package using fields[0]
376
377                 # display if pkg/cat is not installed (missing version)
378                 if not_installed_pkgs ==  pkg_length:
379                     if not display_done:
380                         if (not checking_package_mask):
381                             print_output(info,portage.output.yellow("\n" + fields[0] + ": ") + portage.output.red("Not Installed"),current_package)
382                             if "package.keywords" in filename:
383                                 if (special_line == False):
384                                     stable_list.append(str(current_package.cpv))
385                                 else:
386                                     stable_list.append(original_line)
387                             if "package.accept_keywords" in filename:
388                                 if (special_line == False):
389                                     stable_listNg.append(str(current_package.cpv))
390                                 else:
391                                     stable_listNg.append(original_line)
392                             if (special_line == False):
393                                 unmask_list.append(str(current_package.cpv))
394                             else:
395                                 unmask_list.append(original_line)
396                         else:
397                             print_output (info,portage.output.green("\n" + str(current_package.cpv) + ": ") + portage.output.yellow("Package Masked"),current_package)
398         else:
399             diffs_found = True
400             if "package.keywords" in filename:
401                 stable_list.append(fields[0])
402                 print (portage.output.red ("\nPackage: " + fields[0] + " not found. Please check " + filename + " to validate entry"))
403             if "package.accept_keywords" in filename:
404                 stable_listNg.append(fields[0])
405                 print (portage.output.red ("\nPackage: " + fields[0] + " not found. Please check " + filename + " to validate entry"))
406
407             if "package.unmask" in filename:
408                 package_name = fields[0]
409                 if package_name[0] in atom_check:
410                     package_name = package_name[1:]
411                 port = Package(package_name)
412                 package_exists = portage.portdb.xmatch("match-all", package_name)
413                 # if package is not installed or does not exist remove it
414                 if ( ( not package_exists ) or (not port.is_installed())):
415                     print (portage.output.red ("\nPackage: " + fields[0] + " not found. Please check " + filename + " to validate entry"))
416                     unmask_list.append(fields[0])
417
418             show_all_versions(fields[0], filename)
419     current_package = ""
420
421     return diffs_found
422
423 # adding support for etc/portage/package.keywords/<whatever>/package.keywords
424 def get_recursive_info(filename):
425
426     # determine if filename is a directory
427     if os.path.isdir(filename):
428         # get listing of directory
429         filenames = os.listdir(filename)
430         for file_name in filenames:
431             get_recursive_info(filename+os.path.sep+file_name)
432     else:
433         get_info(filename)
434
435 def get_info(filename):
436
437     diffs_found = False
438     no_file = False
439     filedescriptor = None
440
441     try:
442         filedescriptor = open(filename)
443         for line in filedescriptor.readlines():
444             line = line.strip()
445             if len(line) <= 0:
446                 continue
447             elif line.find("#") >= 0:
448                 # found '#' remove comment
449                 if (skipFile(line,filename)):
450                     return
451                 line = line[0:line.find("#")]
452                 line = line.strip()
453                 if len(line) <= 0:
454                     continue
455             if (processing_package_use == False):
456                 diffs_found = parse_line(line, filename)
457             else:
458                 # process package.use
459                 diffs_found = parse_package_use(line,filename)
460     except IOError:
461         print (portage.output.red("Could not find file " + filename))
462         no_file = True
463     except UnicodeDecodeError:
464         return
465
466     if not diffs_found and no_file:
467         print (portage.output.brown("No ebuild options found."))
468
469     # close file
470     if (filedescriptor != None):
471         filedescriptor.close()
472
473 # parse the package.use file and look for packages
474 # not installed
475 def parse_package_use(line, filename):
476
477     global info,debug
478     print_output(debug,portage.output.blue("parse_package_use: Line: " + line))
479
480     pkgs = None
481     check_pkg = ""
482     pkg_length = 0
483     atom_check="<>="
484     any_version = False
485     has_atom = True
486     has_asterick = False
487
488     diffs_found = False
489     package_installed = False
490     fields = line.replace("\t", " ").split(" ")
491     less_than = False
492     less_than_or_equal = False
493
494     if len(fields) > 0:
495         check_pkg = fields[0] # this could be one of <>=
496
497         if check_pkg.endswith('*'):
498             has_asterick = True
499
500         display_pkg_name = fields[0]
501         orig_pkg_name = check_pkg
502         if check_pkg[0] not in atom_check:
503             has_atom = False
504         else:
505             if check_pkg[0] == '<':
506                 less_than = True;
507                 if check_pkg[1] == '=':
508                     less_than_or_equal = True
509
510             check_pkg = check_pkg[1:]
511             if check_pkg[0] in atom_check:
512                 check_pkg = check_pkg[1:]
513
514
515         # if there is a wildcard, check to make sure at least one
516         # of the packages is installed
517         #check_pkg = "=dev-qt/qtwebkit-4.8*"
518
519         if check_pkg.find("/*") >= 0:
520             query = Query(check_pkg)
521             pkgs = []
522             try:
523                 pkgs = query.smart_find(True,True,True,True,False,True)
524             except errors.GentoolkitException as err:
525                 print_output(debug,portage.output.blue("parse_package_use: Package " + check_pkg + " not found."))
526                 return False
527
528             if (pkgs != None):
529                 pkg_length = len(pkgs)
530             for current_package in pkgs:
531
532                 # on wildcard scenario, return False if one package is installed
533                 if current_package.is_installed():
534                     check_useflags(current_package,line)
535                     return False
536         check_pkg = (check_pkg.rsplit(':',1))[0]
537         if ((orig_pkg_name.find("<=") >=0)
538             or (orig_pkg_name.find("<")>=0)
539             or (orig_pkg_name.find(">=") >=0)
540             or (orig_pkg_name.find(">") >=0)):
541
542             query = Query(check_pkg)
543             pkgs = []
544             try:
545                 pkgs = query.smart_find(True,True,True,True,False,True)
546             except errors.GentoolkitException as err:
547                 print_output(debug,portage.output.blue("parse_package_use: Package " + check_pkg + " not found."))
548                 return False
549
550             if (pkgs != None):
551                 pkg_length = len(pkgs)
552             for current_package in pkgs:
553                 # on wildcard scenario, return False if one package is installed
554                 if (orig_pkg_name.find("<=") >=0):
555                     if (pkgcmp(pkgsplit(check_pkg),pkgsplit(str(current_package.cpv))) == 1) or \
556                         (pkgcmp(pkgsplit(check_pkg),pkgsplit(str(current_package.cpv))) == 0):
557                         if current_package.is_installed():
558                             check_useflags(current_package,line)
559                         return False
560                 else:
561                     if (orig_pkg_name.find("<") >=0):
562                         if (pkgcmp(pkgsplit(check_pkg),pkgsplit(str(current_package.cpv))) == 1):
563                             if current_package.is_installed():
564                                 check_useflags(current_package,line)
565                             return False
566                 if (orig_pkg_name.find(">=") >=0):
567                     while (check_pkg[0] in atom_check):
568                         check_pkg = check_pkg[1:]
569
570                     result = pkgcmp(pkgsplit(check_pkg),pkgsplit(str(current_package.cpv)))
571                     if (pkgcmp(pkgsplit(check_pkg),pkgsplit(str(current_package.cpv))) == -1) or \
572                         (pkgcmp(pkgsplit(check_pkg),pkgsplit(str(current_package.cpv))) == 0):
573                         if current_package.is_installed():
574                             check_useflags(current_package,line)
575                         return False
576                 else:
577                     if (orig_pkg_name.find(">") >=0):
578                         if (pkgcmp(pkgsplit(check_pkg),pkgsplit(str(current_package.cpv))) == -1 ):
579                             if current_package.is_installed():
580                                 check_useflags(current_package,line)
581                             return False
582         else:
583             # look for any version of check_pkg installed as there is
584             # no version specified in package.use
585
586             package_exists = portage.portdb.xmatch("match-all", check_pkg)
587             if package_exists:
588                 # get all package versions
589                 query = Query(check_pkg)
590                 pkgs = []
591                 try:
592                     pkgs = query.smart_find(True,True,True,True,False,True)
593                 except errors.GentoolkitException as err:
594                     print_output(debug,portage.output.blue("Package " + check_pkg + " not found."))
595
596                 if (pkgs != None and len(pkgs)>0):
597                     pkg_length = len(pkgs)
598
599                     # go through each package version for a specific
600                     # version found above
601                     # if one line check returns all ok, we don't need
602                     #to check the rest. One slot could have different
603                     #use flags than another
604                     if (has_atom == False):
605                         check_useflags_all_versions(pkgs, line, check_pkg)
606                         package_installed = check_for_any_installed_version(pkgs)
607                         current_package = None
608
609                         #for current_package in pkgs:
610                         #    if current_package.is_installed():
611                         #        check_useflags(current_package,line)
612                         #        package_installed = True
613                         #        if (invalid_flag_found == False):
614                         #            break;
615                     else:
616                         # go through each package version for a specific version found above
617                         for current_package in pkgs:
618                             if (not has_asterick and not atom_check):
619                                 if (str(current_package.cpv) == check_pkg):
620                                     if not current_package.is_installed():
621                                         print_output(info,portage.output.yellow("\n" + orig_pkg_name + ": ") + portage.output.red("Not Installed"),current_package)
622                                         if "package.keywords" in filename:
623                                             stable_list.append(check_pkg)
624                                         if "package.accept_keywords" in filename:
625                                             stable_listNg.append(check_pkg)
626                                         unmask_list.append(check_pkg)
627                                         if "package.use" in filename:
628                                             valid_flag_list = []
629                                             valid_flag_list.insert(0,current_package);
630                                             use_flag_dict[line] = valid_flag_list
631                                             check_for_change = use_flag_dict[line]
632                                         return True
633                                     else:
634                                         check_useflags(current_package,line)
635                                         return False
636                             else:
637                                 if current_package.is_installed():
638                                     check_useflags(current_package,line)
639                                     return False
640
641
642                         # if we are here, we have a =<category>/package-PN* and none of them are installed
643                         print_output(info,portage.output.yellow("\n" + orig_pkg_name + ": ") +
644                             portage.output.red("Not Installed"),current_package)
645                         if "package.keywords" in filename:
646                             stable_list.append(check_pkg)
647                         if "package.accept_keywords" in filename:
648                             stable_listNg.append(check_pkg)
649                         unmask_list.append(check_pkg)
650                         if "package.use" in filename:
651                             valid_flag_list = []
652                             valid_flag_list.insert(0,current_package);
653                             use_flag_dict[line] = valid_flag_list
654                             check_for_change = use_flag_dict[line]
655                         return True
656             else:
657                 print (portage.output.red ("\nPackage: " + fields[0] + " not found. Please check " + filename + " to validate entry"))
658                 if "package.keywords" in filename:
659                     stable_list.append(check_pkg)
660                 if "package.accept_keywords" in filename:
661                     stable_listNg.append(check_pkg)
662                 unmask_list.append(check_pkg)
663                 if "package.use" in filename:
664                     valid_flag_list = []
665                     #valid_flag_list.insert(0,current_package);
666                     valid_flag_list.insert(0,fields[0]);
667                     use_flag_dict[line] = valid_flag_list
668                     check_for_change = use_flag_dict[line]
669                 return True
670
671     if (package_installed == False):
672         print_output(info,portage.output.yellow("\n" + orig_pkg_name + ": ") + portage.output.red(" Not Installed"))
673
674         if "package.keywords" in filename:
675             stable_list.append(check_pkg)
676         if "package.accept_keywords" in filename:
677             stable_listNg.append(check_pkg)
678         if "package.use" in filename:
679             valid_flag_list = []
680             valid_flag_list.insert(0,display_pkg_name);
681             use_flag_dict[line] = valid_flag_list
682             check_for_change = use_flag_dict[line]
683
684         unmask_list.append(check_pkg)
685         return True
686
687     return False
688
689
690
691
692 # skip the file if portpeek-skip found in a comment
693 # you can put this in the middle of a file and it will
694 #skip all entrie below it, this is useful to speed things
695 #up by not checking ~kde versions, for example
696 def skipFile (line, filename):
697     if ( (line == None) or (filename == None)):
698         return False
699
700     if line.find("portpeek-skip") >= 0:
701         return True
702
703     return False
704
705 # parts blatantly stolen from equery
706 # if pure is true, then get "true" mask status that is
707 # not affected by entries in /etc/portage/package.*
708 def _get_mask_status(pkg, pure):
709     pkgmask = 0
710
711     if (pkg == None):
712         return 0
713
714     if pkg.is_masked():
715         pkgmask = pkgmask + 3
716
717     if pure:
718         try:
719             keywords = portage.portdb.aux_get(str(pkg.cpv), ["KEYWORDS"])
720             keywords = keywords[0].split()
721         except KeyError:
722             # cpv does not exist
723             return 0
724     else:
725         keywords = pkg.environment("KEYWORDS").split()
726
727     # first check for stable arch, stop there if it is found
728     if settings["ARCH"] in keywords:
729         return 0
730
731     if "~" + settings["ARCH"] in keywords:
732         pkgmask = pkgmask + 1
733     elif "-*" in keywords or "-" + settings["ARCH"] in keywords:
734         pkgmask = pkgmask + 2
735
736     return pkgmask
737
738 def is_pkg_package_masked(cpv):
739
740     print_output(debug,portage.output.blue("is_pkg_package_masked called: " + cpv))
741     settings2 = portage.config(local_config=False)
742     portdb2 = portage.portdbapi(None, settings)
743
744     mask_reason_list = None
745
746     try:
747         for mask_reason_list in portage.getmaskingstatus(cpv, settings2, portdb=portdb2):
748             return True
749     except:
750         return False
751
752     return False
753
754 # filter out keywords for archs other than the current one
755 def filter_keywords(keywords):
756     filtered_keywords = ""
757
758     #for key in key_list:
759     for key in keywords:
760         key = key.replace("[", '')
761         key = key.replace("]", "")
762         key = key.replace(",", "")
763         arch=settings["ARCH"]
764
765         # remove '~' from key for comparison
766         key_comparison = key.lstrip('~')
767         if key_comparison == arch:
768             if len(filtered_keywords) != 0:
769                 filtered_keywords = filtered_keywords + " "
770             filtered_keywords = filtered_keywords + key
771         elif "-*" in key:
772             if len(filtered_keywords) != 0:
773                 filtered_keywords = filtered_keywords + " "
774             filtered_keywords = filtered_keywords + key
775
776
777     return filtered_keywords
778
779
780 # this function takes in a package with no cpv
781 # and returns True if any version is masked
782 def is_any_cpv_keyword_masked(package_name):
783     print_output(debug,portage.output.blue("inside is_any_cpv_keyword_masked: " + package_name))
784
785     query = Query(package_name, True)
786
787     packages = []
788     try:
789         packages = query.smart_find(True,True,True,True,False,True)
790     except errors.GentoolkitException as err:
791         print_output(debug,portage.output.blue("Package " + package_name + " not found."))
792
793     for package in packages:
794         if is_pkg_package_masked(package.cpv):
795             print_output(debug,portage.output.blue("Package " + package.cpv + " is masked."))
796             return True
797
798     print_output(debug,portage.output.blue("Package " + package_name + ". No masked versions."))
799     return False
800
801 # we need to know if the package is masked
802 # by being present in the package.mask file
803 # as opposed to masked by keyword.
804 # if it's not, then we can remove from package.unmask
805 def is_any_cpv_file_masked(package_name):
806
807     print_output(debug,portage.output.blue("is_any_cpv_file_masked called: " + package_name))
808     settings2 = portage.config(local_config=False)
809     portdb2 = portage.portdbapi(None, settings)
810
811     mask_reason_list = None
812
813     try:
814         for mask_reason_list in portage.getmaskingstatus(package_name, settings2, portdb=portdb2):
815             print_output(debug,portage.output.blue("Mask Reason is " + mask_reason_list))
816             if (mask_reason_list == 'package.mask'):
817                 return True
818     except:
819         return False
820
821     return False
822
823
824
825 # check to see if we have a stable release
826 # in our package.* files that we can remove
827 def check_for_stable_release(pkg):
828     if not is_pkg_package_masked(str(pkg.cpv)):
829         status = _get_mask_status(pkg, True)
830         if status == 0:
831             return True
832     return False
833
834 #print version info
835 def print_version():
836     # Print the version of this tool to the console.
837     print (__productname__ + "(" + __version__ + ") - " + \
838         __description__)
839     print ("Author(s): " + __author__)
840
841 # function to go through a ~cp without a version
842 # and set for removal from file if no masked package version exists
843 def check_tilde_masked_pkg(package_name, filename):
844     ebuild_output=""
845     variable_version = ""
846
847     orig_package_name = package_name
848     package_name = package_name.replace('~','')
849
850     print_output(debug,portage.output.blue("check_tilde_maskd_pkg: orig_package-name is " + orig_package_name))
851     print_output(debug,portage.output.blue("check_tilde_maskd_pkg: package_name is " + package_name))
852
853     query = Query(package_name, True)
854
855     packages = []
856     try:
857         packages = query.smart_find(True,True,True,True,False,True)
858     except errors.GentoolkitException as err:
859         print_output(debug,portage.output.blue("Package " + package_name + " not found."))
860
861     no_versions_installed = True
862     for package in packages:
863         if package.is_installed():
864             no_versions_installed = False
865
866     if (no_versions_installed == True):
867         ebuild_output = portage.output.yellow("\n" + package_name + ": ") + portage.output.red("Not Installed")
868         if "package.unmask" in filename:
869             unmask_list.append(orig_package_name)
870         if "package.keywords" in filename:
871             stable_list.append(orig_package_name)
872         if "package.accept_keywords" in filename:
873             stable_listNg.append(orig_package_name)
874         print (ebuild_output + portage.output.brown(" : " + filename))
875
876         return
877
878     # get all packages matching cat/package
879     if (packages != None):
880         for current_package in packages:
881             print_output(debug,portage.output.blue("check_tilde_maskd_pkg: current_package is " + str(current_package.cpv)))
882             print_output(debug,portage.output.blue("comparing " + package_name + " to " + str(current_package.cpv)))
883             if (pkgcmp(pkgsplit(package_name),pkgsplit(str(current_package.cpv))) <=0 ):
884             #if (pkgcmp(package_name, str(current_package.cpv)) <= 0):
885                 packageObj = gentoolkit.package.Package(str(current_package.cpv))
886                 if (packageObj == None):
887                     # we could not create a package object
888                     return
889
890                 if "package.unmask" in filename:
891                     #if (is_pkg_package_masked(str(current_package.cpv))):
892                     if (is_any_cpv_file_masked(str(current_package.cpv))):
893                         # package was found as masked
894                         return
895                     else:
896                         # package is not masked
897                         unmask_list.append(str(current_package.cpv))
898                         ebuild_output = portage.output.yellow(str(current_package.cpv) + ": ") + portage.output.green("Not package masked")
899                         print_output(info,ebuild_output, package, filename)
900                         return
901                 else:
902                     if (is_pkg_package_masked(str(current_package.cpv))):
903                         # package was found as masked
904                         return
905         else:
906             # at this point we have no packages >= ~cpv that are masked, present for removal
907             # package does not have any masked versions
908             ebuild_output = portage.output.green(package_name + " has no masked versions")
909
910             if "package.unmask" in filename:
911                 unmask_list.append(orig_package_name)
912             if "package.keywords" in filename:
913                 stable_list.append(orig_package_name)
914             if "package.accept_keywords" in filename:
915                 stable_listNg.append(orig_package_name)
916             print_output(info,ebuild_output, package, filename)
917
918 #helper function to print avail pks when version does not exist
919 def show_all_versions(pkg, filename):
920
921     # is package masked
922     is_package_masked = False
923     pkgArr = portage.pkgsplit(pkg)
924
925     if pkgArr is None or len(pkgArr) == 0:
926         return
927
928     # determine if category/package is masked
929     package = pkgArr[0]
930
931     operator = portage.dep.Atom(pkg).operator
932     if operator is not None:
933         package = package[len(operator):]
934
935     # package is category/package and pkg is category/package-version
936     # is category/package-version we are checking package masked?
937     #if portage.settings.pmaskdict.has_key(package):
938     pmaskdict = settings._mask_manager._pmaskdict
939     if package in pmaskdict:
940         pkg_list = pmaskdict.get(package)
941         # iterate through list array looking for pkg
942         for pkg_check in pkg_list:
943             operator = portage.get_operator(pkg_check)
944             if operator is None:
945                 if pkg_check == package:
946                     is_package_masked = True
947
948     query = Query(package)
949
950     all_pkgs = []
951
952     try:
953         all_pkgs = query.smart_find(True,True,True,True,False,True)
954     except errors.GentoolkitException as err:
955         print_output(debug,portage.output.blue("Package " + package + " not found."))
956
957     for current_package in all_pkgs:
958         keywords = "%s" % (current_package.environment("KEYWORDS").split())
959         keywords = filter_keywords(keywords)
960         keywords = "[%s]" % (keywords)
961         ebuild = current_package.ebuild_path()
962         if ebuild:
963             pkgmask = _get_mask_status(current_package, True)
964             if is_package_masked:
965                 print (portage.output.red("Available: " + str(current_package.cpv) + " [M] Keywords: " + keywords))
966             elif pkgmask > 4:
967                 print (portage.output.red("Available: " + str(current_package.cpv) + " [M] Keywords: " + keywords))
968             elif pkgmask == 4 or pkgmask == 1:
969                 print (portage.output.brown("Available: " + str(current_package.cpv) + " Keywords: " + keywords))
970             else:
971                 print (portage.output.green("Available: " + str(current_package.cpv) + " Keywords: " + keywords))
972                 if "package.keywords" in filename:
973                     stable_list.append(str(current_package.cpv))
974                 if "package.accept_keywords" in filename:
975                     stable_listNg.append(str(current_package.cpv))
976
977
978 def get_useflags(package):
979     iuse = get_iuse(package.cpv)
980     return iuse
981
982 def check_useflags_all_versions(pkgs, line, check_pkgs):
983
984     global useremove_display, invalid_flag_found
985     invalid_flag_found = False
986
987     print_output(debug,portage.output.blue("ENTERED check_useflags_all_versions: " + check_pkgs))
988
989     potential_invalid_flag = []
990     valid_flag_list = []
991     for package in pkgs:
992
993         # if package not installed, move on
994         if (not package.is_installed()):
995             continue;
996
997         print_output(debug,portage.output.blue("check_useflags_all_versions: package: " + package.cpv))
998         if ((package is None) or (package == "")):
999             return
1000
1001         useflag_removal_display=""
1002
1003         if (len(line) <= 0):
1004             return
1005
1006         list2 = get_useflags(package)
1007
1008         for uf in list2:
1009             print_output(debug,portage.output.blue(("use found " + uf)))
1010
1011         iuse_string = package.use()
1012         iuse = iuse_string.split(" ")
1013
1014         for uflag in list2:
1015             iuse.append(uflag)
1016
1017         for iuse_item in iuse:
1018             print_output(debug,portage.output.blue(("iuse_item is " + iuse_item)))
1019
1020         useflags_fromfile = line.replace("\t", " ").split(" ")
1021
1022         #for useflags_fromfile_item in useflags_fromfile:
1023         #    print_output(debug,portage.output.blue(("useflags_fromfile_item is " + useflags_fromfile_item)))
1024
1025         package_string = useflags_fromfile.pop(0)
1026         print_output(debug,portage.output.blue(("package_string is " + package_string)))
1027
1028         clean_useflags_list = []
1029         # remove + or -
1030         atom = "-+"
1031
1032         #clean list from portage of + or -
1033         clean_iuse = []
1034         for item in iuse:
1035             if item[0] in atom:
1036                 clean_iuse.append(item[1:])
1037             else:
1038                 clean_iuse.append(item)
1039
1040         for original_flag in useflags_fromfile:
1041             if (original_flag is None or original_flag == ""):
1042                 continue
1043             flag = original_flag
1044             if original_flag[0] in atom:
1045                 flag = original_flag[1:]
1046             if flag not in clean_iuse:
1047                 print_output(debug,portage.output.blue(("found invalid flag: " + flag)))
1048
1049                 # only add to invalid list if it's not in valid list
1050                 try:
1051                     index = valid_flag_list.index(original_flag)
1052                 except ValueError as error:
1053
1054                     try:
1055                        index = potential_invalid_flag.index(original_flag)
1056                     except ValueError:
1057                        print_output(debug,portage.output.blue(original_flag + " not found for " + package.cpv))
1058                        potential_invalid_flag.append(original_flag)
1059
1060             else:
1061                 print_output(debug,portage.output.blue(("found valid flag: " + flag)))
1062                 try:
1063                     index = valid_flag_list.index(original_flag)
1064                 except ValueError as error:
1065                     valid_flag_list.append(original_flag)
1066
1067                 try:
1068                     index = potential_invalid_flag.index(original_flag)
1069                     potential_invalid_flag.remove(original_flag)
1070                 except ValueError as error:
1071                     continue
1072
1073
1074     # if potential_invalid_flag list is empty, we are done
1075     if (len(potential_invalid_flag) <= 0):
1076         return
1077
1078     invalid_flag_found = True
1079
1080     # build sentence
1081     invalid_flags = ""
1082     verb = "is"
1083     for inv_flag in potential_invalid_flag:
1084         if (len(invalid_flags) > 0):
1085             invalid_flags += ","
1086             verb = "are"
1087         invalid_flags += inv_flag
1088
1089     # if there are no valid flags at all, we remove the line
1090     if ( len(valid_flag_list) == 0):
1091         print_output (info,portage.output.red("No valid use flags found for package: " + str(package.category) + "/" + str(package.name) + ". Invalid flag(s) found: " + invalid_flags +  "\n"))
1092         useremove_display += "Removing line: " + line + "\n"
1093         use_flag_dict[line] = ""
1094         return
1095
1096     # if there are values in potential_invalid_flag, we need to remove them
1097
1098     if (len(potential_invalid_flag) > 0):
1099         removal_text = "use flags: "
1100     else:
1101         removal_text = "use flag: "
1102
1103     if ( (len(valid_flag_list) > 0)):
1104         useremove_display += "Removing " + removal_text + invalid_flags + " for package " + check_pkgs + "\n"
1105         print (portage.output.yellow(removal_text) +  portage.output.red(invalid_flags) + portage.output.yellow(" " + verb + " invalid for " + str(package.cpv)))
1106
1107     valid_flag_list.insert(0,package_string);
1108
1109     if (len(potential_invalid_flag) > 0):
1110         use_flag_dict[line] = valid_flag_list
1111
1112     return valid_flag_list
1113
1114 def check_useflags(package,line):
1115
1116     global useremove_display, invalid_flag_found
1117     invalid_flag_found = False
1118
1119     print_output(debug,portage.output.blue("check_useflags: package: " + package.cpv))
1120     if ((package is None) or (package == "")):
1121         return
1122
1123     useflag_removal_display=""
1124
1125     if (len(line) <= 0):
1126         return
1127
1128     iuse = get_useflags(package)
1129
1130     #for iuse_item in iuse:
1131     #    print_output(debug,portage.output.blue(("iuse_item is " + iuse_item)))
1132
1133     useflags_fromfile = line.replace("\t", " ").split(" ")
1134     #for useflags_fromfile_item in useflags_fromfile:
1135     #    print_output(debug,portage.output.blue(("useflags_fromfile_item is " + useflags_fromfile_item)))
1136
1137     package_string = useflags_fromfile.pop(0)
1138     print_output(debug,portage.output.blue(("package_string is " + package_string)))
1139
1140     clean_useflags_list = []
1141     # remove + or -
1142     atom = "-+"
1143
1144     #clean list from portage of + or -
1145     clean_iuse = []
1146     for item in iuse:
1147         if item[0] in atom:
1148             clean_iuse.append(item[1:])
1149         else:
1150             clean_iuse.append(item)
1151
1152     valid_flag_list = []
1153     for original_flag in useflags_fromfile:
1154         if (original_flag is None or original_flag == ""):
1155             continue
1156         flag = original_flag
1157         if original_flag[0] in atom:
1158             flag = original_flag[1:]
1159         if flag not in clean_iuse:
1160             print_output (info,portage.output.red("use flag: " + flag + " is invalid for : " + str(package.cpv)))
1161             useflag_removal_display += "Removing use flag: " + flag + " for package " + str(package.cpv)
1162             invalid_flag_found = True
1163         else:
1164             valid_flag_list.append(original_flag)
1165
1166     # if valid_flag_list is empty, there are no valid flags
1167     if ( (len(valid_flag_list) > 0) and (len(useflag_removal_display) >0)):
1168         useremove_display += useflag_removal_display + "\n"
1169     elif ( len(valid_flag_list) == 0):
1170         useremove_display += "No valid use flags found for package " + str(package.cpv) + ". Removing line: " + line + "\n"
1171         if ( invalid_flag_found != True):
1172             print_output (info,portage.output.red("No valid use flags found for package " + str(package.cpv)))
1173         invalid_flag_found = True
1174
1175     valid_flag_list.insert(0,package_string);
1176     if (invalid_flag_found == True):
1177         use_flag_dict[line] = valid_flag_list
1178
1179     return valid_flag_list
1180
1181
1182 def clean_useflagsFile(filename):
1183
1184     if "--fix-confirm" in cmdline:
1185         if (confirmFix() == False):
1186             return
1187
1188     display_line = ""
1189     removed_list = []
1190
1191     try:
1192         # determine if filename is a directory
1193         if os.path.isdir(filename):
1194             # get listing of directory
1195             filenames = os.listdir(filename)
1196             for file_name in filenames:
1197                 clean_useflagsFile(filename+os.path.sep+file_name)
1198             return
1199         else:
1200             #go through stable array and remove line if found
1201             for line in fileinput.input(filename,inplace =1):
1202                 itemFound = False
1203                 line = line.strip()
1204
1205                 # make sure line is not empty and do not remove commented out lines
1206                 if len(line) <= 0:
1207                     continue
1208                 elif line.find("#") == 0:
1209                     print (line)
1210                     continue
1211
1212                 check_for_change = ""
1213                 use_flag_dict.get(line,"")
1214                 try:
1215                     check_for_change = use_flag_dict[line]
1216                     removed_list.append(line)
1217                     if ( len(check_for_change) > 1):
1218                         print (" ".join(check_for_change))
1219                 except KeyError as error:
1220                     print (line)
1221
1222             fileinput.close()
1223     except OSError as error:
1224         print (portage.output.red("Modify/Read access to file: " + filename + " failed: " + format(error)))
1225
1226     if (len(removed_list) > 0):
1227         print ("\n")
1228         for package in removed_list:
1229             print (portage.output.red("Removing from: ") + portage.output.yellow(filename + ": Invalid use flag(s) from ")  + portage.output.green(package) + "\n")
1230
1231     return
1232
1233 def handle_if_overlay(package):
1234     overlay_text = ""
1235     global print_overlay_flag,using_gentoo_as_overlay
1236
1237     if (using_gentoo_as_overlay):
1238         return overlay_text
1239
1240     print_overlay_flag = True
1241
1242     ebuild_path,overlay_path = porttree.dbapi.findname2(str(package.cpv))
1243     index = -1
1244     try:
1245         index = overlay_list.index(overlay_path)
1246     except ValueError as error:
1247         overlay_list.append(overlay_path)
1248         index = overlay_list.index(overlay_path)
1249
1250     overlay_text = " [%s]" % (str(index+1))
1251
1252     return overlay_text
1253
1254 # if the overlay_text was displayed to the user
1255 # we need to display the string at the end
1256 # this array will store the overlays to be displayed
1257 def print_overlay_text():
1258
1259     global print_overlay_flag
1260
1261     if (not print_overlay_flag):
1262         return
1263
1264     if (len(overlay_list) <= 0):
1265         return
1266
1267     index = 1
1268     for x in overlay_list:
1269         print (portage.output.turquoise("[" + str(index) + "] ") + x)
1270         index = index + 1
1271
1272     print ("\n")
1273
1274 #helper function to print output
1275 def print_output(log_level,output_string, package=None, filename=None):
1276
1277     global logLevel
1278
1279     if package != None:
1280         if (package.is_overlay()):
1281             output_string = "%s%s" % (output_string,portage.output.turquoise(handle_if_overlay(package)))
1282             #output_string = output_string + portage.output.turquoise(handle_if_overlay(package))
1283         else:
1284             if filename != None:
1285                 output_string = "%s%s" % (output_string,portage.output.brown(" : " + filename))
1286                 #output_string = output_string + portage.output.brown(" : " + filename)
1287
1288     if (log_level <= logLevel):
1289         print (output_string)
1290
1291 # remove stabled files that are no longer needed from package.keywords
1292 # or package.mask
1293 # includes support for etc/portage/package.keywords/<whatever>/package.keywords
1294 def cleanFile (filename):
1295
1296     removeDups = []
1297     removed_list = []
1298
1299     if "--fix-confirm" in cmdline:
1300         if (confirmFix() == False):
1301             return
1302
1303     # if the file or directory does not exist
1304     # exit out
1305     if (os.path.exists(filename) == False):
1306         return
1307
1308     if "package.keywords" in filename:
1309         if ( len(stable_list) == 0):
1310             return
1311         removeDups = stable_list
1312     elif "package.accept_keywords" in filename:
1313         if ( len(stable_listNg) == 0):
1314             return
1315         removeDups = stable_listNg
1316     else:
1317         if ( len(unmask_list) == 0):
1318             return
1319         removeDups = unmask_list
1320
1321     removedDict = {}
1322
1323     try:
1324         # determine if filename is a directory
1325         if os.path.isdir(filename):
1326             # get listing of directory
1327             filenames = os.listdir(filename)
1328             for file_name in filenames:
1329                 cleanFile(filename+os.path.sep+file_name)
1330             return
1331         else:
1332             #go through stable array and remove line if found
1333             for line in fileinput.input(filename,inplace =1):
1334                 itemFound = False
1335                 line = line.strip()
1336
1337                 # make sure line is not empty and do not remove commented out lines
1338                 if len(line) <= 0:
1339                     continue
1340                 elif line.find("#") == 0:
1341                     print (line)
1342                     continue
1343
1344                 for item in removeDups:
1345                     if item in line:
1346                         removed_list.append(item)
1347                         removedDict[filename] = item
1348                         itemFound = True
1349                         removeDups.pop(removeDups.index(item))
1350                         break
1351                 if (itemFound == False):
1352                     print (line)
1353             fileinput.close()
1354     except OSError as error:
1355         print (portage.output.red("Modify/Read access to file: " + filename + " failed: " + format(error)))
1356
1357     if (len(removed_list) > 0):
1358         print ("\n")
1359         for package in removed_list:
1360             print (portage.output.red("Removing from: ") + portage.output.yellow(filename) + ": " + portage.output.green(package) + "\n")
1361
1362 # ask the user if they want to fix their files
1363 # and remove unneeded entries
1364 # Return true if they say yes and False if they say no
1365 def confirmFix():
1366
1367     global fix_asked,fix_confirm
1368
1369     if (fix_asked == True):
1370         return fix_confirm
1371
1372     # only ask if we actually have anything to check
1373     if ( (len(stable_list) == 0) and
1374           (len(stable_listNg) == 0) and
1375           (len(unmask_list) == 0) and
1376           (invalid_flag_found == False) and
1377           (len(use_flag_dict) == 0)):
1378         fix_confirm = True
1379         return fix_confirm
1380
1381     fix_asked = True
1382
1383     valid = {"yes":"yes",   "y":"yes",
1384              "no":"no",     "n":"no"}
1385
1386     prompt = portage.output.bold("Remove entries from files [") + portage.output.green("y") + "/" + portage.output.red("n") + portage.output.bold("]") + " "
1387
1388     while 1:
1389         sys.stdout.write('\n' + prompt)
1390         choice = input().lower()
1391         if choice == '':
1392             fix_confirm = False
1393             break
1394         elif choice in valid.keys():
1395             if (choice == 'y' or choice == 'yes'):
1396                 fix_confirm = True
1397                 break
1398             else:
1399                 fix_confirm = False
1400                 break
1401         else:
1402             sys.stdout.write("Please respond with 'yes' or 'no' "\
1403                              "(or 'y' or 'n').\n")
1404
1405     return fix_confirm
1406
1407
1408 def check_for_any_installed_version(pkgs):
1409
1410     for package in pkgs:
1411         if (package.is_installed()):
1412             return True
1413
1414     return False
1415
1416 # main
1417 if __name__ == "__main__":
1418
1419     if len(sys.argv) == 1:
1420         print_usage()
1421         sys.exit(1)
1422
1423     # soooooo stolen from emerge
1424     tmpcmdline = sys.argv[1:]
1425
1426     for cmd in tmpcmdline:
1427         if cmd[0:1] == "-" and cmd[1:2] != "-":
1428             for cmd_item in cmd[1:]:
1429                 if cmd_item in mappings:
1430                     if mappings[cmd_item] in cmdline:
1431                         print ()
1432                         print ("*** Warning: Redundant use of ", mappings[cmd_item])
1433                     else:
1434                         cmdline.append(mappings[cmd_item])
1435                 else:
1436                     print ("!!! Error: -"+cmd_item+" is an invalid option.")
1437                     sys.exit(-1)
1438         else:
1439             cmdline.append(cmd)
1440
1441     #parse long options
1442     for cmd in cmdline:
1443         if len(cmd)>=2 and cmd[0:2]=="--":
1444             try:
1445                 i = options.index(cmd)
1446                 continue
1447             except ValueError:
1448                 print ("!!! Error: -"+cmd+" is an invalid option.")
1449                 sys.exit(-1)
1450
1451     if "--changes-only" in cmdline:
1452         cmdline.remove("--changes-only")
1453         show_changes_only_flag = True
1454
1455     if "--removable-only" in cmdline:
1456         cmdline.remove("--removable-only")
1457         show_removable_only_flag = True
1458
1459     if "--debug" in cmdline:
1460         logLevel = debug
1461
1462     if "--no-color" in cmdline:
1463         portage.output.nocolor()
1464
1465     if "--tilde-check" in cmdline:
1466         tilde=1
1467
1468     if "--version" in cmdline:
1469         print_version()
1470         sys.exit(0)
1471
1472     if "--fix-confirm" in cmdline:
1473         if '--fix' not in cmdline:
1474             cmdline.append("--fix")
1475
1476     if "--all" in cmdline:
1477         tmpcmdline = ["--all"]
1478         if "--fix" in cmdline:
1479             tmpcmdline.append("--fix")
1480             if "--fix-confirm" in cmdline:
1481                 tmpcmdline.append("--fix-confirm")
1482                 fix_confirm = False
1483         cmdline=tmpcmdline
1484
1485     if "--help" in cmdline:
1486         print_usage()
1487         sys.exit(0)
1488
1489     if (show_changes_only_flag and show_removable_only_flag):
1490         print ("Please select only one of --show-removable (-r) or --changes-only")
1491         print ("Use --help for more info.")
1492         sys.exit(0)
1493
1494     for cmd in cmdline:
1495         if cmd == "--keyword":
1496             print (portage.output.bold("\npackage.keywords:"))
1497             get_recursive_info(USER_CONFIG_PATH + "/package.keywords")
1498             if "--fix" in cmdline:
1499                 cleanFile(USER_CONFIG_PATH + "/package.keywords")
1500             print (portage.output.bold("Done\n"))
1501             print (portage.output.bold("\npackage.accept_keywords:"))
1502             get_recursive_info(USER_CONFIG_PATH + "/package.accept_keywords")
1503             if "--fix" in cmdline:
1504                 cleanFile(USER_CONFIG_PATH + "/package.accept_keywords")
1505             print (portage.output.bold("Done\n"))
1506         elif cmd == "--unmask":
1507             print (portage.output.bold("\npackage.unmask:"))
1508             checking_package_unmask = True
1509             get_recursive_info(USER_CONFIG_PATH + "/package.unmask")
1510             checking_package_unmask = False
1511             if "--fix" in cmdline:
1512                 cleanFile(USER_CONFIG_PATH + "/package.unmask")
1513         elif cmd == "--mask":
1514             checking_package_mask = True
1515             print (portage.output.bold("\npackage.mask:"))
1516             get_recursive_info(USER_CONFIG_PATH + "/package.mask")
1517             print (portage.output.bold("Done\n"))
1518             checking_package_mask = False
1519             if "--fix" in cmdline:
1520                 cleanFile(USER_CONFIG_PATH + "/package.mask")
1521         elif cmd == "--package-use":
1522             print (portage.output.bold("\npackage.use:"))
1523             processing_package_use = True
1524             get_recursive_info(USER_CONFIG_PATH + "/package.use")
1525             if "--fix" in cmdline:
1526                 cleanFile(USER_CONFIG_PATH + "/package.use")
1527                 clean_useflagsFile(USER_CONFIG_PATH + "/package.use")
1528             print (portage.output.bold("Done\n"))
1529         elif cmd == "--all":
1530             print (portage.output.bold("\npackage.keywords:"))
1531             get_recursive_info(USER_CONFIG_PATH + "/package.keywords")
1532             print (portage.output.bold("\npackage.accept_keywords:"))
1533             get_recursive_info(USER_CONFIG_PATH + "/package.accept_keywords")
1534             print (portage.output.bold("\npackage.unmask:"))
1535             checking_package_unmask = True
1536             get_recursive_info(USER_CONFIG_PATH + "/package.unmask")
1537             checking_package_unmask = False
1538             checking_package_mask = True
1539             print (portage.output.bold("\npackage.mask:"))
1540             get_recursive_info(USER_CONFIG_PATH + "/package.mask")
1541             print (portage.output.bold("\npackage.use:"))
1542             processing_package_use = True
1543             get_recursive_info(USER_CONFIG_PATH + "/package.use")
1544             if "--fix" in cmdline:
1545                 cleanFile(USER_CONFIG_PATH + "/package.keywords")
1546                 cleanFile(USER_CONFIG_PATH + "/package.accept_keywords")
1547                 cleanFile(USER_CONFIG_PATH + "/package.unmask")
1548                 cleanFile(USER_CONFIG_PATH + "/package.use")
1549                 cleanFile(USER_CONFIG_PATH + "/package.mask")
1550                 clean_useflagsFile(USER_CONFIG_PATH + "/package.use")
1551             print (portage.output.bold("\nDone\n"))
1552
1553     print_overlay_text()
1554
1555     if len(cmdline) == 0:
1556         if show_changes_only_flag or show_removable_only_flag:
1557             if (show_changes_only_flag):
1558                 print (portage.output.green("-c") + " or " + portage.output.green("--changes-only") + " must be accompanied by one of the following:")
1559             else:
1560                 print (portage.output.green("-r") + " or " + portage.output.green("--removable-only") + " must be accompanied by one of the following:")
1561
1562             print ("     " + portage.output.yellow("-k") + " or " + portage.output.yellow("--keyword"))
1563             print ("     " + portage.output.yellow("-u") + " or " + portage.output.yellow("--unmask"))
1564             print ("     " + portage.output.yellow("-m") + " or " + portage.output.yellow("--mask"))
1565             print ("     " + portage.output.yellow("-a") + " or " + portage.output.yellow("--all"))
1566
1567             print_usage()