Revision: 7741 http://gar.svn.sourceforge.net/gar/?rev=7741&view=rev Author: wahwah Date: 2009-12-24 15:41:02 +0000 (Thu, 24 Dec 2009)
Log Message: ----------- mGAR v2-checkpkg: Dependency reporting done, error code returning done. Modified Paths: -------------- csw/mgar/gar/v2-checkpkg/bin/checkpkg csw/mgar/gar/v2-checkpkg/bin/checkpkg.d/checkpkg-libs.py csw/mgar/gar/v2-checkpkg/bin/checkpkg.d/checkpkg.py Modified: csw/mgar/gar/v2-checkpkg/bin/checkpkg =================================================================== --- csw/mgar/gar/v2-checkpkg/bin/checkpkg 2009-12-24 14:01:28 UTC (rev 7740) +++ csw/mgar/gar/v2-checkpkg/bin/checkpkg 2009-12-24 15:41:02 UTC (rev 7741) @@ -83,6 +83,11 @@ pkgnames="$pkgnames $pkgname" } +if [[ "$1" == "-d" ]] ; then + DEBUG=1 + shift +fi + if [[ "$1" == "-e" ]] ; then quit_on_warn=1; shift @@ -422,7 +427,7 @@ #cat $EXTRACTDIR/elflist| xargs ldd 2>/dev/null |fgrep '.so' | # sed 's:^.*=>[^/]*::' | nawk '{print $1}' |sort -u >$EXTRACTDIR/liblist - cat $EXTRACTDIR/elflist| xargs dump -Lv |nawk '$2=="NEEDED"{print $3}' | + cat $EXTRACTDIR/elflist| xargs /usr/ccs/bin/dump -Lv |nawk '$2=="NEEDED"{print $3}' | sort -u | egrep -v $EXTRACTDIR >$EXTRACTDIR/liblist @@ -564,13 +569,16 @@ checkpkg_scriptname=`basename $0` checkpkg_basedir=${0%/${checkpkg_scriptname}} plugindir=${checkpkg_basedir}/checkpkg.d +if [[ "${DEBUG}" != "" ]]; then + extra_options="--debug" +fi echo "plugindir: '$plugindir'" if [[ -d "$plugindir" ]]; then # echo plugin dir exists for plugin in "${plugindir}"/checkpkg-*; do if [[ -x "${plugin}" ]]; then - echo "Executing: ${plugin} -e \"${EXTRACTDIR}\" ${pkgnames}" - ${plugin} -e "${EXTRACTDIR}" ${pkgnames} + echo "Executing: ${plugin} $extra_options -e \"${EXTRACTDIR}\" ${pkgnames}" + ${plugin} $extra_options -e "${EXTRACTDIR}" ${pkgnames} if [[ "$?" -ne 0 ]]; then errmsg "Plugin ${plugin} has returned an error." fi @@ -581,11 +589,10 @@ else echo plugin dir does not exist fi +# echo "Profiling." +# python -m cProfile gar/bin/checkpkg.d/checkpkg-libs.py --debug -e "${EXTRACTDIR}" ${pkgnames} # End of plugin section -# Not doing the cleanup now -# cleanup - print "" # Cleaning up after all packages Modified: csw/mgar/gar/v2-checkpkg/bin/checkpkg.d/checkpkg-libs.py =================================================================== --- csw/mgar/gar/v2-checkpkg/bin/checkpkg.d/checkpkg-libs.py 2009-12-24 14:01:28 UTC (rev 7740) +++ csw/mgar/gar/v2-checkpkg/bin/checkpkg.d/checkpkg-libs.py 2009-12-24 15:41:02 UTC (rev 7741) @@ -11,14 +11,20 @@ import re import subprocess import logging +import sys DUMP_BIN = "/usr/ccs/bin/dump" NEEDED_SONAMES = "needed sonames" RUNPATH = "runpath" +TYPICAL_DEPENDENCIES = set(["CSWcommon", "CSWcswclassutils"]) def main(): - logging.basicConfig(level=logging.DEBUG) options, args = checkpkg.GetOptions() + if options.debug: + logging.basicConfig(level=logging.DEBUG) + else: + logging.basicConfig(level=logging.INFO) + result_ok = True pkgnames = args checkers = [] for pkgname in pkgnames: @@ -31,39 +37,18 @@ binaries_base = [os.path.split(x)[1] for x in pkg_binary_paths] binaries_by_pkgname[checker.pkgname] = binaries_base binaries.extend(pkg_binary_paths) - # Make the binaries unique + # Making the binaries unique binaries = set(binaries) ws_re = re.compile(r"\s+") - # if [[ "$goodarch" = "yes" ]] ; then - # # man ld.so.1 for more info on this hack - # export LD_NOAUXFLTR=1 - # - # listbinaries $EXTRACTDIR/$pkgname >$EXTRACTDIR/elflist - # # have to do this for ldd to work. arrg. - # if [ -s "$EXTRACTDIR/elflist" ] ; then - # chmod 0755 `cat $EXTRACTDIR/elflist` - # - # cat $EXTRACTDIR/elflist| xargs dump -Lv |nawk '$2=="NEEDED"{print $3}' | - # sort -u | egrep -v $EXTRACTDIR >$EXTRACTDIR/liblist - # - # - # - # print libraries used are: - # cat $EXTRACTDIR/liblist - # print "cross-referencing with depend file (May take a while)" - # else - # print No dynamic libraries in the package - # fi - # fi - + # man ld.so.1 for more info on this hack env = copy.copy(os.environ) env["LD_NOAUXFLTR"] = "1" needed_sonames_by_binary = {} # Assembling a data structure with the data about binaries. # { - # <binary1 name>: {NEEDED_SONAMES: [...], - # RUNPATH: [...]}, + # <binary1 name>: { NEEDED_SONAMES: [...], + # RUNPATH: [...]}, # <binary2 name>: ..., # ... # } @@ -74,7 +59,7 @@ needed_sonames_by_binary[binary_base_name] = {} binary_data = needed_sonames_by_binary[binary_base_name] args = [DUMP_BIN, "-Lv", binary] - dump_proc = subprocess.Popen(args, stdout=subprocess.PIPE) + dump_proc = subprocess.Popen(args, stdout=subprocess.PIPE, env=env) stdout, stderr = dump_proc.communicate() ret = dump_proc.wait() for line in stdout.splitlines(): @@ -114,23 +99,19 @@ binaries_by_soname[soname].append(binary_name) pkgmap = checkpkg.SystemPkgmap() - paths_by_soname = pkgmap.paths_by_soname - - logging.debug("Determining soname-file relationships.") + logging.debug("Determining the soname-package relationships.") # lines by soname is an equivalent of $EXTRACTDIR/shortcatalog lines_by_soname = {} for soname in needed_sonames: - if soname in paths_by_soname: - # logging.debug("%s found", repr(soname)) - # Finding the first matching path + try: for runpath in runpath_by_needed_soname[soname]: - if runpath in paths_by_soname[soname]: - # logging.debug("%s found in %s", runpath, paths_by_soname[soname]) - # logging.debug("line found: %s", repr(paths_by_soname[soname][runpath])) - lines_by_soname[soname] = paths_by_soname[soname][runpath] + if runpath in pkgmap.GetPkgmapLineByBasename(soname): + # logging.debug("%s found in %s", runpath, pkgmap.GetPkgmapLineByBasename(soname)) + # logging.debug("line found: %s", repr(pkgmap.GetPkgmapLineByBasename(soname)[runpath])) + lines_by_soname[soname] = pkgmap.GetPkgmapLineByBasename(soname)[runpath] break - else: - logging.debug("%s not found in the soname list!", soname) + except KeyError, e: + logging.debug("KeyError: %s", soname, e) pkgs_by_soname = {} for soname, line in lines_by_soname.iteritems(): # TODO: Find all the packages, not just the last field. @@ -138,8 +119,10 @@ # For now, we'll assume that the last field is the package. pkgname = fields[-1] pkgs_by_soname[soname] = pkgname + + # A shared object dependency/provisioning report, plus checking. for soname in needed_sonames: - if soname in binaries: + if soname in needed_sonames_by_binary: print "%s is provided by the package itself" % soname elif soname in lines_by_soname: print ("%s is required by %s and provided by %s" @@ -149,91 +132,49 @@ else: print ("%s is required by %s, but we don't know what provides it." % (soname, binaries_by_soname[soname])) + result_ok = False + dependent_pkgs = {} - for pkgname in binaries_by_pkgname: + for checker in checkers: + orphan_sonames = set() + pkgname = checker.pkgname # logging.debug("Reporting package %s", pkgname) - dependencies = set() + declared_dependencies = checker.GetDependencies() + so_dependencies = set() for binary in binaries_by_pkgname[pkgname]: if binary in needed_sonames_by_binary: for soname in needed_sonames_by_binary[binary][NEEDED_SONAMES]: - dependencies.add(pkgs_by_soname[soname]) + if soname in pkgs_by_soname: + so_dependencies.add(pkgs_by_soname[soname]) + else: + orphan_sonames.add(soname) else: logging.warn("%s not found in needed_sonames_by_binary (%s)", binary, needed_sonames_by_binary.keys()) - logging.info("%s depends on %s", pkgname, dependencies) + declared_dependencies_set = set(declared_dependencies) + print "You can consider including the following packages in the dependencies:" + for dep_pkgname in sorted(so_dependencies.difference(declared_dependencies_set)): + print " ", dep_pkgname, + if dep_pkgname.startswith("SUNW"): + print "(it's safe to ignore this one)", + print + + surplus_dependencies = declared_dependencies_set.difference(so_dependencies) + surplus_dependencies = surplus_dependencies.difference(TYPICAL_DEPENDENCIES) + if surplus_dependencies: + print "The following packages might be unnecessary dependencies:" + for dep_pkgname in surplus_dependencies: + print " ", dep_pkgname + if orphan_sonames: + print "The following sonames don't belong to any package:" + for soname in sorted(orphan_sonames): + print " ", soname - # binaries_by_pkgname --> needed_sonames_by_binary --> pkgs_by_soname - # TODO: print per-package deps (requires the transition: pkgname -> soname -> - # pkgname) + if result_ok: + sys.exit(0) + else: + sys.exit(1) - # for lib in `cat $EXTRACTDIR/liblist` ; do - # grep "[/=]$lib[ =]" $EXTRACTDIR/$pkgname/pkgmap - # if [[ $? -eq 0 ]] ; then - # echo $lib provided by package itself - # continue - # else - # grep "[/=]$lib[ =]" $SETLIBS - # if [[ $? -eq 0 ]]; then - # echo "$lib provided by package set being evaluated." - # continue - # fi - # fi - # - # libpkg=`grep /$lib $EXTRACTDIR/shortcatalog | - # sed 's/^.* \([^ ]*\)$/\1/' |sort -u` - # - # if [[ -z "$libpkg" ]] ; then - # echo "$lib $pkgname" >> $SETLIBS.missing - # print Cannot find package providing $lib. Storing for delayed validation. - # else - # print $libpkg | fmt -1 >>$EXTRACTDIR/libpkgs - # fi - # done - # - # sort -u $EXTRACTDIR/libpkgs >$EXTRACTDIR/libpkgs.x - # mv $EXTRACTDIR/libpkgs.x $EXTRACTDIR/libpkgs - # - # diff $EXTRACTDIR/deppkgs $EXTRACTDIR/libpkgs >/dev/null - # if [[ $? -ne 0 ]] ; then - # print SUGGESTION: you may want to add some or all of the following as depends: - # print ' (Feel free to ignore SUNW or SPRO packages)' - # diff $EXTRACTDIR/deppkgs $EXTRACTDIR/libpkgs | fgrep '>' - # fi - # - # - # - # if [[ "$basedir" != "" ]] ; then - # print - # if [[ -f $EXTRACTDIR/elflist ]] ; then - # print "Checking relocation ability..." - # xargs strings < $EXTRACTDIR/elflist| grep /opt/csw - # if [[ $? -eq 0 ]] ; then - # errmsg package build as relocatable, but binaries have hardcoded /opt/csw paths in them - # else - # print trivial check passed - # fi - # else - # echo No relocation check done for non-binary relocatable package. - # fi - # fi - # - # ... - # - # if [ -s $SETLIBS.missing ]; then - # print "Doing late evaluations of package library dependencies." - # while read ldep; do - # lib=`echo $ldep | nawk '{print $1}'` - # [ "$lib" = "libm.so.2" ] && continue - # pkg=`echo $ldep | nawk '{print $2}'` - # /usr/bin/grep "[/=]$lib[ =]" $SETLIBS >/dev/null - # if [ $? -ne 0 ]; then - # errmsg "Couldn't find a package providing $lib" - # else - # print "A package in the set being evaluated provides $lib" - # fi - # done < $SETLIBS.missing - # fi - if __name__ == '__main__': main() Modified: csw/mgar/gar/v2-checkpkg/bin/checkpkg.d/checkpkg.py =================================================================== --- csw/mgar/gar/v2-checkpkg/bin/checkpkg.d/checkpkg.py 2009-12-24 14:01:28 UTC (rev 7740) +++ csw/mgar/gar/v2-checkpkg/bin/checkpkg.d/checkpkg.py 2009-12-24 15:41:02 UTC (rev 7741) @@ -12,6 +12,7 @@ import re SYSTEM_PKGMAP = "/var/sadm/install/contents" +WS_RE = re.compile(r"\s+") class Error(Exception): pass @@ -40,6 +41,9 @@ class CheckpkgBase(object): + """This class has functionality overlapping with DirectoryFormatPackage + from the opencsw.py library. The classes should be merged. + """ def __init__(self, extractdir, pkgname): self.extractdir = extractdir @@ -50,73 +54,92 @@ # ######################################### # # find all executables and dynamic libs,and list their filenames. # listbinaries() { - # if [ ! -d $1 ] ; then - # print errmsg $1 not a directory - # rm -rf $EXTRACTDIR - # exit 1 - # fi + # if [ ! -d $1 ] ; then + # print errmsg $1 not a directory + # rm -rf $EXTRACTDIR + # exit 1 + # fi # - # find $1 -print | xargs file |grep ELF |nawk -F: '{print $1}' + # find $1 -print | xargs file |grep ELF |nawk -F: '{print $1}' # } find_tmpl = "find %s -print | xargs file | grep ELF | nawk -F: '{print $1}'" if not os.path.isdir(self.pkgpath): - raise PackageError("%s does not exist or is not a directory" - % self.pkgpath) + raise PackageError("%s does not exist or is not a directory" + % self.pkgpath) find_proc = subprocess.Popen(find_tmpl % self.pkgpath, shell=True, stdout=subprocess.PIPE) stdout, stderr = find_proc.communicate() ret = find_proc.wait() if ret: - logging.error("The find command returned an error.") + logging.error("The find command returned an error.") return stdout.splitlines() + def GetDependencies(self): + fd = open(os.path.join(self.pkgpath, "install", "depend"), "r") + depends = {} + for line in fd: + fields = re.split(WS_RE, line) + if fields[0] == "P": + depends[fields[1]] = " ".join(fields[1:]) + fd.close() + return depends + + + class SystemPkgmap(object): """A class to hold and manipulate the /var/sadm/install/contents file.""" PICKLE_NAME = "var-sadm-install-contents.pickle" - WS_RE = re.compile(r"\s+") + STOP_PKGS = ["SUNWbcp", "SUNWowbcp", "SUNWucb"] + CHECKPKG_DIR = ".checkpkg" + def __init__(self): """There is no need to re-parse it each time. Read it slowly the first time and cache it for later.""" - self.checkpkg_dir = os.path.join(os.environ["HOME"], ".checkpkg") + self.checkpkg_dir = os.path.join(os.environ["HOME"], self.CHECKPKG_DIR) self.pickle_path = os.path.join(self.checkpkg_dir, self.PICKLE_NAME) if os.path.exists(self.pickle_path): - logging.debug("Unpickling %s, please wait.", self.pickle_path) - pickle_fd = open(self.pickle_path, "r") - self.paths_by_soname = cPickle.load(pickle_fd) - pickle_fd.close() + logging.info("Unpickling %s, this can take up to 30s.", self.pickle_path) + pickle_fd = open(self.pickle_path, "r") + self.pkmap_lines_by_basename = cPickle.load(pickle_fd) + pickle_fd.close() else: # The original checkpkg code to port is in the comments. # # egrep -v 'SUNWbcp|SUNWowbcp|SUNWucb' /var/sadm/install/contents | # fgrep -f $EXTRACTDIR/liblist >$EXTRACTDIR/shortcatalog - stop_pkgs = ["SUNWbcp", "SUNWowbcp", "SUNWucb"] system_pkgmap_fd = open(SYSTEM_PKGMAP, "r") - stop_re = re.compile("(%s)" % "|".join(stop_pkgs)) + stop_re = re.compile("(%s)" % "|".join(self.STOP_PKGS)) # Creating a data structure: # soname - {<path1>: <line1>, <path2>: <line2>, ...} logging.debug("Building in-memory data structure for the %s file", SYSTEM_PKGMAP) - paths_by_soname = {} + pkmap_lines_by_basename = {} for line in system_pkgmap_fd: if stop_re.search(line): continue - fields = re.split(self.WS_RE, line) + fields = re.split(WS_RE, line) pkgmap_entry_path = fields[0].split("=")[0] pkgmap_entry_dir, pkgmap_entry_base_name = os.path.split(pkgmap_entry_path) - if pkgmap_entry_base_name not in paths_by_soname: - paths_by_soname[pkgmap_entry_base_name] = {} - paths_by_soname[pkgmap_entry_base_name][pkgmap_entry_dir] = line + if pkgmap_entry_base_name not in pkmap_lines_by_basename: + pkmap_lines_by_basename[pkgmap_entry_base_name] = {} + pkmap_lines_by_basename[pkgmap_entry_base_name][pkgmap_entry_dir] = line logging.debug("The data structure contains %s files", - len(paths_by_soname)) - self.paths_by_soname = paths_by_soname + len(pkmap_lines_by_basename)) + self.pkmap_lines_by_basename = pkmap_lines_by_basename if not os.path.exists(self.checkpkg_dir): - logging.debug("Creating %s", self.checkpkg_dir) - os.mkdir(self.checkpkg_dir) + logging.debug("Creating %s", self.checkpkg_dir) + os.mkdir(self.checkpkg_dir) logging.debug("Pickling to %s", self.pickle_path) pickle_fd = open(self.pickle_path, "w") - cPickle.dump(self.paths_by_soname, pickle_fd) + cPickle.dump(self.pkmap_lines_by_basename, pickle_fd) pickle_fd.close() + + def GetPkgmapLineByBasename(self, filename): + if filename in self.pkmap_lines_by_basename: + return self.pkmap_lines_by_basename[filename] + else: + raise KeyError, "%s not found in self.pkmap_lines_by_basename" % filename This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. _______________________________________________ devel mailing list devel@lists.opencsw.org https://lists.opencsw.org/mailman/listinfo/devel