[csw-devel] SF.net SVN: gar:[8650] csw/mgar/gar/v2

wahwah at users.sourceforge.net wahwah at users.sourceforge.net
Thu Feb 18 14:20:58 CET 2010


Revision: 8650
          http://gar.svn.sourceforge.net/gar/?rev=8650&view=rev
Author:   wahwah
Date:     2010-02-18 13:20:57 +0000 (Thu, 18 Feb 2010)

Log Message:
-----------
mGAR v2: merging the v2-checkpkg-stats branch back to v2

Modified Paths:
--------------
    csw/mgar/gar/v2/bin/checkpkg
    csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-actionclasses.py
    csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-archall.py
    csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-libs.py
    csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-license.py
    csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-missing-symbols.py
    csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-obsolete-deps.py
    csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-you-can-write-your-own.py
    csw/mgar/gar/v2/bin/update_contents_cache.py
    csw/mgar/gar/v2/gar.conf.mk
    csw/mgar/gar/v2/lib/python/checkpkg.py
    csw/mgar/gar/v2/lib/python/opencsw.py
    csw/mgar/gar/v2/tests/overrides_test.py
    csw/mgar/gar/v2/tests/run_tests.py

Added Paths:
-----------
    csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-basic.py
    csw/mgar/gar/v2/bin/checkpkg_collect_stats.py
    csw/mgar/gar/v2/bin/checkpkg_collect_stats_test.py
    csw/mgar/gar/v2/bin/custom-pkgtrans
    csw/mgar/gar/v2/lib/python/package_checks.py
    csw/mgar/gar/v2/lib/python/package_checks_test.py
    csw/mgar/gar/v2/lib/sh/
    csw/mgar/gar/v2/lib/sh/libcheckpkg.sh

Removed Paths:
-------------
    csw/mgar/gar/v2/lib/sh/libcheckpkg.sh

Property Changed:
----------------
    csw/mgar/gar/v2/
    csw/mgar/gar/v2/pkglib/csw/depend


Property changes on: csw/mgar/gar/v2
___________________________________________________________________
Modified: svn:mergeinfo
   - /csw/mgar/gar/v2:4936-6678
/csw/mgar/gar/v2-checkpkg:7722-7855
/csw/mgar/gar/v2-collapsed-modulations:6895
/csw/mgar/gar/v2-dirpackage:8125-8180
/csw/mgar/gar/v2-migrateconf:7082-7211
/csw/mgar/gar/v2-skayser:6087-6132
   + /csw/mgar/gar/v2:4936-6678
/csw/mgar/gar/v2-checkpkg:7722-7855
/csw/mgar/gar/v2-checkpkg-stats:8454-8649
/csw/mgar/gar/v2-collapsed-modulations:6895
/csw/mgar/gar/v2-dirpackage:8125-8180
/csw/mgar/gar/v2-migrateconf:7082-7211
/csw/mgar/gar/v2-skayser:6087-6132

Modified: csw/mgar/gar/v2/bin/checkpkg
===================================================================
--- csw/mgar/gar/v2/bin/checkpkg	2010-02-18 13:01:38 UTC (rev 8649)
+++ csw/mgar/gar/v2/bin/checkpkg	2010-02-18 13:20:57 UTC (rev 8650)
@@ -21,10 +21,15 @@
 # you know you are tracking the most current version.
 # 
 
-
 PATH=$PATH:/usr/sbin
 readonly NAME_MAX_LENGTH=${NAME_MAX_LENGTH:-20}
 
+command_basename=`basename $0`
+command_basedir="${0%/${command_basename}}"
+libshdir="${command_basedir}/../lib/sh"
+readonly command_basename command_basedir libshdir
+. "${libshdir}/libcheckpkg.sh"
+
 LOCAL_ARCH=`uname -p`
 if [[ -z "${CHECKPKG_TMPDIR}" ]]; then
   readonly CHECKPKG_TMPDIR="/var/tmp"
@@ -44,9 +49,10 @@
 	BOLD=""
 	COLOR_RESET=""
 fi
+readonly GREEN RED BOLD COLOR_RESET
 
 readonly selfpath="$0"
-readonly selfargs="$*"
+readonly selfargs="$@"
 
 # always print out a warning message. (to stderr)
 # exit script, if quit_on_warn set
@@ -124,8 +130,9 @@
 	shift
 fi
 if [[ "$1" == "-h" ]] ; then
-	print 'Usage: checkpkg [-e] pkg1 [pkg2 ....]'
-	print '   -e = "exit on warnings"'
+	print 'Usage: checkpkg [-d] [-e] pkg1 [pkg2 ....]'
+	print '   -d  display debug messages'
+	print '   -e  exit on warnings (soon to be obsolete)'
 	shift
 fi
 
@@ -209,12 +216,6 @@
 basedir=`sed -n 's/^BASEDIR=//p' $TMPFILE`
 pkgarch=`sed -n 's/^ARCH=//p' $TMPFILE|head -1`
 
-case $software in
-     *[A-Z]*)
-	errmsg "$software must be all lowercase"
-	;;
-esac
-
 case `basename $f` in
 	${software}-${version}-*)
 		# file name looks okay
@@ -337,38 +338,9 @@
 #	exit 0
 #fi
 
-
-# This function exists, because pkgtrans is BROKEN!!
-# It leaves a directory in /var/tmp/aaXXXXXXX, even after clean quit
-# SO, emulate pkgtrans behaviour, for "pkgtrans src destdir pkgname"
-#   Except that we ignore pkgname arg, and just do first one we find.
-#  and we are a bit hacky about how we do things.
-pkgtrans(){
-	if [[ ! -d $2 ]] ; then
-		print ERROR: $2 is not a directory >/dev/fd/2
-		return 1
-	fi
-	hdrblks=`(dd if=$1 skip=1 2>/dev/null| cpio -i -t  >/dev/null) 2>&1 |
-		nawk '{print $1; exit;}'`
-
-	## print initial hdrblks=$hdrblks
-
-	hdrblks=$(($hdrblks + 1))
-	mkdir $2/$3 || return 1
-
-	dd if=$1 skip=$hdrblks 2>/dev/null | (cd $2/$3 ; cpio -ivdm)
-	# on fail, SOMETIMES cpio returns 1, but sometimes it returns 0!!
-	if [[ ! -d $2/$3/install ]] ; then
-		print retrying extract with different archive offset...
-		# no, I cant tell in advance why/when the prev fails
-		hdrblks=$(($hdrblks + 1))
-		dd if=$1 skip=$hdrblks 2>/dev/null| (cd $2/$3 ; cpio -ivdm)
-	fi
-}
-
 print ""
 print Extracing pkg for examination of files...
-pkgtrans $f $EXTRACTDIR $pkgname
+custom_pkgtrans $f $EXTRACTDIR $pkgname
 
 #############################################################
 # We now have the package expanded, in "directory" form, in
@@ -566,33 +538,36 @@
 set_variables_for_individual_package_check "$f"
 
 test_suite_ok=1
-checkpkg_scriptname=`basename $0`
-checkpkg_basedir=${0%/${checkpkg_scriptname}}
-plugindir=${checkpkg_basedir}/checkpkg.d
+checkpkg_module_dir=${command_basedir}/checkpkg.d
 checkpkg_module_tag="checkpkg-"
+checkpkg_stats_basedir="${HOME}/.checkpkg/stats"
 
 # Cleaning up old *.pyc files which can cause grief.  This is because of the
 # move of Python libraries.
-for pyc_file in ${plugindir}/opencsw.pyc \
-                ${plugindir}/checkpkg.pyc; do
+for pyc_file in ${checkpkg_module_dir}/opencsw.pyc \
+                ${checkpkg_module_dir}/checkpkg.pyc; do
   if [ -f "${pyc_file}" ]; then
     echo "Removing old pyc file: '${pyc_file}'"
     rm "${pyc_file}"
   fi
 done
 
-# /var/sadm/install/contents cache update
-${checkpkg_basedir}/update_contents_cache.py
-
 if [[ "${DEBUG}" != "" ]]; then
 	extra_options="--debug"
 fi
-debugmsg "plugindir: '$plugindir'"
+
+# /var/sadm/install/contents cache update
+${command_basedir}/update_contents_cache.py
+# Collects package stats to be later analyzed
+${command_basedir}/checkpkg_collect_stats.py ${extra_options} "$@"
+
+debugmsg "checkpkg_module_dir: '$checkpkg_module_dir'"
 log_files=""
 module_name_format="%-40s"
-if [[ -d "$plugindir" ]]; then
-	echo "Running modular tests"
-	for plugin in "${plugindir}/${checkpkg_module_tag}"*; do
+md5sums=`gmd5sum "$@" | awk '{print $1}'`
+if [[ -d "${checkpkg_module_dir}" ]]; then
+	echo "Running modular tests in ${checkpkg_module_dir}"
+	for plugin in "${checkpkg_module_dir}/${checkpkg_module_tag}"*; do
 		if [[ -x "${plugin}" ]]; then
 			plugin_base_name=`basename ${plugin}`
 			plugin_log="${EXTRACTDIR}/${plugin_base_name}.log"
@@ -600,12 +575,12 @@
 			plugin_name="`echo ${plugin} | sed -e 's+.*/checkpkg-++' | sed -e 's+\.py$++'`"
 			error_tag_file="tags.${plugin_name}"
 			printf "${BOLD}${module_name_format}${COLOR_RESET} running..." "${plugin_name}"
-			debugmsg "Executing: ${plugin} $extra_options -e \"${EXTRACTDIR}\" ${pkgnames}"
+			debugmsg "Executing: ${plugin} $extra_options -b \"${checkpkg_stats_basedir}\" -o \"${EXTRACTDIR}/${error_tag_file}\" ${md5sums}"
 			${plugin} \
 				$extra_options \
