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