2 # -*- coding: utf-8 -*-
7 Main program, cli parsing and api program control and operation
9 Author: SÅ‚awomir Lis <lis.slawek@gmail.com>
10 revdep-rebuild original author: Stanislav Brabec
11 revdep-rebuild original rewrite Author: Michael A. Smith
12 Current Maintainer: Paul Varner <fuzzyray@gentoo.org>
13 Creation date: 2010/10/17
17 from __future__ import print_function
23 from portage.output import bold, red, blue, yellow, green, nocolor
25 from .analyse import analyse
26 from .stuff import get_masking_status
27 from .cache import check_temp_files, read_cache
28 from .assign import get_slotted_cps
29 from .settings import DEFAULTS
30 from . import __version__
33 APP_NAME = sys.argv[0]
36 __productname__ = "revdep-ng"
42 """Outputs the help message"""
43 print( APP_NAME + ': (' + VERSION +')')
45 print('This is free software; see the source for copying conditions.')
47 print('Usage: ' + APP_NAME + ' [OPTIONS] [--] [EMERGE_OPTIONS]')
49 print('Broken reverse dependency rebuilder, python implementation.')
51 print('Available options:')
53 -C, --nocolor Turn off colored output
54 -d, --debug Print debug informations
55 -e, --exact Emerge based on exact package version
56 -h, --help Print this usage
57 -i, --ignore Ignore temporary files from previous runs
58 (also won't create any)
59 -L, --library NAME Unconditionally emerge existing packages that use
60 --library=NAME the library with NAME. NAME can be a full or partial
62 -l, --no-ld-path Do not set LD_LIBRARY_PATH
63 -o, --no-order Do not check the build order
64 (Saves time, but may cause breakage.)
65 -p, --pretend Do a trial run without actually emerging anything
66 (also passed to emerge command)
67 -q, --quiet Be less verbose (also passed to emerge command)
68 -v, --verbose Be more verbose (also passed to emerge command)
70 print( 'Calls emerge, options after -- are ignored by ' + APP_NAME)
71 print('and passed directly to emerge.')
74 def init_logger(settings):
75 """Creates and iitializes our logger according to the settings"""
76 logger = logging.getLogger()
77 log_handler = logging.StreamHandler()
78 log_fmt = logging.Formatter('%(msg)s')
79 log_handler.setFormatter(log_fmt)
80 logger.addHandler(log_handler)
82 logger.setLevel(logging.ERROR)
83 elif settings['VERBOSITY'] == 2:
84 logger.setLevel(logging.INFO)
85 elif settings['debug']:
86 logger.setLevel(logging.DEBUG)
88 logger.setLevel(logging.WARNING)
93 """Parses the command line options an sets settings accordingly"""
95 # TODO: Verify: options: no-ld-path, no-order, no-progress
98 settings = DEFAULTS.copy()
100 opts, args = getopt.getopt(sys.argv[1:],
102 ['nocolor', 'debug', 'exact', 'help', 'ignore',
103 'keep-temp', 'library=', 'no-ld-path', 'no-order',
104 'pretend', 'no-pretend', 'no-progress', 'quiet', 'verbose'])
107 for key, val in opts:
108 if key in ('-h', '--help'):
110 elif key in ('-q', '--quiet'):
111 settings['quiet'] = True
112 settings['VERBOSITY'] = 0
113 elif key in ('-v', '--verbose'):
114 settings['VERBOSITY'] = 2
115 elif key in ('-d', '--debug'):
116 settings['debug'] = True
117 settings['VERBOSITY'] = 3
118 elif key in ('-p', '--pretend'):
119 settings['PRETEND'] = True
120 elif key == '--no-pretend':
121 settings['NO_PRETEND'] = True
122 elif key in ('-e', '--exact'):
123 settings['EXACT'] = True
124 elif key in ('-C', '--nocolor', '--no-color'):
125 settings['nocolor'] = True
126 elif key in ('-L', '--library', '--library='):
127 settings['library'] = settings['library'].union(val.split(','))
128 elif key in ('-i', '--ignore'):
129 settings['USE_TMP_FILES'] = False
131 settings['pass_through_options'] = " " + " ".join(args)
132 except getopt.GetoptError:
133 #logging.info(red('Unrecognized option\n'))
134 print(red('Unrecognized option\n'))
143 def rebuild(logger, assigned, settings):
144 """rebuilds the assigned pkgs"""
146 args = settings['pass_through_options']
147 if settings['EXACT']:
148 emerge_command = '=' + ' ='.join(assigned)
150 emerge_command = ' '.join(get_slotted_cps(assigned, logger))
151 if settings['PRETEND']:
153 if settings['VERBOSITY'] >= 2:
155 elif settings['VERBOSITY'] < 1:
157 if settings['nocolor']:
160 if len(emerge_command) == 0:
161 logger.warn(bold('\nThere is nothing to emerge. Exiting.'))
164 emerge_command = emerge_command
168 ' --oneshot --complete-graph=y ' +
169 bold(emerge_command))
173 ' --oneshot --complete-graph=y ' +
178 def main(settings=None, logger=None):
179 """Main program operation method....
181 @param settings: dict. defaults to settings.DEFAULTS
182 @param logger: python logging module defaults to init_logger(settings)
183 @return boolean success/failure
187 print("NO Input settings, using defaults...")
188 settings = DEFAULTS.copy()
191 logger = init_logger(settings)
193 _libs_to_check = settings['library']
195 if not settings['stdout'].isatty() or settings['nocolor']:
198 #TODO: Development warning
199 logger.warn(blue(' * ') +
200 yellow('This is a development version, '
201 'so it may not work correctly'))
202 logger.warn(blue(' * ') +
203 yellow('The original revdep-rebuild script is '
204 'installed as revdep-rebuild.sh'))
206 if os.getuid() != 0 and not settings['PRETEND']:
207 logger.warn(blue(' * ') +
208 yellow('You are not root, adding --pretend to portage options'))
209 settings['PRETEND'] = True
211 if settings['library']:
212 logger.warn(green(' * ') +
213 "Looking for libraries: %s" % (bold(', '.join(settings['library']))))
215 if settings['USE_TMP_FILES'] \
216 and check_temp_files(settings['DEFAULT_TMP_DIR'], logger=logger):
217 libraries, la_libraries, libraries_links, binaries = read_cache(
218 settings['DEFAULT_TMP_DIR'])
223 la_libraries=la_libraries,
224 libraries_links=libraries_links,
226 _libs_to_check=_libs_to_check)
228 assigned = analyse(settings, logger, _libs_to_check=_libs_to_check)
231 logger.warn('\n' + bold('Your system is consistent'))
232 # return the correct exit code
237 for ebuild in assigned:
238 if get_masking_status(ebuild):
240 logger.warn('!!! ' + red('All ebuilds that could satisfy: ') +
241 green(ebuild) + red(' have been masked'))
247 logger.info(red(' * ') +
248 'Unmask all ebuild(s) listed above and call revdep-rebuild '
249 'again or manually emerge given packages.')
251 success = rebuild(logger, assigned, settings)
252 logger.debug("rebuild return code = %i" %success)