-				-e "${EXTRACTDIR}" \
+				-b "${checkpkg_stats_basedir}" \
 				-o "${EXTRACTDIR}/${error_tag_file}" \
-				${pkgnames} \
+				${md5sums} \
 				> "${plugin_log}" 2>&1
 			if [[ "$?" -ne 0 ]]; then
 				printf "\r${module_name_format} ${RED}[ERROR]${COLOR_RESET}        \\n" "${plugin_name}"
@@ -618,7 +593,7 @@
 		fi
 	done
 else
-	debugmsg "plugin dir ${plugindir} does not exist"
+	debugmsg "module dir ${checkpkg_module_dir} does not exist"
 fi
 
 for log_file in ${log_files}; do
@@ -653,7 +628,7 @@
 fi
 
 # Collecting errors and applying the overrides.
-${checkpkg_basedir}/analyze_module_results.py \
+${command_basedir}/analyze_module_results.py \
 	-e "${EXTRACTDIR}" \
 	${pkgnames}
 if [[ "$?" -ne 0 ]]; then

Modified: csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-actionclasses.py
===================================================================
--- csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-actionclasses.py	2010-02-18 13:01:38 UTC (rev 8649)
+++ csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-actionclasses.py	2010-02-18 13:20:57 UTC (rev 8650)
@@ -22,18 +22,21 @@
 import opencsw
 
 
-def CheckActionClasses(pkg, debug):
+def CheckActionClasses(pkg_data, debug):
   """Checks the consistency between classes in the prototype and pkginfo."""
   errors = []
-  pkginfo = pkg.GetParsedPkginfo()
-  pkgmap = pkg.GetPkgmap()
+  pkginfo = pkg_data["pkginfo"]
+  pkgmap = pkg_data["pkgmap"]
   pkginfo_classes = set(re.split(opencsw.WS_RE, pkginfo["CLASSES"]))
-  pkgmap_classes = pkgmap.GetClasses()
+  pkgmap_classes = set()
+  for entry in pkgmap:
+    if entry["class"]:  # might be None
+      pkgmap_classes.add(entry["class"])
   only_in_pkginfo = pkginfo_classes.difference(pkgmap_classes)
   only_in_pkgmap = pkgmap_classes.difference(pkginfo_classes)
   for action_class in only_in_pkginfo:
     error = checkpkg.CheckpkgTag(
-        pkg.pkgname,
+        pkg_data["basic_stats"]["pkgname"],
         "action-class-only-in-pkginfo",
         action_class,
         msg="This shouldn't cause any problems, but it might be not necessary.")
@@ -46,10 +49,16 @@
 
 def main():
   options, args = checkpkg.GetOptions()
-  pkgnames = args
+  if options.debug:
+  	logging.basicConfig(level=logging.DEBUG)
+  else:
+  	logging.basicConfig(level=logging.INFO)
+  md5sums = args
+  # CheckpkgManager class abstracts away things such as the collection of
+  # results.
   check_manager = checkpkg.CheckpkgManager(CHECKPKG_MODULE_NAME,
-                                           options.extractdir,
-                                           pkgnames,
+                                           options.stats_basedir,
+                                           md5sums,
                                            options.debug)
   # Registering functions defined above.
   check_manager.RegisterIndividualCheck(CheckActionClasses)

Modified: csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-archall.py
===================================================================
--- csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-archall.py	2010-02-18 13:01:38 UTC (rev 8649)
+++ csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-archall.py	2010-02-18 13:20:57 UTC (rev 8650)
@@ -19,13 +19,14 @@
 
 ARCH_RE = re.compile(r"(sparcv(8|9)|i386|amd64)")
 
-def CheckArchitectureVsContents(pkg, debug):
+def CheckArchitectureVsContents(pkg_data, debug):
   """Verifies the relationship between package contents and architecture."""
   errors = []
-  binaries = pkg.ListBinaries()
-  pkginfo = pkg.GetParsedPkginfo()
+  binaries = pkg_data["binaries"]
+  pkginfo = pkg_data["pkginfo"]
   pkgmap = pkg.GetPkgmap()
   arch = pkginfo["ARCH"]
+  pkgname = pkg_data["basic_stats"]["pkgname"]
   reasons_to_be_arch_specific = []
   for pkgmap_path in pkgmap.entries_by_path:
     # print "pkgmap_path", repr(pkgmap_path), type(pkgmap_path)
@@ -41,13 +42,13 @@
         "package contains binary %s" % binary))
   if arch == "all":
     for tag, param, desc in reasons_to_be_arch_specific:
-      errors.append(checkpkg.CheckpkgTag(pkg.pkgname, tag, param))
+      errors.append(checkpkg.CheckpkgTag(pkgname, tag, param))
   elif not reasons_to_be_arch_specific:
     # This is not a clean way of handling messages for the user, but there's
     # not better way at the moment.
-    print "Package %s does not contain any binaries." % pkg.pkgname
+    print "Package %s does not contain any binaries." % pkgname
     print "Consider making it ARCHALL = 1 instead of %s:" % arch
-    print "ARCHALL_%s = 1" % pkg.pkgname
+    print "ARCHALL_%s = 1" % pkgname
     print ("However, be aware that there might be other reasons "
            "to keep it architecture-specific.")
   return errors
@@ -55,10 +56,12 @@
 
 def main():
   options, args = checkpkg.GetOptions()
-  pkgnames = args
+  md5sums = args
+  # CheckpkgManager class abstracts away things such as the collection of
+  # results.
   check_manager = checkpkg.CheckpkgManager(CHECKPKG_MODULE_NAME,
-                                           options.extractdir,
-                                           pkgnames,
+                                           options.stats_basedir,
+                                           md5sums,
                                            options.debug)
 
   check_manager.RegisterIndividualCheck(CheckArchitectureVsContents)

Copied: csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-basic.py (from rev 8649, csw/mgar/gar/v2-checkpkg-stats/bin/checkpkg.d/checkpkg-basic.py)
===================================================================
--- csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-basic.py	                        (rev 0)
+++ csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-basic.py	2010-02-18 13:20:57 UTC (rev 8650)
@@ -0,0 +1,44 @@
+#!/opt/csw/bin/python2.6
+# $Id: checkpkg-you-can-write-your-own.py 8571 2010-02-16 09:05:51Z wahwah $
+
+"""This is a dummy module. You can use it as a boilerplate for your own modules.
+
+Copy it and modify.
+"""
+
+import os.path
+import sys
+
+CHECKPKG_MODULE_NAME = "basic checks ported from Korn shell"
+
+# The following bit of code sets the correct path to Python libraries
+# distributed with GAR.
+path_list = [os.path.dirname(__file__),
+             "..", "..", "lib", "python"]
+sys.path.append(os.path.join(*path_list))
+import checkpkg
+import package_checks
+
+def main():
+  options, args = checkpkg.GetOptions()
+  md5sums = args
+  # CheckpkgManager class abstracts away things such as the collection of
+  # results.
+  check_manager = checkpkg.CheckpkgManager(CHECKPKG_MODULE_NAME,
+                                           options.stats_basedir,
+                                           md5sums,
+                                           options.debug)
+  # Registering functions defined above.
+  check_manager.RegisterIndividualCheck(package_checks.CatalognameLowercase)
+  check_manager.RegisterIndividualCheck(package_checks.FileNameSanity)
+  # Running the checks, reporting and exiting.
+  exit_code, screen_report, tags_report = check_manager.Run()
+  f = open(options.output, "w")
+  f.write(tags_report)
+  f.close()
+  print screen_report.strip()
+  sys.exit(exit_code)
+
+
+if __name__ == '__main__':
+  main()

Modified: csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-libs.py
===================================================================
--- csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-libs.py	2010-02-18 13:01:38 UTC (rev 8649)
+++ csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-libs.py	2010-02-18 13:20:57 UTC (rev 8650)
@@ -28,69 +28,32 @@
 import checkpkg
 import opencsw
 
-DUMP_BIN = "/usr/ccs/bin/dump"
-
-def GetIsalist():
-  args = ["isalist"]
-  isalist_proc = subprocess.Popen(args, stdout=subprocess.PIPE)
-  stdout, stderr = isalist_proc.communicate()
-  ret = isalist_proc.wait()
-  if ret:
-    logging.error("Calling isalist has failed.")
-  isalist = re.split(r"\s+", stdout.strip())
-  return isalist
-
-
-def CheckSharedLibraryConsistency(pkgs, debug):
+def CheckSharedLibraryConsistency(pkgs_data, debug):
+  ws_re = re.compile(r"\s+")
   result_ok = True
   errors = []
   binaries = []
   binaries_by_pkgname = {}
   sonames_by_pkgname = {}
   pkg_by_any_filename = {}
-  for checker in pkgs:
-    pkg_binary_paths = checker.ListBinaries()
-    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)
-    for filename in checker.GetAllFilenames():
-      pkg_by_any_filename[filename] = checker.pkgname
+  needed_sonames_by_binary = {}
+  filenames_by_soname = {}
+  for pkg_data in pkgs_data:
+    binaries_base = [os.path.basename(x) for x in pkg_data["binaries"]]
+    pkgname = pkg_data["basic_stats"]["pkgname"]
+    binaries_by_pkgname[pkgname] = binaries_base
+    binaries.extend(pkg_data["binaries"])
+    for filename in pkg_data["all_filenames"]:
+      pkg_by_any_filename[filename] = pkgname
+    for binary_data in pkg_data["binaries_dump_info"]:
+      binary_base_name = os.path.basename(binary_data["base_name"])
+      needed_sonames_by_binary[binary_base_name] = binary_data
+      filenames_by_soname[binary_data[checkpkg.SONAME]] = binary_base_name
+    
   # Making the binaries unique
   binaries = set(binaries)
