new /bin/revdep-ng script. revamp rebuild.py for a better api.
authordol-sen <brian.dolbec@gmail.com>
Mon, 25 Apr 2011 06:15:05 +0000 (23:15 -0700)
committerPaul Varner <fuzzyray@gentoo.org>
Tue, 12 Jul 2011 21:29:01 +0000 (16:29 -0500)
bin/revdep-ng [new file with mode: 0755]
pym/gentoolkit/revdep_rebuild/rebuild.py

diff --git a/bin/revdep-ng b/bin/revdep-ng
new file mode 100755 (executable)
index 0000000..a4c8e11
--- /dev/null
@@ -0,0 +1,51 @@
+#!/usr/bin/python
+#
+# Copyright 2010 Brian Dolbec <brian.dolbec@gmail.com>
+# Copyright 2002-2010 Gentoo Technologies, Inc.
+# Distributed under the terms of the GNU General Public License v2 or later
+#
+# $Header$
+
+"""'analyse' is a flexible utility for Gentoo linux which can display various
+information about installed packages, such as the USE flags used and the
+packages that use them.  It can also be used to help rebuild /etc/portage/package.*
+files in the event of corruption, and possibly more.
+"""
+
+from __future__ import print_function
+
+import sys
+# This block ensures that ^C interrupts are handled quietly.
+try:
+       import signal
+
+       def exithandler(signum,frame):
+               signal.signal(signal.SIGINT, signal.SIG_IGN)
+               signal.signal(signal.SIGTERM, signal.SIG_IGN)
+               print()
+               sys.exit(1)
+
+       signal.signal(signal.SIGINT, exithandler)
+       signal.signal(signal.SIGTERM, exithandler)
+       signal.signal(signal.SIGPIPE, signal.SIG_DFL)
+
+
+except KeyboardInterrupt:
+       print()
+       sys.exit(1)
+
+from gentoolkit import errors
+from gentoolkit.revdep_rebuild import rebuild
+
+try:
+       success = rebuild.main(rebuild.parse_options())
+       sys.exit(success)
+except errors.GentoolkitException as err:
+       if '--debug' in sys.argv:
+               raise
+       else:
+               from gentoolkit import pprinter as pp
+               sys.stderr.write(pp.error(str(err)))
+               print()
+               print("Add '--debug' to global options for traceback.")
+               sys.exit(1)
index 4ad5e586d6a070fb3f6e0ccd4dd85584d739f23f..6185e0c7a87b9f39fd61fa1468a36dd9f45871da 100644 (file)
@@ -28,7 +28,7 @@ from analyse import analyse
 from stuff import exithandler, get_masking_status
 from cache import check_temp_files, read_cache
 from assign import get_slotted_cps
-from settings import SETTINGS
+from settings import DEFAULTS
 
 
 APP_NAME = sys.argv[0]
@@ -37,156 +37,198 @@ VERSION = '0.1-r6'
 __productname__ = "revdep-ng"
 
 
+# functions
 
 def print_usage():
