diff options
| author | slis <lis.slawek@gmail.com> | 2014-01-21 11:48:32 +0100 |
|---|---|---|
| committer | slis <lis.slawek@gmail.com> | 2014-01-21 11:48:32 +0100 |
| commit | 4335bf979f374300ac6678765f490f92ee805ab4 (patch) | |
| tree | 938da11abd9746e87ed35d9ad9d7868f7a420f23 | |
| parent | 627386fe0402160f5255f2ed4dfd3b9d63c01f5e (diff) | |
| parent | 6282695a77af21bd60a31d182575c5a12a1a359b (diff) | |
| download | gentoolkit-4335bf979f374300ac6678765f490f92ee805ab4.tar.gz | |
Merged revdep-rebuild branch
| -rwxr-xr-x | bin/revdep-ng | 51 | ||||
| -rw-r--r-- | pym/gentoolkit/revdep_rebuild/analyse.py | 200 | ||||
| -rw-r--r-- | pym/gentoolkit/revdep_rebuild/assign.py | 23 | ||||
| -rw-r--r-- | pym/gentoolkit/revdep_rebuild/cache.py | 50 | ||||
| -rw-r--r-- | pym/gentoolkit/revdep_rebuild/collect.py | 33 | ||||
| -rw-r--r-- | pym/gentoolkit/revdep_rebuild/rebuild.py | 30 | ||||
| -rwxr-xr-x | pym/gentoolkit/revdep_rebuild/revdep-rebuild.py | 17 | ||||
| -rw-r--r-- | pym/gentoolkit/revdep_rebuild/runner.py | 114 | ||||
| -rw-r--r-- | pym/gentoolkit/revdep_rebuild/stuff.py | 4 |
9 files changed, 409 insertions, 113 deletions
diff --git a/bin/revdep-ng b/bin/revdep-ng new file mode 100755 index 0000000..a4c8e11 --- /dev/null +++ b/bin/revdep-ng @@ -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) diff --git a/pym/gentoolkit/revdep_rebuild/analyse.py b/pym/gentoolkit/revdep_rebuild/analyse.py index aad8f81..7b17517 100644 --- a/pym/gentoolkit/revdep_rebuild/analyse.py +++ b/pym/gentoolkit/revdep_rebuild/analyse.py @@ -28,27 +28,54 @@ def prepare_checks(files_to_check, libraries, bits, cmd_max_args): # list of lists of files (from file_to_check) that uses # library (for dependencies[id] and libs[id] => id==id) dependencies = [] - for line in scan( - ['-M', str(bits), '-nBF', '%F %n'], - files_to_check, cmd_max_args - ): - parts = line.strip().split(' ') - if len(parts) < 2: # no dependencies? + bits = [] + + +# from runner import ScanRunner +# sr = ScanRunner(['-M', str(bits), '-nBF', '%F %n'], files_to_check, cmd_max_args) +# sr.wait() + + for line in scan(['-M', str(bits), '-nBF', '%F %n %M'], files_to_check, cmd_max_args): + #call_program(['scanelf', '-M', str(bits), '-nBF', '%F %n',]+files_to_check).strip().split('\n'): + r = line.strip().split(' ') + if len(r) < 2: # no dependencies? continue - deps = parts[1].split(',') - for dep in deps: - if dep in libs: - index = libs.index(dep) - dependencies[index].append(parts[0]) + deps = r[1].split(',') + for d in deps: + if d in libs: + i = libs.index(d) + dependencies[i].append(r[0]) else: - libs.append(dep) - dependencies.append([parts[0],]) - + #print d, 'bits:', r[2][8:] # 8: -> strlen('ELFCLASS') + libs.append(d) + dependencies.append([r[0],]) + return (libs, dependencies) +def scan_files(libs_and_bins, cmd_max_args): + import os + + scanned_files = {} # {bits: {soname: (filename, needed), ...}, ...} + for line in scan(['-nBF', '%F %f %S %n %M'], libs_and_bins, cmd_max_args): + filename, sfilename, soname, needed, bits = line.split(' ') + filename = os.path.realpath(filename) + needed = needed.split(',') + bits = bits[8:] # 8: -> strlen('ELFCLASS') + if not soname: + soname = sfilename + + try: + scanned_files[bits][soname] = (filename, needed) + except KeyError: + scanned_files[bits] = {} + scanned_files[bits][soname] = (filename, needed) + return scanned_files + + + def extract_dependencies_from_la(la, libraries, to_check, logger): broken = [] @@ -122,6 +149,25 @@ def find_broken(found_libs, system_libraries, to_check): return broken +def find_broken2(scanned_files, logger): + broken_libs = {} + for bits, libs in scanned_files.items(): + logger.debug('Checking for bits: %s' % bits) + alllibs = '|'.join(libs.keys()) + '|' + for soname, needed in libs.items(): + for l in needed[1]: + if not l+'|' in alllibs: + try: + broken_libs[bits][l].add(soname) + except KeyError: + try: + broken_libs[bits][l] = set([soname]) + except KeyError: + broken_libs = {bits: {l: set([soname])}} + + return broken_libs + + def main_checks(found_libs, broken_list, dependencies, logger): ''' Checks for broken dependencies. found_libs have to be the same as returned by prepare_checks @@ -133,13 +179,25 @@ def main_checks(found_libs, broken_list, dependencies, logger): for broken in broken_list: found = found_libs[broken] - logger.info('Broken files that requires: ' + bold(found)) + logger.info('Broken files that requires: ' + bold(f)) for dep_path in dependencies[broken]: logger.info(yellow(' * ') + dep_path) broken_pathes.append(dep_path) return broken_pathes +def main_checks2(broken, scanned_files, logger): + broken_pathes = [] + for bits, _broken in broken.items(): + for soname, needed in _broken.items(): + logger.info('Broken files that requires: %s (%s bits)' % (bold(soname), bits)) + for n in needed: + fp = scanned_files[bits][n][0] + logger.info(yellow(' * ') + n + ' (' + fp + ')') + broken_pathes.append(fp) + return broken_pathes + + def analyse(settings, logger, libraries=None, la_libraries=None, libraries_links=None, binaries=None, _libs_to_check=set()): """Main program body. It will collect all info and determine the @@ -164,14 +222,15 @@ def analyse(settings, logger, libraries=None, la_libraries=None, masked_dirs, masked_files, ld = \ parse_revdep_config(settings['REVDEP_CONFDIR']) - lib_dirs.update(ld) - bin_dirs.update(ld) - masked_dirs.update([ - '/lib/modules', - '/lib32/modules', - '/lib64/modules' - ] - ) + lib_dirs = lib_dirs.union(ld) + bin_dirs = bin_dirs.union(ld) + masked_dirs = masked_dirs.union( + set([ + '/lib/modules', + '/lib32/modules', + '/lib64/modules', + ]) + ) logger.info(green(' * ') + bold('Collecting dynamic linking informations')) @@ -188,56 +247,79 @@ def analyse(settings, logger, libraries=None, la_libraries=None, ) - logger.debug('Found '+ str(len(libraries)) + - ' libraries (+' + str(len(libraries_links)) + - ' symlinks) and ' + str(len(binaries)) + - ' binaries') + logger.debug('Found %i libraries (+%i symlinks) and %i binaries' % + (len(libraries), len(libraries_links), len(binaries)) + ) + logger.info(green(' * ') + bold('Scanning files')) + + libs_and_bins = libraries+binaries + scanned_files = scan_files(libs_and_bins, settings['CMD_MAX_ARGS']) + logger.warn(green(' * ') + bold('Checking dynamic linking consistency')) - logger.debug('Search for ' + str(len(binaries)+len(libraries)) + - ' within ' + str(len(libraries)+len(libraries_links))) - libs_and_bins = libraries+binaries + logger.debug('Search for %i within %i' % + (len(binaries)+len(libraries), len(libraries)+len(libraries_links)) + ) + + broken = find_broken2(scanned_files, logger) + broken_pathes = main_checks2(broken, scanned_files, logger) + + broken_la = extract_dependencies_from_la(la_libraries, libraries+libraries_links, _libs_to_check, logger) + broken_pathes += broken_la - found_libs = [] - dependencies = [] + logger.warn(green(' * ') + bold('Assign files to packages')) + + return assign_packages(broken_pathes, logger, settings) - if _libs_to_check: - nltc = [] - for ltc in _libs_to_check: - if os.path.isfile(ltc): - ltc = scan(['-nBSF', '%S'], [ltc,], settings['CMD_MAX_ARGS'])[0].split()[0] - nltc += [ltc,] - _libs_to_check = nltc + import sys + sys.exit() + + #l = [] + #for line in call_program(['scanelf', '-M', '64', '-BF', '%F',] + libraries).strip().split('\n'): + #l.append(line) + #libraries = l - _bits, linkg = platform.architecture() - if _bits.startswith('32'): - bits = 32 - elif _bits.startswith('64'): - bits = 64 + ## old version from here + #found_libs = [] + #dependencies = [] - broken = [] - for av_bits in glob.glob('/lib[0-9]*') or ('/lib32',): - bits = int(av_bits[4:]) + #if _libs_to_check: + #nltc = [] + #for ltc in _libs_to_check: + #if os.path.isfile(ltc): + #ltc = scan(['-nBSF', '%S'], [ltc,], settings['CMD_MAX_ARGS'])[0].split()[0] + #nltc += [ltc,] + #_libs_to_check = nltc - _libraries = libraries+libraries_links + #_bits, linkg = platform.architecture() + #if _bits.startswith('32'): + #bits = 32 + #elif _bits.startswith('64'): + #bits = 64 - found_libs, dependencies = prepare_checks(libs_and_bins, - _libraries, bits, settings['CMD_MAX_ARGS']) - broken = find_broken(found_libs, _libraries, _libs_to_check) + #import time + #broken = [] + #for av_bits in glob.glob('/lib[0-9]*') or ('/lib32',): + #bits = int(av_bits[4:]) - bits /= 2 - bits = int(bits) + ##_libraries = scan(['-M', str(bits), '-BF', '%F'], libraries+libraries_links, settings['CMD_MAX_ARGS']) + #_libraries = libraries+libraries_links - broken_la = extract_dependencies_from_la(la_libraries, - libraries+libraries_links, _libs_to_check, logger) + #found_libs, dependencies = prepare_checks(libs_and_bins, _libraries, bits, settings['CMD_MAX_ARGS']) + #broken = find_broken(found_libs, _libraries, _libs_to_check) + #bits /= 2 + #bits = int(bits) - broken_pathes = main_checks(found_libs, broken, dependencies, logger) - broken_pathes += broken_la + #broken_la = extract_dependencies_from_la(la_libraries, libraries+libraries_links, _libs_to_check, logger) - logger.warn(green(' * ') + bold('Assign files to packages')) - return assign_packages(broken_pathes, logger, settings) + #broken_pathes = main_checks(found_libs, broken, dependencies, logger) + #broken_pathes += broken_la + + #logger.warn(green(' * ') + bold('Assign files to packages')) + + #return assign_packages(broken_pathes, logger, settings) diff --git a/pym/gentoolkit/revdep_rebuild/assign.py b/pym/gentoolkit/revdep_rebuild/assign.py index e8e87b3..2a93fe1 100644 --- a/pym/gentoolkit/revdep_rebuild/assign.py +++ b/pym/gentoolkit/revdep_rebuild/assign.py @@ -27,10 +27,25 @@ def assign_packages(broken, logger, settings): Broken is list of files ''' assigned = set() - if not broken: - return assigned + for group in os.listdir(settings['PKG_DIR']): + for pkg in os.listdir(settings['PKG_DIR'] + group): + f = settings['PKG_DIR'] + group + '/' + pkg + '/CONTENTS' + if os.path.exists(f): + try: + with open(f, 'r') as cnt: + for line in cnt.readlines(): + m = re.match('^obj (/[^ ]+)', line) + if m is not None: + m = m.group(1) + if m in broken: + found = group+'/'+pkg + if found not in assigned: + assigned.add(found) + logger.info('\t' + m + ' -> ' + bold(found)) + except Exception as e: + logger.warn(red(' !! Failed to read ' + f)) - pkgset = set(get_installed_cpvs()) + return assigned # Map all files in CONTENTS database to package names fname_pkg_dict = {} @@ -88,6 +103,8 @@ def get_best_match(cpv, cp, logger): def get_slotted_cps(cpvs, logger): """Uses portage to reduce the cpv list into a cp:slot list and returns it """ + from portage.versions import catpkgsplit + from portage import portdb cps = [] for cpv in cpvs: diff --git a/pym/gentoolkit/revdep_rebuild/cache.py b/pym/gentoolkit/revdep_rebuild/cache.py index d6ef7ce..1be8cb0 100644 --- a/pym/gentoolkit/revdep_rebuild/cache.py +++ b/pym/gentoolkit/revdep_rebuild/cache.py @@ -29,9 +29,9 @@ def read_cache(temp_path=DEFAULTS['DEFAULT_TMP_DIR']): 'binaries':[] } try: - for key, val in list(ret.items()): - _file = open(os.path.join(temp_path, key)) - for line in _file .readlines(): + for key,val in ret.iteritems(): + _file = open(os.path.join(temp_path, key)) + for line in _file.readlines(): val.append(line.strip()) #libraries.remove('\n') _file .close() @@ -42,26 +42,22 @@ def read_cache(temp_path=DEFAULTS['DEFAULT_TMP_DIR']): ret['libraries_links'], ret['binaries']) -def save_cache(logger, to_save=None, temp_path=DEFAULTS['DEFAULT_TMP_DIR']): +def save_cache(logger, to_save={}, temp_path=DEFAULTS['DEFAULT_TMP_DIR']): ''' Tries to store caching information. @param logger @param to_save have to be dict with keys: libraries, la_libraries, libraries_links and binaries ''' - if to_save is None: - to_save = {} - -# TODO: Don't blindly make the cache directory, see Bug 203414 -# if not os.path.exists(temp_path): -# os.makedirs(temp_path) + if not os.path.exists(temp_path): + os.makedirs(temp_path) try: _file = open(os.path.join(temp_path, 'timestamp'), 'w') _file.write(str(int(time.time()))) _file.close() - for key, val in list(to_save.items()): + for key,val in to_save.iteritems(): _file = open(os.path.join(temp_path, key), 'w') for line in val: _file.write(line + '\n') @@ -71,8 +67,7 @@ def save_cache(logger, to_save=None, temp_path=DEFAULTS['DEFAULT_TMP_DIR']): -def check_temp_files(temp_path=DEFAULTS['DEFAULT_TMP_DIR'], max_delay=3600, - logger=None): +def check_temp_files(temp_path=DEFAULTS['DEFAULT_TMP_DIR'], max_delay=3600): ''' Checks if temporary files from previous run are still available and if they aren't too old @param temp_path is directory, where temporary files should be found @@ -110,27 +105,26 @@ if __name__ == '__main__': from .collect import (prepare_search_dirs, parse_revdep_config, collect_libraries_from_dir, collect_binaries_from_dir) - import logging - bin_dirs, lib_dirs = prepare_search_dirs(logging, DEFAULTS) + bin_dirs, lib_dirs = prepare_search_dirs() - masked_dirs, masked_files, ld = parse_revdep_config("/etc/revdep-rebuild/") - lib_dirs.update(ld) - bin_dirs.update(ld) - masked_dirs = masked_dirs.update([ - '/lib/modules', - '/lib32/modules', - '/lib64/modules' - ] - ) + masked_dirs, masked_files, ld = parse_revdep_config() + lib_dirs = lib_dirs.union(ld) + bin_dirs = bin_dirs.union(ld) + masked_dirs = masked_dirs.union( + set([ + '/lib/modules', + '/lib32/modules', + '/lib64/modules', + ]) + ) - libraries, la_libraries, libraries_links, symlink_pairs = \ - collect_libraries_from_dir(lib_dirs, masked_dirs, logging) + libraries, la_libraries, libraries_links, symlink_pairs = collect_libraries_from_dir(lib_dirs, masked_dirs, logging) binaries = collect_binaries_from_dir(bin_dirs, masked_dirs, logging) - save_cache(logger=logging, - to_save={'libraries':libraries, 'la_libraries':la_libraries, + save_cache(logger=logging, + to_save={'libraries':libraries, 'la_libraries':la_libraries, 'libraries_links':libraries_links, 'binaries':binaries} ) diff --git a/pym/gentoolkit/revdep_rebuild/collect.py b/pym/gentoolkit/revdep_rebuild/collect.py index 740ae32..f8ee60d 100644 --- a/pym/gentoolkit/revdep_rebuild/collect.py +++ b/pym/gentoolkit/revdep_rebuild/collect.py @@ -21,13 +21,13 @@ def parse_conf(conf_file, visited=None, logger=None): lib_dirs = set() to_parse = set() - if isinstance(conf_file, str): + if isinstance(conf_file, basestring): conf_file = [conf_file] for conf in conf_file: try: with open(conf) as _file: - for line in _file: + for line in _file.readlines(): line = line.strip() if line.startswith('#'): continue @@ -40,7 +40,7 @@ def parse_conf(conf_file, visited=None, logger=None): else: path = included - to_parse.update(glob.glob(path)) + to_parse = to_parse.union(glob.glob(path)) else: lib_dirs.add(line) except EnvironmentError: @@ -49,10 +49,10 @@ def parse_conf(conf_file, visited=None, logger=None): if visited is None: visited = set() - visited.update(conf_file) - to_parse.difference_update(visited) + visited = visited.union(conf_file) + to_parse = to_parse.difference(visited) if to_parse: - lib_dirs.update(parse_conf(to_parse, visited, logger=logger)) + lib_dirs = lib_dirs.union(parse_conf(to_parse, visited, logger=logger)) return lib_dirs @@ -68,7 +68,7 @@ def prepare_search_dirs(logger, settings): #try: with open(os.path.join( portage.root, settings['DEFAULT_ENV_FILE']), 'r') as _file: - for line in _file: + for line in _file.readlines(): line = line.strip() match = re.match("^export (ROOT)?PATH='([^']+)'", line) if match is not None: @@ -250,13 +250,18 @@ def collect_binaries_from_dir(dirs, mask, logger): if __name__ == '__main__': import logging - from .settings import DEFAULTS - mbin_dirs, mlib_dirs = prepare_search_dirs(logging, DEFAULTS) - - mmasked_dirs, mmasked_files, mld = parse_revdep_config("/etc/revdep-rebuild/") - mlib_dirs.update(mld) - mbin_dirs.update(mld) - mmasked_dirs.update(['/lib/modules', '/lib32/modules', '/lib64/modules']) + bin_dirs, lib_dirs = prepare_search_dirs(logging) + + masked_dirs, masked_files, ld = parse_revdep_config() + lib_dirs = lib_dirs.union(ld) + bin_dirs = bin_dirs.union(ld) + masked_dirs = masked_dirs.union( + set([ + '/lib/modules', + '/lib32/modules', + '/lib64/modules', + ]) + ) libraries, la_libraries, libraries_links, msymlink_pairs = \ collect_libraries_from_dir(mlib_dirs, mmasked_dirs, logging) diff --git a/pym/gentoolkit/revdep_rebuild/rebuild.py b/pym/gentoolkit/revdep_rebuild/rebuild.py index 8d21b76..386ac33 100644 --- a/pym/gentoolkit/revdep_rebuild/rebuild.py +++ b/pym/gentoolkit/revdep_rebuild/rebuild.py @@ -106,7 +106,8 @@ def parse_options(): do_help = False for key, val in opts: if key in ('-h', '--help'): - do_help = True + print_usage() + sys.exit(0) elif key in ('-q', '--quiet'): settings['quiet'] = True settings['VERBOSITY'] = 0 @@ -134,9 +135,7 @@ def parse_options(): print(red('Unrecognized option\n')) print_usage() sys.exit(2) - if do_help: - print_usage() - sys.exit(0) + return settings @@ -207,13 +206,21 @@ def main(settings=None, logger=None): 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 - if settings['library']: - logger.warn(green(' * ') + - "Looking for libraries: %s" % (bold(', '.join(settings['library'])))) - + analyze_cache = {} if settings['USE_TMP_FILES'] \ - and check_temp_files(settings['DEFAULT_TMP_DIR'], logger=logger): + and check_temp_files(settings['DEFAULT_TMP_DIR']): libraries, la_libraries, libraries_links, binaries = read_cache( settings['DEFAULT_TMP_DIR']) assigned = analyse( @@ -251,3 +258,8 @@ def main(settings=None, logger=None): success = rebuild(logger, assigned, settings) logger.debug("rebuild return code = %i" %success) return success + + +if __name__ == '__main__': + main(parse_options()) + diff --git a/pym/gentoolkit/revdep_rebuild/revdep-rebuild.py b/pym/gentoolkit/revdep_rebuild/revdep-rebuild.py new file mode 100755 index 0000000..2619ee0 --- /dev/null +++ b/pym/gentoolkit/revdep_rebuild/revdep-rebuild.py @@ -0,0 +1,17 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + + +# Author: Sławomir Lis <lis.slawek@gmail.com> +# revdep-rebuild original author: Stanislav Brabec +# revdep-rebuild original rewrite Author: Michael A. Smith +# Current Maintainer: Paul Varner <fuzzyray@gentoo.org> + +# Creation date: 2010/10/17 +# License: BSD + +from rebuild import APP_NAME, VERSION, main + +if __name__ == '__main__': + # instead of revdep-rebuild.py call rebuild.py + main() diff --git a/pym/gentoolkit/revdep_rebuild/runner.py b/pym/gentoolkit/revdep_rebuild/runner.py new file mode 100644 index 0000000..24411a5 --- /dev/null +++ b/pym/gentoolkit/revdep_rebuild/runner.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- + +import threading +import subprocess + + +class ProcessRunner(threading.Thread): + ''' + ProcessRunner is class designed to run arbitrary command + in background (separate thread). It's replacement for old + stuff.call_program function. + + When called program is finished, its output can be accessed + through .stdout and .stderr fields + ''' + + def __init__(self, args, autorun=True): + ''' + @param args - program name and its arguments + @param autorun - if True, then automatically starts new thread + ''' + + threading.Thread.__init__(self) + self.args = args + self.lock = threading.Lock() + self.stdout = '' + self.stderr = '' + + if autorun: + self.start() + + + + def run(self): + self.lock.acquire() + + subp = subprocess.Popen(self.args, stdout=subprocess.PIPE, \ + stderr=subprocess.PIPE) + self.stdout, self.stderr = subp.communicate() + self.lock.release() + + + def is_ready(self): + ''' Checks whether current command is finished ''' + return not self.lock.locked() + + + def wait(self): + ''' Waits until called program finishes ''' + self.lock.acquire() + self.lock.release() + + + + +class ScanRunner(threading.Thread): + ''' + ScanRunner is a class for calling scanelf in separate + thread, so several instances could be called at a time, + and then all results could be consolidated. + + Consolidated output is available through .out + ''' + + def __init__(self, params, files, max_args, autorun=True): + ''' + @param params is list of parameters that should be passed into scanelf app. + @param files list of files to scan. + @param max_args number of files to process at once + @param autorun automatically start new thread + + When files count is greater CMD_MAX_ARGS, then scanelf will be called + several times. + ''' + + threading.Thread.__init__(self) + self.params = params + self.files = files + self.max_args = max_args + + self.out = [] + self.lock = threading.Lock() + + if autorun: + self.start() + + + def run(self): + self.lock.acquire() + + process_pool = [] + for i in range(0, len(self.files), self.max_args): + process_pool.append(ProcessRunner(['scanelf'] + self.params + self.files[i:i+self.max_args])) + + while process_pool: + p = process_pool.pop() + p.wait() + self.out += p.stdout.strip().split('\n') + + self.lock.release() + + + def is_ready(self): + ''' Checks whether scanning is finished ''' + return not self.lock.locked() + + + def wait(self): + ''' Waits until all scanning instances are finished ''' + self.lock.acquire() + self.lock.release() + + +
\ No newline at end of file diff --git a/pym/gentoolkit/revdep_rebuild/stuff.py b/pym/gentoolkit/revdep_rebuild/stuff.py index e78748c..0bebce2 100644 --- a/pym/gentoolkit/revdep_rebuild/stuff.py +++ b/pym/gentoolkit/revdep_rebuild/stuff.py @@ -43,6 +43,10 @@ def scan(params, files, max_args): return out +def exithandler(signum, frame): + sys.exit(1) + + def get_masking_status(ebuild): """returns the masking status of an ebuild |