-  ws_re = re.compile(r"\s+")
+  isalist = pkg_data["isalist"]
 
-  # man ld.so.1 for more info on this hack
-  env = copy.copy(os.environ)
-  env["LD_NOAUXFLTR"] = "1"
-  needed_sonames_by_binary = {}
-  filenames_by_soname = {}
-  # Assembling a data structure with the data about binaries.
-  # {
-  #   <binary1 name>: { checkpkg.NEEDED_SONAMES: [...],
-  #                     checkpkg.RUNPATH:        [...]},
-  #   <binary2 name>: ...,
-  #   ...
-  # }
-  #
-  for binary in binaries:
-    binary_base_name = binary.split("/")[-1]
-    args = [DUMP_BIN, "-Lv", binary]
-    dump_proc = subprocess.Popen(args, stdout=subprocess.PIPE, env=env)
-    stdout, stderr = dump_proc.communicate()
-    ret = dump_proc.wait()
-    binary_data = checkpkg.ParseDumpOutput(stdout)
-    needed_sonames_by_binary[binary_base_name] = binary_data
-    if checkpkg.SONAME not in binary_data:
-      logging.debug("The %s binary doesn't provide a SONAME. "
-                    "(It might be an executable)",
-                   binary_base_name)
-      # The shared library doesn't tell its SONAME.  We're guessing it's the
-      # same as the base file name.
-      binary_data[checkpkg.SONAME] = binary_base_name
-    filenames_by_soname[binary_data[checkpkg.SONAME]] = binary_base_name
-
-  isalist = GetIsalist()
-
   # Building indexes by soname to simplify further processing
   # These are indexes "by soname".
   (needed_sonames,
@@ -158,10 +121,9 @@
     print
 
   dependent_pkgs = {}
-  for checker in pkgs:
-    pkgname = checker.pkgname
-    dir_format_pkg = opencsw.DirectoryFormatPackage(checker.pkgpath)
-    declared_dependencies = dir_format_pkg.GetDependencies()
+  for checker in pkgs_data:
+    pkgname = checker["basic_stats"]["pkgname"]
+    declared_dependencies = checker["depends"]
     if debug:
       sanitized_pkgname = pkgname.replace("-", "_")
       data_file_name = "/var/tmp/checkpkg_test_data_%s.py" % sanitized_pkgname
@@ -191,7 +153,7 @@
         filenames_by_soname,
         pkg_by_any_filename)
     namespace = {
-        "pkgname": checker.pkgname,
+        "pkgname": pkgname,
         "missing_deps": missing_deps,
         "surplus_deps": surplus_deps,
         "orphan_sonames": orphan_sonames,
@@ -206,20 +168,22 @@
             "orphan-soname",
             soname))
     for missing_dep in missing_deps:
-    	errors.append(
-    	    checkpkg.CheckpkgTag(
-    	      pkgname,
-    	      "missing-dependency",
-    	      missing_dep))
+      errors.append(
+          checkpkg.CheckpkgTag(
+            pkgname,
+            "missing-dependency",
+            missing_dep))
   return errors
 
 
 def main():
   options, args = checkpkg.GetOptions()
-  pkgnames = args
+  md5sums = args
+  # CheckpkgManager class abstracts away things such as the collection of
+  # results.
   check_manager = checkpkg.CheckpkgManager(CHECKPKG_MODULE_NAME,
-                                           options.extractdir,
-                                           pkgnames,
+                                           options.stats_basedir,
+                                           md5sums,
                                            options.debug)
 
   check_manager.RegisterSetCheck(CheckSharedLibraryConsistency)

Modified: csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-license.py
===================================================================
--- csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-license.py	2010-02-18 13:01:38 UTC (rev 8649)
+++ csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-license.py	2010-02-18 13:20:57 UTC (rev 8650)
@@ -19,16 +19,17 @@
 
 LICENSE_TMPL = "/opt/csw/share/doc/%s/license"
 
-def CheckLicenseFile(pkg, debug):
+def CheckLicenseFile(pkg_data, debug):
   """Checks for the presence of the license file."""
   errors = []
-  pkgmap = pkg.GetPkgmap()
-  catalogname = pkg.GetCatalogname()
+  pkgmap = pkg_data["pkgmap"]
+  catalogname = pkg_data["basic_stats"]["catalogname"]
   license_path = LICENSE_TMPL % catalogname
-  if license_path not in pkgmap.entries_by_path:
+  pkgmap_paths = [x["path"] for x in pkgmap]
+  if license_path not in pkgmap_paths:
     errors.append(
         checkpkg.CheckpkgTag(
-          pkg.pkgname,
+          pkg_data["basic_stats"]["pkgname"],
           "license-missing",
           msg="See http://sourceforge.net/apps/trac/gar/wiki/CopyRight"))
   return errors
@@ -36,10 +37,12 @@
 
 def main():
   options, args = checkpkg.GetOptions()
-  pkgnames = args
+  md5sums = args
+  # CheckpkgManager class abstracts away things such as the collection of
+  # results.
   check_manager = checkpkg.CheckpkgManager(CHECKPKG_MODULE_NAME,
-                                           options.extractdir,
-                                           pkgnames,
+                                           options.stats_basedir,
+                                           md5sums,
                                            options.debug)
   # Registering functions defined above.
   check_manager.RegisterIndividualCheck(CheckLicenseFile)

Modified: csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-missing-symbols.py
===================================================================
--- csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-missing-symbols.py	2010-02-18 13:01:38 UTC (rev 8649)
+++ csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-missing-symbols.py	2010-02-18 13:20:57 UTC (rev 8650)
@@ -22,39 +22,33 @@
 
 # Defining checking functions.
 
-def CheckForMissingSymbols(pkg, debug):
+def CheckForMissingSymbols(pkg_data, debug):
   """Looks for "symbol not found" in ldd -r output."""
   errors = []
-  binaries = pkg.ListBinaries()
+  binaries = pkg_data["binaries"]
   symbol_re = re.compile(r"symbol not found:")
   for binary in binaries:
-    # this could be potentially moved into the DirectoryFormatPackage class.
-    args = ["ldd", "-r", binary]
-    ldd_proc = subprocess.Popen(
-        args,
-        stdout=subprocess.PIPE,
-        stderr=subprocess.PIPE)
-    stdout, stderr = ldd_proc.communicate()
-    retcode = ldd_proc.wait()
-    lines = stdout.splitlines()
+    lines = pkg_data["ldd_dash_r"][binary]
     missing_symbols = False
     for line in lines:
       if re.search(symbol_re, line):
       	missing_symbols = True
     binary_base = os.path.basename(binary)
     if missing_symbols:
-    	errors.append(checkpkg.CheckpkgTag(pkg.pkgname, "symbol-not-found", binary_base))
+    	errors.append(checkpkg.CheckpkgTag(
+    	  pkg_data["basic_stats"]["pkgname"],
+    	  "symbol-not-found", binary_base))
   return errors
 
 
 def main():
   options, args = checkpkg.GetOptions()
-  pkgnames = args
+  md5sums = args
   # CheckpkgManager class abstracts away things such as the collection of
   # results.
   check_manager = checkpkg.CheckpkgManager(CHECKPKG_MODULE_NAME,
-                                           options.extractdir,
-                                           pkgnames,
+                                           options.stats_basedir,
+                                           md5sums,
                                            options.debug)
   # Registering functions defined above.
   check_manager.RegisterIndividualCheck(CheckForMissingSymbols)

Modified: csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-obsolete-deps.py
===================================================================
--- csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-obsolete-deps.py	2010-02-18 13:01:38 UTC (rev 8649)
+++ csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-obsolete-deps.py	2010-02-18 13:20:57 UTC (rev 8650)
@@ -8,6 +8,8 @@
 import os.path
 import sys
 
+CHECKPKG_MODULE_NAME = "obsolete dependencies"
+
 # The following bit of code sets the correct path to Python libraries
 # distributed with GAR.
 path_list = [os.path.dirname(__file__),
@@ -26,10 +28,10 @@
     },
 }
 
-def CheckObsoleteDeps(pkg, debug):
+def CheckObsoleteDeps(pkg_data, debug):
   """Checks for obsolete dependencies."""
   errors = []
-  deps = set(pkg.GetDependencies())
+  deps = set(pkg_data["depends"])
   obsolete_pkg_deps = deps.intersection(set(OBSOLETE_DEPS))
   if obsolete_pkg_deps:
     for obsolete_pkg in obsolete_pkg_deps:
@@ -43,17 +45,20 @@
       if not msg:
         msg = None
       errors.append(
-          checkpkg.CheckpkgTag(pkg.pkgname, "obsolete-dependency",
-                               obsolete_pkg, msg=msg))
+          checkpkg.CheckpkgTag(
+    	      pkg_data["basic_stats"]["pkgname"],
+            "obsolete-dependency", obsolete_pkg, msg=msg))
   return errors
 
 
 def main():
   options, args = checkpkg.GetOptions()
