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