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