-  pkgnames = args
-  check_manager = checkpkg.CheckpkgManager("obsolete dependencies",
-                                           options.extractdir,
-                                           pkgnames,
+  md5sums = args
+  # CheckpkgManager class abstracts away things such as the collection of
+  # results.
+  check_manager = checkpkg.CheckpkgManager(CHECKPKG_MODULE_NAME,
+                                           options.stats_basedir,
+                                           md5sums,
                                            options.debug)
   check_manager.RegisterIndividualCheck(CheckObsoleteDeps)
   # Running the checks, reporting and exiting.

Modified: csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-you-can-write-your-own.py
===================================================================
--- csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-you-can-write-your-own.py	2010-02-18 13:01:38 UTC (rev 8649)
+++ csw/mgar/gar/v2/bin/checkpkg.d/checkpkg-you-can-write-your-own.py	2010-02-18 13:20:57 UTC (rev 8650)
@@ -21,7 +21,7 @@
 # Defining the checking functions.  They come in two flavors: individual
 # package checks and set checks.
 
-def MyCheckForAsinglePackage(pkg, debug):
+def MyCheckForAsinglePackage(pkg_data, debug):
   """Checks an individual package.
   
   Gets a DirctoryFormatPackage as an argument, and returns a list of errors.
@@ -40,11 +40,13 @@
   # Here's how to report an error:
   something_is_wrong = False
   if something_is_wrong:
-    errors.append(checkpkg.CheckpkgTag(pkg.pkgname, "example-problem", "thing"))
+    errors.append(checkpkg.CheckpkgTag(
+      pkg_data["basic_stats"]["pkgname"],
+      "example-problem", "thing"))
   return errors
 
 
-def MyCheckForAsetOfPackages(pkgs, debug):
+def MyCheckForAsetOfPackages(pkgs_data, debug):
   """Checks a set of packages.
 
   Sometimes individual checks aren't enough. If you need to write code which
@@ -59,12 +61,12 @@
 
 def main():
   options, args = checkpkg.GetOptions()
-  pkgnames = args
+  md5sums = args
   # CheckpkgManager class abstracts away things such as the collection of
   # results.
   check_manager = checkpkg.CheckpkgManager(CHECKPKG_MODULE_NAME,
-                                           options.extractdir,
-                                           pkgnames,
+                                           options.stats_basedir,
+                                           md5sums,
                                            options.debug)
   # Registering functions defined above.
   check_manager.RegisterIndividualCheck(MyCheckForAsinglePackage)

Copied: csw/mgar/gar/v2/bin/checkpkg_collect_stats.py (from rev 8649, csw/mgar/gar/v2-checkpkg-stats/bin/checkpkg_collect_stats.py)
===================================================================
--- csw/mgar/gar/v2/bin/checkpkg_collect_stats.py	                        (rev 0)
+++ csw/mgar/gar/v2/bin/checkpkg_collect_stats.py	2010-02-18 13:20:57 UTC (rev 8650)
@@ -0,0 +1,42 @@
+#!/opt/csw/bin/python2.6
+#
+# $Id$
+#
+# Collects statistics about a package and saves to a directory, for later use
+# by checkpkg modules.
+
+import logging
+import optparse
+import os
+import os.path
+import subprocess
+import sys
+
+# The following bit of code sets the correct path to Python libraries
+# distributed with GAR.
+path_list = [os.path.dirname(__file__),
+             "..", "lib", "python"]
+sys.path.append(os.path.join(*path_list))
+import checkpkg
+import opencsw
+
+
+def main():
+  parser = optparse.OptionParser()
+  parser.add_option("-d", "--debug", dest="debug",
+                    default=False, action="store_true",
+                    help="Turn on debugging messages")
+  options, args = parser.parse_args()
+  if options.debug:
+    logging.basicConfig(level=logging.DEBUG)
+  else:
+    logging.basicConfig(level=logging.INFO)
+  logging.info("Collecting statistics about given package files.")
+  logging.debug("calling: %s, please be patient", args)
+  packages = [opencsw.CswSrv4File(x, options.debug) for x in args]
+  stats_list = [checkpkg.PackageStats(pkg) for pkg in packages]
+  for pkg_stats in stats_list:
+  	pkg_stats.CollectStats()
+
+if __name__ == '__main__':
+	main()

Copied: csw/mgar/gar/v2/bin/checkpkg_collect_stats_test.py (from rev 8649, csw/mgar/gar/v2-checkpkg-stats/bin/checkpkg_collect_stats_test.py)
===================================================================
--- csw/mgar/gar/v2/bin/checkpkg_collect_stats_test.py	                        (rev 0)
+++ csw/mgar/gar/v2/bin/checkpkg_collect_stats_test.py	2010-02-18 13:20:57 UTC (rev 8650)
@@ -0,0 +1,34 @@
+#!/opt/csw/bin/python2.6
+
+import os
+import sys
+import unittest
+import mox
+import checkpkg_collect_stats as ccs
+
+# The following bit of code sets the correct path to Python libraries
+# distributed with GAR.
+path_list = [os.path.dirname(__file__),
+             "..", "lib", "python"]
+sys.path.append(os.path.join(*path_list))
+import checkpkg
+import opencsw
+
+
+class PackageStatsUnitTest(unittest.TestCase):
+
+  def setUp(self):
+    self.mocker = mox.Mox()
+
+  def testGetStatsPath(self):
+    mock_pkg = self.mocker.CreateMock(opencsw.CswSrv4File)
+    mock_pkg.GetMd5sum().AndReturn("abcdef")
+    self.mocker.ReplayAll()
+    sc = ccs.PackageStats(mock_pkg)
+    expected = "/home/joe/.checkpkg/stats/ab/abcdef"
+    self.assertEqual(expected, sc.GetStatsPath("/home/joe"))
+    self.mocker.VerifyAll()
+
+
+if __name__ == '__main__':
+	unittest.main()

Copied: csw/mgar/gar/v2/bin/custom-pkgtrans (from rev 8649, csw/mgar/gar/v2-checkpkg-stats/bin/custom-pkgtrans)
===================================================================
--- csw/mgar/gar/v2/bin/custom-pkgtrans	                        (rev 0)
+++ csw/mgar/gar/v2/bin/custom-pkgtrans	2010-02-18 13:20:57 UTC (rev 8650)
@@ -0,0 +1,22 @@
+#!/bin/ksh -p
+# 
+# $Id$
+#
+# This file exists in order to avoid implementing pipelines in Python.  It
+# could be integrated into the package stats collection program.
+
+command_basename=`basename $0`
+command_basedir="${0%/${command_basename}}"
+libshdir="${command_basedir}/../lib/sh"
+readonly command_basename command_basedir libshdir
+. "${libshdir}/libcheckpkg.sh"
+
+if [[ -z "$1" || -z "$2" || -z "$3" ]]; then
+	print >&2 "usage: $0 <file.pkg> <targetdir> <pkgname>"
+	exit 1
+fi
+if [[ "$3" == "all" ]]; then
+  print >&2 "This script can't handle 'all' as the third argument"
+  exit 1
+fi
+custom_pkgtrans "$1" "$2" "$3"

Modified: csw/mgar/gar/v2/bin/update_contents_cache.py
===================================================================
--- csw/mgar/gar/v2/bin/update_contents_cache.py	2010-02-18 13:01:38 UTC (rev 8649)
+++ csw/mgar/gar/v2/bin/update_contents_cache.py	2010-02-18 13:20:57 UTC (rev 8650)
@@ -12,8 +12,7 @@
 
 # The following bit of code sets the correct path to Python libraries
 # distributed with GAR.
-path_list = [os.getcwd(),
-             os.path.split(sys.argv[0])[0],
+path_list = [os.path.dirname(__file__),
              "..", "lib", "python"]
 sys.path.append(os.path.join(*path_list))
 import checkpkg

Modified: csw/mgar/gar/v2/gar.conf.mk
===================================================================
--- csw/mgar/gar/v2/gar.conf.mk	2010-02-18 13:01:38 UTC (rev 8649)
+++ csw/mgar/gar/v2/gar.conf.mk	2010-02-18 13:20:57 UTC (rev 8650)
@@ -179,6 +179,7 @@
 DEF_BASE_PKGS += CSWgsed
 DEF_BASE_PKGS += CSWgtar
 DEF_BASE_PKGS += CSWpy-cheetah
+DEF_BASE_PKGS += CSWpy-yaml
 DEF_BASE_PKGS += CSWpython
 DEF_BASE_PKGS += CSWtextutils
 DEF_BASE_PKGS += CSWwget

Modified: csw/mgar/gar/v2/lib/python/checkpkg.py
===================================================================
--- csw/mgar/gar/v2/lib/python/checkpkg.py	2010-02-18 13:01:38 UTC (rev 8649)
+++ csw/mgar/gar/v2/lib/python/checkpkg.py	2010-02-18 13:20:57 UTC (rev 8650)
@@ -3,6 +3,9 @@
 # This is the checkpkg library, common for all checkpkg tests written in
 # Python.
 
+import copy
+import cPickle
+import errno
 import itertools
 import logging
 import optparse
@@ -12,6 +15,7 @@
 import socket
 import sqlite3
 import subprocess
+import yaml
 from Cheetah import Template
 import opencsw
 
@@ -24,21 +28,23 @@
 DO_NOT_REPORT_SURPLUS = set([u"CSWcommon", u"CSWcswclassutils", u"CSWisaexec"])
 DO_NOT_REPORT_MISSING = set([])
 DO_NOT_REPORT_MISSING_RE = [r"SUNW.*", r"\*SUNW.*"]
+DUMP_BIN = "/usr/ccs/bin/dump"
 
 SYSTEM_SYMLINKS = (
-    ("/opt/csw/bdb4", ["/opt/csw/bdb42"]),
-    ("/64", ["/amd64", "/sparcv9"]),
+    ("/opt/csw/bdb4",     ["/opt/csw/bdb42"]),
+    ("/64",               ["/amd64", "/sparcv9"]),
     ("/opt/csw/lib/i386", ["/opt/csw/lib"]),
 )
+INSTALL_CONTENTS_AVG_LINE_LENGTH = 102.09710677919261
 
 # This shared library is present on Solaris 10 on amd64, but it's missing on
 # Solaris 8 on i386.  It's okay if it's missing.
 ALLOWED_ORPHAN_SONAMES = set([u"libm.so.2"])
 DEPENDENCY_FILENAME_REGEXES = (
-    (r".*\.pl", u"CSWperl"),
-    (r".*\.pm", u"CSWperl"),
-    (r".*\.py", u"CSWpython"),
-    (r".*\.rb", u"CSWruby"),
+    (r".*\.pl$", u"CSWperl"),
+    (r".*\.pm$", u"CSWperl"),
+    (r".*\.py$", u"CSWpython"),
+    (r".*\.rb$", u"CSWruby"),
 )
 
 REPORT_TMPL = u"""#if $missing_deps or $surplus_deps or $orphan_sonames
@@ -75,7 +81,7 @@
 #end for
 #else
 #if $debug
-OK: $name found no problems.
+OK: $repr($name) module found no problems.
 #end if
 #end if
 """
@@ -106,16 +112,19 @@
 
 def GetOptions():
   parser = optparse.OptionParser()
-  parser.add_option("-e", dest="extractdir",
-                    help="The directory into which the package has been extracted")
+  parser.add_option("-b", dest="stats_basedir",
+                    help=("The base directory with package statistics "
+                          "in yaml format, e.g. ~/.checkpkg/stats"))
   parser.add_option("-d", "--debug", dest="debug",
                     default=False, action="store_true",
                     help="Turn on debugging messages")
   parser.add_option("-o", "--output", dest="output",
                     help="Output error tag file")
   (options, args) = parser.parse_args()
-  if not options.extractdir:
-    raise ConfigurationError("ERROR: -e option is missing.")
+  if not options.stats_basedir:
+    raise ConfigurationError("ERROR: the -b option is missing.")
+  if not options.output:
+    raise ConfigurationError("ERROR: the -o option is missing.")
   # Using set() to make the arguments unique.
   return options, set(args)
 
@@ -199,18 +208,21 @@
         fgrep -f $EXTRACTDIR/liblist >$EXTRACTDIR/shortcatalog
     """
 
+    contents_length = os.stat(SYSTEM_PKGMAP).st_size
+    estimated_lines = contents_length / INSTALL_CONTENTS_AVG_LINE_LENGTH
     system_pkgmap_fd = open(SYSTEM_PKGMAP, "r")
     stop_re = re.compile("(%s)" % "|".join(self.STOP_PKGS))
     # Creating a data structure:
     # soname - {<path1>: <line1>, <path2>: <line2>, ...}
     logging.debug("Building sqlite3 cache db of the %s file",
                   SYSTEM_PKGMAP)
+    print "Processing %s" % SYSTEM_PKGMAP
     c = self.conn.cursor()
     count = itertools.count()
     for line in system_pkgmap_fd:
       i = count.next()
       if not i % 1000:
-        print "\r%s" % i,
+        print "\r~%3.1f%%" % (100.0 * i / estimated_lines,),
       if stop_re.search(line):
         continue
       fields = re.split(WS_RE, line)
@@ -218,7 +230,7 @@
       pkgmap_entry_dir, pkgmap_entry_base_name = os.path.split(pkgmap_entry_path)
       sql = "INSERT INTO systempkgmap (basename, path, line) VALUES (?, ?, ?);"
       c.execute(sql, (pkgmap_entry_base_name, pkgmap_entry_dir, line.strip()))
-    print
+    print "\rAll lines of %s were processed." % SYSTEM_PKGMAP
     print "Creating the main database index."
     sql = "CREATE INDEX basename_idx ON systempkgmap(basename);"
     c.execute(sql)
@@ -280,17 +292,18 @@
     return self.GetFileMtime() <= self.GetDatabaseMtime()
 
   def PurgeDatabase(self):
-    logging.info("Purging the cache database")
     c = self.conn.cursor()
-    sql = "DELETE FROM config;"
-    c.execute(sql)
-    sql = "DELETE FROM systempkgmap;"
-    c.execute(sql)
+    logging.info("Dropping the index.")
     sql = "DROP INDEX basename_idx;"
     try:
       c.execute(sql)
     except sqlite3.OperationalError, e:
       logging.warn(e)
+    logging.info("Deleting all rows from the cache database")
+    sql = "DELETE FROM config;"
+    c.execute(sql)
+    sql = "DELETE FROM systempkgmap;"
+    c.execute(sql)
 
 def SharedObjectDependencies(pkgname,
                              binaries_by_pkgname,
@@ -560,11 +573,11 @@
 class CheckpkgManager(object):
   """Takes care of calling checking functions"""
 
-  def __init__(self, name, extractdir, pkgname_list, debug=False):
+  def __init__(self, name, stats_basedir, md5sum_list, debug=False):
     self.debug = debug
     self.name = name
-    self.extractdir = extractdir
-    self.pkgname_list = pkgname_list
+    self.md5sum_list = md5sum_list
+    self.stats_basedir = stats_basedir
     self.errors = []
     self.individual_checks = []
     self.set_checks = []
@@ -576,23 +589,24 @@
   def RegisterSetCheck(self, function):
     self.set_checks.append(function)
 
-  def GetDirectoryFormatPackages(self):
-    packages = []
-    for pkgname in self.pkgname_list:
-        pkg_path = os.path.join(self.extractdir, pkgname)
-        packages.append(opencsw.DirectoryFormatPackage(pkg_path))
-    return packages
+  def GetPackageStatsList(self):
+    stats_list = []
+    for md5sum in self.md5sum_list:
+      stats_list.append(PackageStats(None, self.stats_basedir, md5sum))
+    return stats_list
 
-  def GetAllTags(self, packages):
+  def GetAllTags(self, packages_data):
     errors = {}
-    for pkg in packages:
+    for pkg_data in packages_data:
       for function in self.individual_checks:
-        errors_for_pkg = function(pkg, debug=self.debug)
+        all_stats = pkg_data.GetAllStats()
+        errors_for_pkg = function(all_stats, debug=self.debug)
         if errors_for_pkg:
-          errors[pkg.pkgname] = errors_for_pkg
+          errors[all_stats["basic_stats"]["pkgname"]] = errors_for_pkg
     # Set checks
     for function in self.set_checks:
-      set_errors = function(packages, debug=self.debug)
+      set_errors = function([x.GetAllStats() for x in packages_data],
+                            debug=self.debug)
       if set_errors:
         # These were generated by a set, but are likely to be bound to specific
         # packages. We'll try to preserve the package assignments.
@@ -624,8 +638,8 @@
 
     Returns a tuple of an exit code and a report.
     """
-    packages = self.GetDirectoryFormatPackages()
-    errors = self.GetAllTags(packages)
+    packages_data = self.GetPackageStatsList()
+    errors = self.GetAllTags(packages_data)
     screen_report, tags_report = self.FormatReports(errors)
     exit_code = 0
     return (exit_code, screen_report, tags_report)
@@ -679,7 +693,6 @@
       basket_b["tag_info"] = tag.tag_info
     basket_a["tag_name"] = self.tag_name
     basket_b["tag_name"] = tag.tag_name
-    # print "comparing", basket_a, basket_b
     return basket_a == basket_b
 
 def ParseOverrideLine(line):
@@ -714,3 +727,234 @@
     if not override_applies:
       tags_after_overrides.append(tag)
   return tags_after_overrides
+
+
+def GetIsalist():
+  args = ["isalist"]
+  isalist_proc = subprocess.Popen(args, stdout=subprocess.PIPE)
+  stdout, stderr = isalist_proc.communicate()
+  ret = isalist_proc.wait()
+  if ret:
+    logging.error("Calling isalist has failed.")
+  isalist = re.split(r"\s+", stdout.strip())
+  return isalist
+
+
+class PackageStats(object):
+  """Collects stats about a package and saves it."""
+  STATS_VERSION = 1L
+  # This list needs to be synchronized with the CollectStats() method.
+  STAT_FILES = [
+      "all_filenames",
+      "basic_stats",
+      "binaries",
+      "binaries_dump_info",
+      "depends",
+      "isalist",
+      "ldd_dash_r",
+      "overrides",
+      "pkginfo",
+      "pkgmap",
+  ]
+
+  def __init__(self, srv4_pkg, stats_basedir=None, md5sum=None):
+    self.srv4_pkg = srv4_pkg
+    self.md5sum = md5sum
+    self.dir_format_pkg = None
+    self.stats_path = None
+    self.all_stats = {}
+    self.stats_basedir = stats_basedir
+    if not self.stats_basedir:
+      home = os.environ["HOME"]
+      parts = [home, ".checkpkg", "stats"]
+      self.stats_basedir = os.path.join(*parts)
+
+  def GetMd5sum(self):
+    if not self.md5sum:
+      self.md5sum = self.srv4_pkg.GetMd5sum()
+    return self.md5sum
+
+  def GetStatsPath(self):
+    if not self.stats_path:
+      md5sum = self.GetMd5sum()
+      two_chars = md5sum[0:2]
+      parts = [self.stats_basedir, two_chars, md5sum]
+      self.stats_path = os.path.join(*parts)
+    return self.stats_path
+
+  def StatsExist(self):
+    """Checks if statistics of a package exist.
+
+    Returns:
+      bool
+    """
+    if not self.StatsDirExists():
+      return False
+    # More checks can be added in the future.
+    return True
+
+  def StatsDirExists(self):
+    return os.path.isdir(self.GetStatsPath())
+
+  def GetDirFormatPkg(self):
+    if not self.dir_format_pkg:
+      self.dir_format_pkg = self.srv4_pkg.GetDirFormatPkg()
+    return self.dir_format_pkg
+
+  def MakeStatsDir(self):
+    """mkdir -p equivalent.
+
+    http://stackoverflow.com/questions/600268/mkdir-p-functionality-in-python
+    """
+    stats_path = self.GetStatsPath()
+    try:
+      os.makedirs(stats_path)
+    except OSError, e:
+      if e.errno == errno.EEXIST:
+        pass
+      else:
+        raise
+
+  def GetBinaryDumpInfo(self):
+    dir_pkg = self.GetDirFormatPkg()
+    # Binaries. This could be split off to a separate function.
+    # man ld.so.1 for more info on this hack
+    env = copy.copy(os.environ)
+    env["LD_NOAUXFLTR"] = "1"
+    binaries_dump_info = []
+    for binary in dir_pkg.ListBinaries():
+      binary_abs_path = os.path.join(dir_pkg.directory, "root", binary)
+      binary_base_name = os.path.basename(binary)
+      args = [DUMP_BIN, "-Lv", binary_abs_path]
+      dump_proc = subprocess.Popen(args, stdout=subprocess.PIPE, env=env)
+      stdout, stderr = dump_proc.communicate()
+      ret = dump_proc.wait()
+      binary_data = ParseDumpOutput(stdout)
+      binary_data["path"] = binary
+      binary_data["soname_guessed"] = False
+      binary_data["base_name"] = binary_base_name
+      if SONAME not in binary_data:
+        logging.debug("The %s binary doesn't provide a SONAME. "
+                      "(It might be an executable)",
+                     binary_base_name)
+        # The binary doesn't tell its SONAME.  We're guessing it's the
+        # same as the base file name.
+        binary_data[SONAME] = binary_base_name
+        binary_data["soname_guessed"] = True
+      binaries_dump_info.append(binary_data)
+    return binaries_dump_info
+
+  def GetBasicStats(self):
+    dir_pkg = self.GetDirFormatPkg()
+    basic_stats = {}
+    basic_stats["stats_version"] = self.STATS_VERSION
+    basic_stats["pkg_path"] = self.srv4_pkg.pkg_path
+    basic_stats["pkg_basename"] = os.path.basename(self.srv4_pkg.pkg_path)
+    basic_stats["parsed_basename"] = opencsw.ParsePackageFileName(basic_stats["pkg_basename"])
+    basic_stats["pkgname"] = dir_pkg.pkgname
+    basic_stats["catalogname"] = dir_pkg.GetCatalogname()
+    return basic_stats
+
+  def GetOverrides(self):
+    dir_pkg = self.GetDirFormatPkg()
+    overrides = dir_pkg.GetOverrides()
+    def OverrideToDict(override):
+      d = {}
+      d["pkgname"] = override.pkgname
+      d["tag_name"] = override.tag_name
+      d["tag_info"] = override.tag_info
+      return d
+    overrides_simple = [OverrideToDict(x) for x in overrides]
+    return overrides_simple
+
+  def GetLddMinusRlines(self):
+    """Returns ldd -r output."""
+    dir_pkg = self.GetDirFormatPkg()
+    binaries = dir_pkg.ListBinaries()
+    ldd_output = {}
+    for binary in binaries:
+      binary_abspath = os.path.join(dir_pkg.directory, "root", binary)
+      # this could be potentially moved into the DirectoryFormatPackage class.
+      # ldd needs the binary to be executable
+      os.chmod(binary_abspath, 0755)
+      args = ["ldd", "-r", binary_abspath]
+      ldd_proc = subprocess.Popen(
+          args,
+          stdout=subprocess.PIPE,
+          stderr=subprocess.PIPE)
+      stdout, stderr = ldd_proc.communicate()
+      retcode = ldd_proc.wait()
+      if retcode:
+        logging.error("%s returned an error: %s", args, stderr)
+      lines = stdout.splitlines()
+      ldd_output[binary] = lines
+    return ldd_output
+
+
+  def CollectStats(self):
+    stats_path = self.GetStatsPath()
+    self.MakeStatsDir()
+    dir_pkg = self.GetDirFormatPkg()
+    logging.info("Collecting %s package statistics.", repr(dir_pkg.pkgname))
+    self.DumpObject(dir_pkg.GetAllFilenames(), "all_filenames")
+    self.DumpObject(self.GetBasicStats(), "basic_stats")
+    self.DumpObject(dir_pkg.ListBinaries(), "binaries")
+    self.DumpObject(self.GetBinaryDumpInfo(), "binaries_dump_info")
+    self.DumpObject(dir_pkg.GetDependencies(), "depends")
+    self.DumpObject(GetIsalist(), "isalist")
+    self.DumpObject(self.GetOverrides(), "overrides")
+    self.DumpObject(dir_pkg.GetParsedPkginfo(), "pkginfo")
+    self.DumpObject(dir_pkg.GetPkgmap().entries, "pkgmap")
+    self.DumpObject(self.GetLddMinusRlines(), "ldd_dash_r")
+    logging.debug("Statistics collected.")
+
+  def GetAllStats(self):
+    if self.StatsExist():
+      self.all_stats = self.ReadSavedStats()
+    else:
+      self.CollectStats()
+    return self.all_stats
+
+  def DumpObject(self, obj, name):
+    """Saves an object.
+
+    TODO(maciej): Implement pickling with cPickle.
+    """
+    stats_path = self.GetStatsPath()
+    # yaml
+    out_file_name = os.path.join(stats_path, "%s.yml" % name)
+    logging.debug("DumpObject(): writing %s", repr(out_file_name))
+    f = open(out_file_name, "w")
+    f.write(yaml.safe_dump(obj))
+    f.close()
+    # pickle
+    out_file_name_pickle = os.path.join(stats_path, "%s.pickle" % name)
+    f = open(out_file_name_pickle, "wb")
+    cPickle.dump(obj, f)
+    f.close()
+    self.all_stats[name] = obj
+
+  def ReadObject(self, name):
+    """Reads an object."""
+    stats_path = self.GetStatsPath()
+    in_file_name = os.path.join(stats_path, "%s.yml" % name)
+    in_file_name_pickle = os.path.join(stats_path, "%s.pickle" % name)
+    if os.path.exists(in_file_name_pickle):
+      logging.debug("ReadObject(): reading %s", repr(in_file_name_pickle))
+      f = open(in_file_name_pickle, "r")
+      obj = cPickle.load(f)
+      f.close()
+      logging.debug("ReadObject(): finished reading %s", repr(in_file_name_pickle))
+    else:
+      logging.debug("ReadObject(): reading %s", repr(in_file_name))
+      f = open(in_file_name, "r")
+      obj = yaml.safe_load(f)
+      f.close()
+      logging.debug("ReadObject(): finished reading %s", repr(in_file_name))
+    return obj
+
+  def ReadSavedStats(self):
+    all_stats = {}
+    for name in self.STAT_FILES:
+      all_stats[name] = self.ReadObject(name)
+    return all_stats

Modified: csw/mgar/gar/v2/lib/python/opencsw.py
===================================================================
--- csw/mgar/gar/v2/lib/python/opencsw.py	2010-02-18 13:01:38 UTC (rev 8649)
+++ csw/mgar/gar/v2/lib/python/opencsw.py	2010-02-18 13:20:57 UTC (rev 8650)
@@ -15,6 +15,7 @@
 import copy
 import datetime
 import difflib
+import hashlib
 import logging
 import os
 import os.path
@@ -347,14 +348,13 @@
   def ShellCommand(self, args, quiet=False):
     logging.debug("Calling: %s", repr(args))
     if quiet:
-      sub_stdout = subprocess.PIPE
-      sub_stderr = subprocess.PIPE
+      process = subprocess.Popen(args,
+                                 stdout=subprocess.PIPE,
+                                 stderr=subprocess.PIPE)
+      stdout, stderr = process.communicate()
+      retcode = process.wait()
     else:
-      sub_stdout = None
-      sub_stderr = None
-    retcode = subprocess.call(args,
-                              stdout=sub_stdout,
-                              stderr=sub_stderr)
+      retcode = subprocess.call(args)
     if retcode:
       raise Error("Running %s has failed." % repr(args))
     return retcode
@@ -363,13 +363,17 @@
 class CswSrv4File(ShellMixin, object):
   """Represents a package in the srv4 format (pkg)."""
 
-  def __init__(self, pkg_path):
+  def __init__(self, pkg_path, debug=False):
     self.pkg_path = pkg_path
     self.workdir = None
     self.gunzipped_path = None
     self.transformed = False
     self.dir_format_pkg = None
+    self.debug = debug
 
+  def __repr__(self):
+    return u"CswSrv4File(%s)" % repr(self.pkg_path)
+
   def GetWorkDir(self):
     if not self.workdir:
       self.workdir = tempfile.mkdtemp(prefix="pkg_")
@@ -399,11 +403,49 @@
                     "%s or %s." % (gzip_suffix, pkg_suffix))
     return self.gunzipped_path
 
+  def Pkgtrans(self, src_file, destdir, pkgname):
+    """A proxy for the pkgtrans command.
+
+    This requires custom-pkgtrans to be available.
+    """
+    if not os.path.isdir(destdir):
+      raise PackageError("%s doesn't exist or is not a directory" % destdir)
+    args = [os.path.join(os.path.dirname(__file__), "custom-pkgtrans"),
+           src_file, destdir, pkgname ]
+    pkgtrans_proc = subprocess.Popen(args)
+    pkgtrans_proc.communicate()
+    ret = pkgtrans_proc.wait()
+    if ret:
+      logging.error("% has failed" % args)
+
+  def GetPkgname(self):
+    """It's necessary to figure out the pkgname from the .pkg file.
+    # nawk 'NR == 2 {print $1; exit;} $f
+    """
+    gunzipped_path = self.GetGunzippedPath()
+    args = ["nawk", "NR == 2 {print $1; exit;}", gunzipped_path]
+    nawk_proc = subprocess.Popen(args, stdout=subprocess.PIPE)
+    stdout, stderr = nawk_proc.communicate()
+    ret_code = nawk_proc.wait()
+    pkgname = stdout.strip()
+    logging.debug("GetPkgname(): %s", repr(pkgname))
+    return pkgname
+
   def TransformToDir(self):
+    """Transforms the file to the directory format.
+
+    This uses the Pkgtrans function at the top, because pkgtrans behaves
+    differently on Solaris 8 and 10.  Having our own implementation helps
+    achieve consistent behavior.
+    """
     if not self.transformed:
-      args = ["pkgtrans", "-a", self.GetAdminFilePath(),
-              self.GetGunzippedPath(), self.GetWorkDir(), "all"]
-      unused_retcode = self.ShellCommand(args, quiet=True)
+      gunzipped_path = self.GetGunzippedPath()
+      pkgname = self.GetPkgname()
+      args = [os.path.join(os.path.dirname(__file__),
+                           "..", "..", "bin", "custom-pkgtrans"),
+              gunzipped_path, self.GetWorkDir(), pkgname]
+      logging.info("transforming: %s", args)
+      unused_retcode = self.ShellCommand(args, quiet=(not self.debug))
       dirs = self.GetDirs()
       if len(dirs) != 1:
         raise Error("Need exactly one package in the package stream: "
@@ -428,6 +470,13 @@
     dir_format_pkg = self.GetDirFormatPkg()
     return dir_format_pkg.GetPkgmap(analyze_permissions, strip)
 
+  def GetMd5sum(self):
+    fp = open(self.pkg_path)
+    hash = hashlib.md5()
+    hash.update(fp.read())
+    fp.close()
+    return hash.hexdigest()
+
   def __del__(self):
     if self.workdir:
       logging.debug("Removing %s", repr(self.workdir))
@@ -537,12 +586,17 @@
 
 
 class DirectoryFormatPackage(ShellMixin, object):
+  """Represents a package in the directory format.
 
+  Allows some read-write operations.
+  """
+
   def __init__(self, directory):
     self.directory = directory
-    self.pkgname = os.path.split(directory)[1]
+    self.pkgname = os.path.basename(directory)
     self.pkgpath = self.directory
     self.pkginfo_dict = None
+    self.binaries = None
 
   def GetCatalogname(self):
     """Returns the catalog name of the package.
@@ -682,16 +736,23 @@
 
     Returns a list of absolute paths.
     """
-    self.CheckPkgpathExists()
-    find_tmpl = "find '%s' -print | xargs file | grep ELF | nawk -F: '{print $1}'"
-    find_proc = subprocess.Popen(find_tmpl % self.directory,
-                                 shell=True,
-                                 stdout=subprocess.PIPE)
-    stdout, stderr = find_proc.communicate()
-    ret = find_proc.wait()
-    if ret:
-      logging.error("The find command returned an error.")
-    return stdout.splitlines()
+    if not self.binaries:
+      self.CheckPkgpathExists()
+      files_root = os.path.join(self.directory, "root")
+      find_tmpl = "find '%s' -print | xargs file | grep ELF | nawk -F: '{print $1}'"
+      find_proc = subprocess.Popen(find_tmpl % ".",
+                                   shell=True,
+                                   stdout=subprocess.PIPE,
+                                   cwd=files_root)
+      stdout, stderr = find_proc.communicate()
+      ret = find_proc.wait()
+      if ret:
+        logging.error("The find command returned an error.")
+      dotslash_re = re.compile(r"^./")
+      def StripRe(x, strip_re):
+        return re.sub(strip_re, "", x)
+      self.binaries = [StripRe(x, dotslash_re) for x in stdout.splitlines()]
+    return self.binaries
 
   def GetAllFilenames(self):
     self.CheckPkgpathExists()
@@ -710,15 +771,15 @@
     # worry about that at this stage.
     logging.debug("Trying to open %s", repr(file_path))
     if os.path.isfile(file_path):
-    	return open(file_path, "r")
+      return open(file_path, "r")
     else:
-    	return None
+      return None
 
   def _ParseOverridesStream(self, stream):
     overrides = []
     for line in stream:
       if line.startswith("#"):
-      	continue
+        continue
       overrides.append(checkpkg.ParseOverrideLine(line))
     return overrides
 
@@ -726,9 +787,9 @@
     """Returns overrides, a list of checkpkg.Override instances."""
     stream = self._GetOverridesStream()
     if stream:
-    	return self._ParseOverridesStream(stream)
+      return self._ParseOverridesStream(stream)
     else:
-    	return list()
+      return list()
 
   def GetFileContent(self, pkg_file_path):
     if pkg_file_path.startswith("/"):
@@ -802,7 +863,7 @@
       if line_to_add:
         self.paths.add(line_to_add)
       entry = {
-          "line": line,
+          "line": line.strip(),
           "type": line_type,
       }
       entry["path"] = installed_path
@@ -892,6 +953,7 @@
       else:
         logging.warn("%s is not a directory.", pkg_path)
 
+
   def Srv4Exists(self, pkg_dir):
     pkg = DirectoryFormatPackage(pkg_dir)
     srv4_name = pkg.GetSrv4FileName()

Copied: csw/mgar/gar/v2/lib/python/package_checks.py (from rev 8649, csw/mgar/gar/v2-checkpkg-stats/lib/python/package_checks.py)
===================================================================
--- csw/mgar/gar/v2/lib/python/package_checks.py	                        (rev 0)
+++ csw/mgar/gar/v2/lib/python/package_checks.py	2010-02-18 13:20:57 UTC (rev 8650)
@@ -0,0 +1,32 @@
+# Defining the checking functions.  They come in two flavors: individual
+# package checks and set checks.
+
+import checkpkg
+import re
+
+def CatalognameLowercase(pkg_data, debug):
+  errors = []
+  # Here's how to report an error:
+  catalogname = pkg_data["basic_stats"]["catalogname"]
+  if catalogname != catalogname.lower():
+    errors.append(checkpkg.CheckpkgTag(
+      pkg_data["basic_stats"]["pkgname"],
+      "catalogname-not-lowercase"))
+  if not re.match(r"^\w+$", catalogname):
+    errors.append(checkpkg.CheckpkgTag(
+      pkg_data["basic_stats"]["pkgname"],
+      "catalogname-is-not-a-simple-word"))
+  return errors
+
+
+def FileNameSanity(pkg_data, debug):
+  errors = []
+  # Here's how to report an error:
+  basic_stats = pkg_data["basic_stats"]
+  revision_info = basic_stats["parsed_basename"]["revision_info"]
+  catalogname = pkg_data["basic_stats"]["catalogname"]
+  if "REV" not in revision_info:
+    errors.append(checkpkg.CheckpkgTag(
+      pkg_data["basic_stats"]["pkgname"],
+      "rev-tag-missing-in-filename"))
+  return errors

Copied: csw/mgar/gar/v2/lib/python/package_checks_test.py (from rev 8649, csw/mgar/gar/v2-checkpkg-stats/lib/python/package_checks_test.py)
===================================================================
--- csw/mgar/gar/v2/lib/python/package_checks_test.py	                        (rev 0)
+++ csw/mgar/gar/v2/lib/python/package_checks_test.py	2010-02-18 13:20:57 UTC (rev 8650)
@@ -0,0 +1,55 @@
+#!/opt/csw/bin/python2.6
+# coding=utf-8
+# $Id$
+
+import unittest
+import package_checks as pc
+
+class PackageChecksUnitTest(unittest.TestCase):
+
+  def setUp(self):
+    self.pkg_data_1 = {
+    	  "basic_stats": {
+    	  	"pkgname": "CSWfoo"
+        }
+    }
+    self.pkg_data_2 = {
+        'basic_stats': {
+          'parsed_basename':
+              {'revision_info': {'REV': '2010.02.15'},
+               'catalogname': 'python_tk',
+               'full_version_string': '2.6.4,REV=2010.02.15',
+               'version': '2.6.4',
+               'version_info': {
+                 'minor version': '6',
+                 'major version': '2',
+                 'patchlevel': '4'}},
+          'pkgname': 'CSWpython-tk',
+          'stats_version': 1,
+          'pkg_basename': 'python_tk-2.6.4,REV=2010.02.15-SunOS5.8-sparc-CSW.pkg.gz',
+          'pkg_path': '/tmp/pkg_lL0HDH/python_tk-2.6.4,REV=2010.02.15-SunOS5.8-sparc-CSW.pkg.gz',
+          'catalogname': 'python_tk'}}
+
+  def testCatalogName_1(self):
+    self.pkg_data_1["basic_stats"]["catalogname"] = "Foo"
+    errors = pc.CatalognameLowercase(self.pkg_data_1, False)
+    self.failUnless(errors)
+
+  def testCatalogName_2(self):
+    self.pkg_data_1["basic_stats"]["catalogname"] = "foo"
+    errors = pc.CatalognameLowercase(self.pkg_data_1, False)
+    self.failIf(errors)
+
+  def testCatalogNameSpecialCharacters(self):
+    self.pkg_data_1["basic_stats"]["catalogname"] = "foo+abc&123"
+    errors = pc.CatalognameLowercase(self.pkg_data_1, False)
+    self.failUnless(errors)
+
+  def testFileNameSanity(self):
+    del(self.pkg_data_2["basic_stats"]["parsed_basename"]["revision_info"]["REV"])
+    errors = pc.FileNameSanity(self.pkg_data_2, False)
+    self.failUnless(errors)
+
+
+if __name__ == '__main__':
+  unittest.main()

Deleted: csw/mgar/gar/v2/lib/sh/libcheckpkg.sh
===================================================================
--- csw/mgar/gar/v2-checkpkg-stats/lib/sh/libcheckpkg.sh	2010-02-18 13:01:38 UTC (rev 8649)
+++ csw/mgar/gar/v2/lib/sh/libcheckpkg.sh	2010-02-18 13:20:57 UTC (rev 8650)
@@ -1,30 +0,0 @@
-#!/bin/ksh -p
-# 
-# $Id$
-
-# pkgtrans leaves a directory in /var/tmp/aaXXXXXXX even after clean quit.
-# Emulating pkgtrans behaviour, for "pkgtrans src destdir pkgname".  Except
-# that the pkgname arg is ignored, and only the first pkg is processed.
-
-custom_pkgtrans(){
-	if [[ ! -d $2 ]] ; then
-		print ERROR: $2 is not a directory >/dev/fd/2
-		return 1
-	fi
-	hdrblks=`(dd if=$1 skip=1 2>/dev/null| cpio -i -t  >/dev/null) 2>&1 |
-		nawk '{print $1; exit;}'`
-
-	## print initial hdrblks=$hdrblks
-
-	hdrblks=$(($hdrblks + 1))
-	mkdir $2/$3 || return 1
-
-	dd if=$1 skip=$hdrblks 2>/dev/null | (cd $2/$3 ; cpio -ivdm)
-	# on fail, SOMETIMES cpio returns 1, but sometimes it returns 0!!
-	if [[ ! -d $2/$3/install ]] ; then
-		print retrying extract with different archive offset...
-		# no, I can't tell in advance why/when the prev fails
-		hdrblks=$(($hdrblks + 1))
-		dd if=$1 skip=$hdrblks 2>/dev/null| (cd $2/$3 ; cpio -ivdm)
-	fi
-}

Copied: csw/mgar/gar/v2/lib/sh/libcheckpkg.sh (from rev 8649, csw/mgar/gar/v2-checkpkg-stats/lib/sh/libcheckpkg.sh)
===================================================================
--- csw/mgar/gar/v2/lib/sh/libcheckpkg.sh	                        (rev 0)
+++ csw/mgar/gar/v2/lib/sh/libcheckpkg.sh	2010-02-18 13:20:57 UTC (rev 8650)
@@ -0,0 +1,30 @@
+#!/bin/ksh -p
+# 
+# $Id$
+
+# pkgtrans leaves a directory in /var/tmp/aaXXXXXXX even after clean quit.
+# Emulating pkgtrans behaviour, for "pkgtrans src destdir pkgname".  Except
+# that the pkgname arg is ignored, and only the first pkg is processed.
+
+custom_pkgtrans(){
+	if [[ ! -d $2 ]] ; then
+		print ERROR: $2 is not a directory >/dev/fd/2
+		return 1
+	fi
+	hdrblks=`(dd if=$1 skip=1 2>/dev/null| cpio -i -t  >/dev/null) 2>&1 |
+		nawk '{print $1; exit;}'`
+
+	## print initial hdrblks=$hdrblks
+
+	hdrblks=$(($hdrblks + 1))
+	mkdir $2/$3 || return 1
+
+	dd if=$1 skip=$hdrblks 2>/dev/null | (cd $2/$3 ; cpio -ivdm)
+	# on fail, SOMETIMES cpio returns 1, but sometimes it returns 0!!
+	if [[ ! -d $2/$3/install ]] ; then
+		print retrying extract with different archive offset...
+		# no, I can't tell in advance why/when the prev fails
+		hdrblks=$(($hdrblks + 1))
+		dd if=$1 skip=$hdrblks 2>/dev/null| (cd $2/$3 ; cpio -ivdm)
+	fi
+}


Property changes on: csw/mgar/gar/v2/pkglib/csw/depend
___________________________________________________________________
Modified: svn:mergeinfo
   - /csw/mgar/gar/v2/pkglib/csw/depend:4936-6678
/csw/mgar/gar/v2-checkpkg/pkglib/csw/depend:7722-7855
/csw/mgar/gar/v2-collapsed-modulations/pkglib/csw/depend:6895
/csw/mgar/gar/v2-dirpackage/pkglib/csw/depend:8125-8180
/csw/mgar/gar/v2-skayser/pkglib/csw/depend:6087-6132
   + /csw/mgar/gar/v2/pkglib/csw/depend:4936-6678
/csw/mgar/gar/v2-checkpkg/pkglib/csw/depend:7722-7855
/csw/mgar/gar/v2-checkpkg-stats/pkglib/csw/depend:8454-8649
/csw/mgar/gar/v2-collapsed-modulations/pkglib/csw/depend:6895
/csw/mgar/gar/v2-dirpackage/pkglib/csw/depend:8125-8180
/csw/mgar/gar/v2-skayser/pkglib/csw/depend:6087-6132

Modified: csw/mgar/gar/v2/tests/overrides_test.py
===================================================================
--- csw/mgar/gar/v2/tests/overrides_test.py	2010-02-18 13:01:38 UTC (rev 8649)
+++ csw/mgar/gar/v2/tests/overrides_test.py	2010-02-18 13:20:57 UTC (rev 8650)
@@ -6,7 +6,7 @@
 sys.path.append("../lib/python")
 import gartest
 
-class OverridesUnitTest(unittest.TestCase):
+class OverridesUnitTest_1(unittest.TestCase):
   """Tests CHECKPKG_OVERRIDES support."""
 
   def testOneOverride(self):
@@ -15,7 +15,7 @@
     mybuild.SetGarVariable("GARNAME", "overrides-test")
     mybuild.SetGarVariable("CATALOGNAME", "overrides_test")
     mybuild.SetGarVariable("CHECKPKG_OVERRIDES",
-                           "CSWoverrides-test|example-tag|example-parameter")
+                           "example-tag|example-parameter")
     mybuild.WriteGarFiles()
     self.assertEquals(0, mybuild.Build())
     pkg = mybuild.GetFirstBuiltPackage()
@@ -32,8 +32,8 @@
     mybuild.SetGarVariable("CATALOGNAME", "overrides_test")
     mybuild.SetGarVariable(
         "CHECKPKG_OVERRIDES",
-        ("CSWoverrides-test|example-tag-1|example-parameter-1 "
-         "CSWoverrides-test|example-tag-2|example-parameter-2"))
+        ("example-tag-1|example-parameter-1 "
+         "example-tag-2|example-parameter-2"))
     mybuild.WriteGarFiles()
     self.assertEquals(0, mybuild.Build())
     pkg = mybuild.GetFirstBuiltPackage()
