diff options
Diffstat (limited to 'Tools/scripts/chkdepschain.py')
-rwxr-xr-x | Tools/scripts/chkdepschain.py | 320 |
1 files changed, 0 insertions, 320 deletions
diff --git a/Tools/scripts/chkdepschain.py b/Tools/scripts/chkdepschain.py deleted file mode 100755 index dfbb0e4817ff..000000000000 --- a/Tools/scripts/chkdepschain.py +++ /dev/null @@ -1,320 +0,0 @@ -#!/usr/bin/env python -# -# ---------------------------------------------------------------------------- -# "THE BEER-WARE LICENSE" (Revision 42, (c) Poul-Henning Kamp): -# Maxim Sobolev <sobomax@FreeBSD.org> wrote this file. As long as you retain -# this notice you can do whatever you want with this stuff. If we meet some -# day, and you think this stuff is worth it, you can buy me a beer in return. -# -# Maxim Sobolev -# ---------------------------------------------------------------------------- -# -# $FreeBSD$ -# -# MAINTAINER= sobomax@FreeBSD.org <- any unapproved commits to this file are -# highly discouraged!!! -# - -import os, os.path, popen2, types, sys, getopt, pickle - -# Global constants and semi-constants -PKG_DBDIR = '/var/db/pkg' -PORTSDIR = '/usr/ports' -ROOT_PORTMK = '/usr/share/mk/bsd.port.mk' -PLIST_FILE = '+CONTENTS' -ORIGIN_PREF = '@comment ORIGIN:' -MAKEFILE = 'Makefile' -MAKE = 'make' -ERR_PREF = 'Error:' -WARN_PREF = 'Warning:' - -# Global variables -# -# PortInfo cache -picache = {} - -# Useful aliases -op_isdir = os.path.isdir -op_join = os.path.join -op_split = os.path.split -op_abspath = os.path.abspath - - -# -# Query origin of specified installed package. -# -def getorigin(pkg): - plist = op_join(PKG_DBDIR, pkg, PLIST_FILE) - for line in open(plist).xreadlines(): - if line.startswith(ORIGIN_PREF): - origin = line[len(ORIGIN_PREF):].strip() - break - else: - raise RuntimeError('%s: no origin recorded' % plist) - - return origin - - -# -# Execute external command and return content of its stdout. -# -def getcmdout(cmdline, filterempty = 1): - pipe = popen2.Popen3(cmdline, 1) - results = pipe.fromchild.readlines() - for stream in (pipe.fromchild, pipe.tochild, pipe.childerr): - stream.close() - - if pipe.wait() != 0: - if type(cmdline) is types.StringType: - cmdline = (cmdline) - raise IOError('%s: external command returned non-zero error code' % \ - cmdline[0]) - - if filterempty != 0: - results = filter(lambda line: len(line.strip()) > 0, results) - - return results - - -# -# For a specified path (either dir or makefile) query requested make(1) -# variables and return them as a tuple in exactly the same order as they -# were specified in function call, i.e. querymakevars('foo', 'A', 'B') will -# return a tuple with a first element being the value of A variable, and -# the second one - the value of B. -# -def querymakevars(path, *vars): - if op_isdir(path): - path = op_join(path, MAKEFILE) - dirname, makefile = op_split(path) - cmdline = [MAKE, '-f', makefile] - savedir = os.getcwd() - os.chdir(dirname) - try: - for var in vars: - cmdline.extend(('-V', var)) - - results = map(lambda line: line.strip(), getcmdout(cmdline, 0)) - finally: - os.chdir(savedir) - - return tuple(results) - - -def parsedeps(depstr): - return tuple(map(lambda dep: dep.split(':'), depstr.split())) - - -# -# For a specified port return either a new instance of the PortInfo class, -# or existing instance from the cache. -# -def getpi(path): - path = op_abspath(path) - if not picache.has_key(path): - picache[path] = PortInfo(path) - return picache[path] - - -# -# Format text string according to requested constrains. Useful when you have -# to display multi-line, variable width message on terminal. -# -def formatmsg(msg, wrapat = 78, seclindent = 0): - words = msg.split() - result = '' - position = 0 - for word in words: - if position + 1 + len(word) > wrapat: - result += '\n' + ' ' * seclindent + word - position = seclindent + len(word) - else: - if position != 0: - result += ' ' - position += 1 - result += word - position += len(word) - - return result - - -# -# Class that contain main info about the port -# -class PortInfo: - PKGNAME = None - CATEGORIES = None - MAINTAINER = None - BUILD_DEPENDS = None - LIB_DEPENDS = None - RUN_DEPENDS = None - PKGORIGIN = None - # Cached values, to speed-up things - __deps = None - __bt_deps = None - __rt_deps = None - - def __init__(self, path): - self.PKGNAME, self.CATEGORIES, self.MAINTAINER, self.BUILD_DEPENDS, \ - self.LIB_DEPENDS, self.RUN_DEPENDS, self.PKGORIGIN = \ - querymakevars(path, 'PKGNAME', 'CATEGORIES', 'MAINTAINER', \ - 'BUILD_DEPENDS', 'LIB_DEPENDS', 'RUN_DEPENDS', 'PKGORIGIN') - - def __str__(self): - return 'PKGNAME:\t%s\nCATEGORIES:\t%s\nMAINTAINER:\t%s\n' \ - 'BUILD_DEPENDS:\t%s\nLIB_DEPENDS:\t%s\nRUN_DEPENDS:\t%s\n' \ - 'PKGORIGIN:\t%s' % (self.PKGNAME, self.CATEGORIES, self.MAINTAINER, \ - self.BUILD_DEPENDS, self.LIB_DEPENDS, self.RUN_DEPENDS, \ - self.PKGORIGIN) - - def getdeps(self): - if self.__deps == None: - result = [] - for depstr in self.BUILD_DEPENDS, self.LIB_DEPENDS, \ - self.RUN_DEPENDS: - deps = tuple(map(lambda dep: dep[1], parsedeps(depstr))) - result.append(deps) - self.__deps = tuple(result) - return self.__deps - - def get_bt_deps(self): - if self.__bt_deps == None: - topdeps = self.getdeps() - topdeps = list(topdeps[0] + topdeps[1]) - for dep in topdeps[:]: - botdeps = filter(lambda dep: dep not in topdeps, \ - getpi(dep).get_rt_deps()) - topdeps.extend(botdeps) - self.__bt_deps = tuple(topdeps) - return self.__bt_deps - - def get_rt_deps(self): - if self.__rt_deps == None: - topdeps = self.getdeps() - topdeps = list(topdeps[1] + topdeps[2]) - for dep in topdeps[:]: - botdeps = filter(lambda dep: dep not in topdeps, \ - getpi(dep).get_rt_deps()) - topdeps.extend(botdeps) - self.__rt_deps = tuple(topdeps) - return self.__rt_deps - - -def write_msg(*message): - if type(message) == types.StringType: - message = message, - message = tuple(filter(lambda line: line != None, message)) - sys.stderr.writelines(message) - - -# -# Print optional message and usage information and exit with specified exit -# code. -# -def usage(code, msg = None): - myname = os.path.basename(sys.argv[0]) - if msg != None: - msg = str(msg) + '\n' - write_msg(msg, "Usage: %s [-rb] [-l|L cachefile] [-s cachefile]\n" % \ - myname) - sys.exit(code) - - -def main(): - global picache - - # Parse command line arguments - try: - opts, args = getopt.getopt(sys.argv[1:], 'erbl:L:s:') - except getopt.GetoptError, msg: - usage(2, msg) - - if len(args) > 0 or len(opts) == 0 : - usage(2) - - cachefile = None - chk_bt_deps = 0 - chk_rt_deps = 0 - warn_as_err = 0 - for o, a in opts: - if o == '-b': - chk_bt_deps = 1 - elif o == '-r': - chk_rt_deps = 1 - elif o in ('-l', '-L'): - # Try to load saved PortInfo cache - try: - picache = pickle.load(open(a)) - except: - picache = {} - try: - if o == '-L': - os.unlink(a) - except: - pass - elif o == '-s': - cachefile = a - elif o == '-e': - warn_as_err = 1 - - # Load origins of all installed packages - instpkgs = os.listdir(PKG_DBDIR) - instpkgs = filter(lambda pkg: op_isdir(op_join(PKG_DBDIR, pkg)), instpkgs) - origins = {} - for pkg in instpkgs: - origins[pkg] = getorigin(pkg) - - # Resolve dependencies for the current port - info = getpi(os.getcwd()) - deps = [] - if chk_bt_deps != 0: - deps.extend(filter(lambda d: d not in deps, info.get_bt_deps())) - if chk_rt_deps != 0: - deps.extend(filter(lambda d: d not in deps, info.get_rt_deps())) - - # Perform validation - nerrs = 0 - nwarns = 0 - if warn_as_err == 0: - warn_pref = WARN_PREF - else: - warn_pref = ERR_PREF - err_pref = ERR_PREF - for dep in deps: - pi = getpi(dep) - if pi.PKGORIGIN not in origins.values(): - print formatmsg(seclindent = 7 * 0, msg = \ - '%s package %s (%s) belongs to dependency chain, but ' \ - 'isn\'t installed.' % (err_pref, pi.PKGNAME, pi.PKGORIGIN)) - nerrs += 1 - elif pi.PKGNAME not in origins.keys(): - for instpkg in origins.keys(): - if origins[instpkg] == pi.PKGORIGIN: - break - print formatmsg(seclindent = 9 * 0, msg = \ - '%s package %s (%s) belongs to dependency chain, but ' \ - 'package %s is installed instead. Perhaps it\'s an older ' \ - 'version - update is highly recommended.' % (warn_pref, \ - pi.PKGNAME, pi.PKGORIGIN, instpkg)) - nwarns += 1 - - # Save PortInfo cache if requested - if cachefile != None: - try: - pickle.dump(picache, open(cachefile, 'w')) - except: - pass - - if warn_as_err != 0: - nerrs += nwarns - - return nerrs - - -PORTSDIR, PKG_DBDIR = querymakevars(ROOT_PORTMK, 'PORTSDIR', 'PKG_DBDIR') - -if __name__ == '__main__': - try: - sys.exit(main()) - except KeyboardInterrupt: - pass |