-    print APP_NAME + ': (' + VERSION +')'
-    print
-    print 'This is free software; see the source for copying conditions.'
-    print
-    print 'Usage: ' + APP_NAME + ' [OPTIONS] [--] [EMERGE_OPTIONS]'
-    print
-    print 'Broken reverse dependency rebuilder, python implementation.'
-    print
-    print 'Available options:'
-    print '''
-  -C, --nocolor        Turn off colored output
-  -d, --debug          Print debug informations
-  -e, --exact          Emerge based on exact package version
-  -h, --help           Print this usage
-  -i, --ignore         Ignore temporary files from previous runs (also won't create any)
-  -L, --library NAME   Emerge existing packages that use the library with NAME
-      --library=NAME   NAME can be a full or partial library name
-  -l, --no-ld-path     Do not set LD_LIBRARY_PATH
-  -o, --no-order       Do not check the build order
-                       (Saves time, but may cause breakage.)
-  -p, --pretend        Do a trial run without actually emerging anything
-                       (also passed to emerge command)
-  -q, --quiet          Be less verbose (also passed to emerge command)
-  -v, --verbose        Be more verbose (also passed to emerge command)
+       print APP_NAME + ': (' + VERSION +')'
+       print
+       print 'This is free software; see the source for copying conditions.'
+       print
+       print 'Usage: ' + APP_NAME + ' [OPTIONS] [--] [EMERGE_OPTIONS]'
+       print
+       print 'Broken reverse dependency rebuilder, python implementation.'
+       print
+       print 'Available options:'
+       print '''
+  -C, --nocolor         Turn off colored output
+  -d, --debug           Print debug informations
+  -e, --exact           Emerge based on exact package version
+  -h, --help            Print this usage
+  -i, --ignore          Ignore temporary files from previous runs
+                        (also won't create any)
+  -L, --library NAME    Emerge existing packages that use
+                        the library with NAME
+       --library=NAME   NAME can be a full or partial library name
+  -l, --no-ld-path      Do not set LD_LIBRARY_PATH
+  -o, --no-order        Do not check the build order
+                        (Saves time, but may cause breakage.)
+  -p, --pretend         Do a trial run without actually emerging anything
+                        (also passed to emerge command)
+  -q, --quiet           Be less verbose (also passed to emerge command)
+  -v, --verbose         Be more verbose (also passed to emerge command)
 '''
-    print 'Calls emerge, options after -- are ignored by ' + APP_NAME
-    print 'and passed directly to emerge.'
-
-
-
-# functions
+       print 'Calls emerge, options after -- are ignored by ' + APP_NAME
+       print 'and passed directly to emerge.'
 
 
 def _match_str_in_list(lst, stri):
-    for l in lst:
-        if stri.endswith(l):
-            return l
-    return False
+       for l in lst:
+               if stri.endswith(l):
+                       return l
+       return False
+
+
+def init_logger(settings):
+       """Creates and iitializes our logger according to the settings"""
+       logger = logging.getLogger()
+       log_handler = logging.StreamHandler()
+       log_fmt = logging.Formatter('%(msg)s')
+       log_handler.setFormatter(log_fmt)
+       logger.addHandler(log_handler)
+       if settings['quiet']:
+               logger.setLevel(logging.ERROR)
+       elif settings['VERBOSITY'] == 2:
+               logger.setLevel(logging.INFO)
+       elif settings['debug']:
+               logger.setLevel(logging.DEBUG)
+       else:
+               logger.setLevel(logging.WARNING)
+       return logger
+
+
+def parse_options():
+       """Parses the command line options an sets settings accordingly"""
+
+       settings = DEFAULTS.copy()
+       try:
+               opts, args = getopt.getopt(sys.argv[1:], 
+                       'dehiklopqvCL:P', 
+                       ['nocolor', 'debug', 'exact', 'help', 'ignore',
+                       'keep-temp', 'library=', 'no-ld-path', 'no-order',
+                       'pretend', 'no-pretend', 'no-progress', 'quiet', 'verbose'])
+
+               for key, val in opts:
+                       if key in ('-h', '--help'):
+                               print_usage()
+                               sys.exit(0)
+                       elif key in ('-q', '--quiet'):
+                               settings['quiet'] = True
+                               settings['VERBOSITY'] = 0
+                       elif key in ('-v', '--verbose'):
+                               settings['VERBOSITY'] = 2
+                       elif key in ('-d', '--debug'):
+                               settings['debug'] = True
+                               settings['VERBOSITY'] = 3
+                       elif key in ('-p', '--pretend'):
+                               settings['PRETEND'] = True
+                       elif key == '--no-pretend':
+                               settings['NO_PRETEND'] = True
+                       elif key in ('-e', '--exact'):
+                               settings['EXACT'] = True
+                       elif key in ('-C', '--nocolor', '--no-color'):
+                               settings['nocolor'] = True
+                       elif key in ('-L', '--library', '--library='):
+                               settings['library'] = settings['library'].union(val.split(','))
+                       elif key in ('-i', '--ignore'):
+                               settings['USE_TMP_FILES'] = False
+
+               settings['pass_through_options'] = " " + " ".join(args)
+       except getopt.GetoptError:
+               #logging.info(red('Unrecognized option\n'))
+               print(red('Unrecognized option\n'))
+               print_usage()
+               sys.exit(2)
+       return settings
+
+
+def rebuild(logger, assigned, settings):
+       """rebuilds the assigned pkgs"""
+       
+       args = settings['pass_through_options']
+       if settings['EXACT']:
+               emerge_command = '=' + ' ='.join(assigned)
+       else:
+               emerge_command = ' '.join(get_slotted_cps(assigned, logger))
+       if settings['PRETEND']:
+               args += ' --pretend'
+       if settings['VERBOSITY'] >= 2:
+               args += ' --verbose'
+       elif settings['VERBOSITY'] < 1:
+               args += ' --quiet'
+
+       if len(emerge_command) == 0:
+               logger.warn(bold('\nThere is nothing to emerge. Exiting.'))
+               return 0
+
+       emerge_command = args + ' --oneshot ' + emerge_command
+
+       logger.warn(yellow('\nemerge') + bold(emerge_command))
+       
+       success = os.system('emerge ' + emerge_command)
+       return success
 
 
 # Runs from here
-if __name__ == "__main__":
-    logger = logging.getLogger()
-    log_handler = logging.StreamHandler()
-    log_fmt = logging.Formatter('%(msg)s')
-    log_handler.setFormatter(log_fmt)
-    logger.addHandler(log_handler)
-    logger.setLevel(logging.WARNING)
-
-    _libs_to_check = set()
-
-    try:
-        opts, args = getopt.getopt(sys.argv[1:], 'dehiklopqvCL:P', ['nocolor', 'debug', 'exact', 'help', 'ignore',\
-            'keep-temp', 'library=', 'no-ld-path', 'no-order', 'pretend', 'no-pretend', 'no-progress', 'quiet', 'verbose'])
-
-        for key, val in opts:
-            if key in ('-h', '--help'):
-                print_usage()
-                sys.exit(0)
-            elif key in ('-q', '--quiet'):
-                logger.setLevel(logging.ERROR)
-                SETTINGS['VERBOSITY'] = 0
-            elif key in ('-v', '--verbose'):
-                logger.setLevel(logging.INFO)
-                SETTINGS['VERBOSITY'] = 2
-            elif key in ('-d', '--debug'):
-                logger.setLevel(logging.DEBUG)
-                SETTINGS['VERBOSITY'] = 3
-            elif key in ('-p', '--pretend'):
-                SETTINGS['PRETEND'] = True
-            elif key == '--no-pretend':
-                SETTINGS['NO_PRETEND'] = True
-            elif key in ('-e', '--exact'):
-                SETTINGS['EXACT'] = True
-            elif key in ('-C', '--nocolor', '--no-color'):
-                nocolor()
-            elif key in ('-L', '--library', '--library='):
-                _libs_to_check = _libs_to_check.union(val.split(','))
-            elif key in ('-i', '--ignore'):
-                SETTINGS['USE_TMP_FILES'] = False
-
-        args = " " + " ".join(args)
-    except getopt.GetoptError:
-        logging.info(red('Unrecognized option\n'))
-        print_usage()
-        sys.exit(2)
-
-    if not sys.stdout.isatty():
-        nocolor()
-
-    if os.getuid() != 0 and not SETTINGS['PRETEND']:
-        logger.warn(blue(' * ') + yellow('You are not root, adding --pretend to portage options'))
-        SETTINGS['PRETEND'] = True
-    elif not SETTINGS['PRETEND'] and SETTINGS['IS_DEV'] and not SETTINGS['NO_PRETEND']:
-        logger.warn(blue(' * ') + yellow('This is a development version, so it may not work correctly'))
-        logger.warn(blue(' * ') + yellow('Adding --pretend to portage options anyway'))
-        logger.info(blue(' * ') + 'If you\'re sure, you can add --no-pretend to revdep options')
-        SETTINGS['PRETEND'] = True
-
-
-    signal.signal(signal.SIGINT, exithandler)
-    signal.signal(signal.SIGTERM, exithandler)
-    signal.signal(signal.SIGPIPE, signal.SIG_DFL)
-
-    analyze_cache = {}
-    if SETTINGS['USE_TMP_FILES'] and check_temp_files():
-        libraries, la_libraries, libraries_links, binaries = read_cache()
-        assigned = analyse(libraries=libraries, la_libraries=la_libraries, \
-                       libraries_links=libraries_links, binaries=binaries, _libs_to_check=_libs_to_check)
-    else:
-        assigned = analyse()
-
-    if not assigned:
-        logger.warn('\n' + bold('Your system is consistent'))
-        sys.exit(0)
-
-
-    has_masked = False
-    tmp = []
-    for a in assigned:
-        if get_masking_status(a):
-            has_masked = True
-            logger.warn('!!! ' + red('All ebuilds that could satisfy: ') + green(a) + red(' have been masked'))
-        else:
-            tmp.append(a)
-    assigned = tmp
-
-    if has_masked:
-        logger.info(red(' * ') + 'Unmask all ebuild listed above and call revdep-rebuild again or manually emerge given packages.')
-
-
-    if SETTINGS['EXACT']:
-        emerge_command = '=' + ' ='.join(assigned)
-    else:
-        emerge_command = ' '.join(get_slotted_cps(assigned, logger))
-    if SETTINGS['PRETEND']:
-        args += ' --pretend'
-    if SETTINGS['VERBOSITY'] >= 2:
-        args += ' --verbose'
-    elif SETTINGS['VERBOSITY'] < 1:
-        args += ' --quiet'
-
-    if len(emerge_command) == 0:
-        logger.warn(bold('\nThere is nothing to emerge. Exiting.'))
-        sys.exit(0)
-
-    emerge_command = args + ' --oneshot ' + emerge_command
-
-    logger.warn(yellow('\nemerge') + bold(emerge_command))
-    os.system('emerge ' + emerge_command)
-
+def main(settings=None):
+
+       if settings is None:
+               print("NO Input settings, using defaults...")
+               settings = DEFAULTS.copy()
+
+       logger = init_logger(settings)
+
+       _libs_to_check = settings['library']
+
+       if not settings['stdout'].isatty() or settings['nocolor']:
+               nocolor()
+
+       if os.getuid() != 0 and not settings['PRETEND']:
+               logger.warn(blue(' * ') + 
+                       yellow('You are not root, adding --pretend to portage options'))
+               settings['PRETEND'] = True
+       elif not settings['PRETEND'] \
+                       and settings['IS_DEV'] \
+                       and not settings['NO_PRETEND']:
+               logger.warn(blue(' * ') + 
+                       yellow('This is a development version, '
+                               'so it may not work correctly'))
+               logger.warn(blue(' * ') + 
+                       yellow('Adding --pretend to portage options anyway'))
+               logger.info(blue(' * ') + 
+                       'If you\'re sure, you can add --no-pretend to revdep options')
+               settings['PRETEND'] = True
+
+       analyze_cache = {}
+       if settings['USE_TMP_FILES'] and check_temp_files():
+               libraries, la_libraries, libraries_links, binaries = read_cache()
+               assigned = analyse(libraries=libraries, la_libraries=la_libraries, 
+                       libraries_links=libraries_links,
+                       binaries=binaries,
+                       _libs_to_check=_libs_to_check)
+       else:
+               assigned = analyse(settings, logger)
+
+       if not assigned:
+               logger.warn('\n' + bold('Your system is consistent'))
+               # return the correct exit code
+               return 0
+
+       has_masked = False
+       tmp = []
+       for a in assigned:
+               if get_masking_status(a):
+                       has_masked = True
+                       logger.warn('!!! ' + red('All ebuilds that could satisfy: ') + 
+                               green(a) + red(' have been masked'))
+               else:
+                       tmp.append(a)
+       assigned = tmp
+
+       if has_masked:
+               logger.info(red(' * ') + 
+                       'Unmask all ebuild(s) listed above and call revdep-rebuild '
+                       'again or manually emerge given packages.')
+
+       success = rebuild(logger, assigned, settings)
+       logger.debug("rebuild return code =", success)
+       return success