@@ -43,3 +43,39 @@
     self.assertEqual(expected, pkg.GetFileContent(overr_file))
     overrides = pkg.GetOverrides()
     self.assertEqual(2, len(overrides))
+
+# This bit fails, needs more work.
+#
+# class OverridesUnitTest_2(unittest.TestCase):
+#   """Tests CHECKPKG_OVERRIDES support."""
+# 
+#   def testOverridersForTwoPackages(self):
+#     """http://sourceforge.net/apps/trac/gar/ticket/17"""
+#     overr_file_1 = "/opt/csw/share/checkpkg/overrides/overrides_test_1"
+#     mybuild = gartest.DynamicGarBuild()
+#     mybuild.SetGarVariable("GARNAME", "overrides-test")
+#     mybuild.SetGarVariable("PACKAGES", "CSWoverrides-test-1 "
+#                                        "CSWoverrides-test-2")
+#     mybuild.SetGarVariable("CATALOGNAME_CSWoverrides-test-1",
+#                            "overrides_test_1")
+#     mybuild.SetGarVariable("CATALOGNAME_CSWoverrides-test-2",
+#                            "overrides_test_2")
+#     mybuild.SetGarVariable("SPKG_DESC_CSWoverrides-test-1",
+#                            "Test package 1")
+#     mybuild.SetGarVariable("SPKG_DESC_CSWoverrides-test-1",
+#                            "Test package 2")
+#     mybuild.SetGarVariable("PKGFILES_CSWoverrides-test-1",
+#                            overr_file_1)
+#     mybuild.SetGarVariable(
+#         "CHECKPKG_OVERRIDESCSWoverrides-test-1",
+#         "example-tag-1|example-parameter-1")
+#     mybuild.SetGarVariable(
+#         "CHECKPKG_OVERRIDESCSWoverrides-test-2",
+#         "example-tag-2|example-parameter-2")
+#     mybuild.WriteGarFiles()
+#     self.assertEquals(0, mybuild.Build())
+#     pkg = mybuild.GetFirstBuiltPackage()
+#     expected = ('CSWoverrides-test-1: example-tag-1 example-parameter-1\n')
+#     self.assertEqual(expected, pkg.GetFileContent(overr_file_1))
+#     overrides = pkg.GetOverrides()
+#     self.assertEqual(1, len(overrides))

Modified: csw/mgar/gar/v2/tests/run_tests.py
===================================================================
--- csw/mgar/gar/v2/tests/run_tests.py	2010-02-18 13:01:38 UTC (rev 8649)
+++ csw/mgar/gar/v2/tests/run_tests.py	2010-02-18 13:20:57 UTC (rev 8650)
@@ -10,10 +10,11 @@
 
 # To add more test files, create <name>.py file and add a corresponding line
 # here:
-from opencsw_test   import *
-from checkpkg_test  import *
-from example_test   import *
-from overrides_test import *
+from checkpkg_test       import *
+from example_test        import *
+from opencsw_test        import *
+from overrides_test      import *
+from package_checks_test import *
 
 if __name__ == '__main__':
   unittest.main()


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.


More information about the devel mailing list