summaryrefslogtreecommitdiff
path: root/Tools/scripts/chkdepschain.py
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/scripts/chkdepschain.py')
-rwxr-xr-xTools/scripts/chkdepschain.py320
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