3 # Copyright 2010 Brian Dolbec <brian.dolbec@gmail.com>
4 # Copyright(c) 2010, Gentoo Foundation
5 # Distributed under the terms of the GNU General Public License v2
9 """Provides a rebuild file of USE flags or keywords used and by
10 what packages according to the Installed package database"""
13 from __future__ import print_function
19 from gentoolkit.dbapi import PORTDB, VARDB
20 from gentoolkit.analyse.base import ModuleBase
21 from gentoolkit import pprinter as pp
22 from gentoolkit.analyse.lib import (get_installed_use, get_flags,
23 abs_flag, abs_list, FlagAnalyzer)
24 from gentoolkit.analyse.output import RebuildPrinter
27 from portage import os
33 # override-able for testing
35 _get_used=get_installed_use
37 """Data gathering and analysis function determines
38 the difference between the current default USE flag settings
39 and the currently installed pkgs recorded USE flag settings
42 @param cpvs: optional list of [cat/pkg-ver,...] to analyse or
43 defaults to entire installed pkg db
44 @type: system_flags: list
45 @param system_flags: the current default USE flags as defined
46 by portage.settings["USE"].split()
47 @type _get_flags: function
48 @param _get_flags: ovride-able for testing,
49 defaults to gentoolkit.analyse.lib.get_flags
50 @param _get_used: ovride-able for testing,
51 defaults to gentoolkit.analyse.lib.get_installed_use
52 @rtype dict. {cpv:['flag1', '-flag2',...]}
55 cpvs = VARDB.cpv_all()
58 # pass them in to override for tests
59 flags = FlagAnalyzer(system_flags,
62 _get_flags=_get_flags,
63 _get_used=get_installed_use
66 plus, minus, unset = flags.analyse_cpv(cpv)
70 data[cpv] = list(plus)
74 class Rebuild(ModuleBase):
75 """Installed db analysis tool to query the installed databse
76 and produce/output stats for USE flags or keywords/mask.
77 The 'rebuild' action output is in the form suitable for file type output
78 to create a new package.use, package.keywords, package.unmask
79 type files in the event of needing to rebuild the
80 /etc/portage/* user configs
83 ModuleBase.__init__(self)
84 self.module_name = "rebuild"
96 "-p": ("pretend", "boolean", True),
97 "--pretend": ("pretend", "boolean", True),
98 "-e": ("exact", "boolean", True),
99 "--exact": ("exact", "boolean", True),
100 "-v": ("verbose", "boolean", True),
101 "--verbose": ("verbose", "boolean", True),
103 self.formatted_options = [
104 (" -h, --help", "Outputs this useage message"),
105 (" -p, --pretend", "Does not actually create the files."),
106 (" ", "It directs the outputs to the screen"),
107 (" -e, --exact", "will atomize the package with a"),
108 (" ", "leading '=' and include the version")
110 self.formatted_args = [
112 "causes the action to analyse the installed packages USE flags"),
114 "causes the action to analyse the installed packages keywords"),
116 "causes the action to analyse the installed packages " + \
117 "current mask status")
119 self.short_opts = "hepv"
120 self.long_opts = ("help", "exact", "pretend", "verbose")
121 self.need_queries = True
122 self.arg_spec = "TargetSpec"
123 self.arg_options = ['use', 'keywords', 'unmask']
124 self.arg_option = False
127 "This is beta software and some features/options are incomplete,",
128 "some features may change in future releases includig its name.",
129 "The file generated is saved in your home directory",
130 "Feedback will be appreciated, http://bugs.gentoo.org")
134 def run(self, input_args, quiet=False):
137 @param input_args: input arguments to be parsed
139 self.options['quiet'] = quiet
140 query = self.main_setup(input_args)
141 query = self.validate_query(query)
144 elif query in ["keywords"]:
145 self.rebuild_keywords()
146 elif query in ["unmask"]:
147 self.rebuild_unmask()
150 def rebuild_use(self):
151 if not self.options["quiet"]:
153 print(" -- Scanning installed packages for USE flag settings that")
154 print(" do not match the default settings")
155 system_use = portage.settings["USE"].split()
156 output = RebuildPrinter("use", self.options["pretend"], self.options["exact"])
157 pkgs = cpv_all_diff_use(system_flags=system_use)
158 pkg_count = len(pkgs)
159 if self.options["verbose"]:
161 print((pp.emph(" -- Found ") + pp.number(str(pkg_count)) +
162 pp.emph(" packages that need entries")))
163 #print pp.emph(" package.use to maintain their current setting")
165 pkg_keys = sorted(pkgs)
167 if self.options["pretend"] and not self.options["quiet"]:
169 print(pp.globaloption(
170 " -- These are the installed packages & flags " +
171 "that were detected"))
172 print(pp.globaloption(" to need flag settings other " +
173 "than the defaults."))
175 elif not self.options["quiet"]:
176 print(" -- preparing pkgs for file entries")
180 if self.options['verbose']:
181 flag_count += len(pkgs[pkg])
182 unique_flags.update(abs_list(pkgs[pkg]))
183 output(pkg, pkgs[pkg])
184 if self.options['verbose']:
185 message = (pp.emph(" ") +
186 pp.number(str(len(unique_flags))) +
187 pp.emph(" unique flags\n") + " " +
188 pp.number(str(flag_count))+
189 pp.emph(" flag entries\n") + " " +
190 pp.number(str(pkg_count)) +
191 pp.emph(" different packages"))
193 print(pp.globaloption(" -- Totals"))
196 #unique = list(unique_flags)
199 if not self.options["pretend"]:
200 filepath = os.path.expanduser('~/package.use.test')
201 self.save_file(filepath, output.use_lines)
203 def rebuild_keywords(self):
204 print("Module action not yet available")
207 def rebuild_unmask(self):
208 print("Module action not yet available")
212 def save_file(self, filepath, data):
213 """Writes the data to the file determined by filepath
215 @param filepath: string. eg. '/path/to/filename'
216 @param data: list of lines to write to filepath
218 if not self.options["quiet"]:
219 print(' - Saving file: %s' %filepath)
220 with open(filepath, "w") as output:
221 output.write('\n'.join(data))
225 def main(input_args):
226 """Common starting method by the analyse master
227 unless all modules are converted to this class method.
229 @param input_args: input args as supplied by equery master module.
231 query_module = Rebuild()
232 query_module.run(input_args, gentoolkit.CONFIG['quiet'])
234 # vim: set ts=4 sw=4 tw=79: